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   package org.epics.pvmanager.jca;
6   
7   import org.epics.pvmanager.DataSourceTypeAdapter;
8   import gov.aps.jca.Channel;
9   import gov.aps.jca.dbr.DBR;
10  import gov.aps.jca.dbr.DBRType;
11  import org.epics.pvmanager.ValueCache;
12  
13  /**
14   * Type adapter for JCA data source. Will match a channel based on the value
15   * type provided and the array flag. Will match the cache based on the type class.
16   *
17   * @author carcassi
18   */
19  public abstract class JCATypeAdapter implements DataSourceTypeAdapter<JCAConnectionPayload, JCAMessagePayload> {
20  
21      private final Class<?> typeClass;
22      private final DBRType epicsValueType;
23      private final DBRType epicsMetaType;
24      private final Boolean array;
25  
26      /**
27       * Creates a new type adapter.
28       * 
29       * @param typeClass the java type this adapter will create
30       * @param epicsValueType the epics type used for the monitor
31       * @param epicsMetaType the epics type for the get at connection time; null if no metadata is needed
32       * @param array true whether this will require an array type
33       */
34      public JCATypeAdapter(Class<?> typeClass, DBRType epicsValueType, DBRType epicsMetaType, Boolean array) {
35          this.typeClass = typeClass;
36          this.epicsValueType = epicsValueType;
37          this.epicsMetaType = epicsMetaType;
38          this.array = array;
39      }
40  
41      @Override
42      public int match(ValueCache<?> cache, JCAConnectionPayload connPayload) {
43          Channel channel = connPayload.getChannel();
44          
45          // If the generated type can't be put in the cache, no match
46          if (!cache.getType().isAssignableFrom(typeClass))
47              return 0;
48          
49          // If the type of the channel does not match, no match
50          if (!dbrTypeMatch(epicsValueType, connPayload.getFieldType()))
51              return 0;
52          
53          // If processes array, but count is 1, no match
54          if (array != null &&array && channel.getElementCount() == 1)
55              return 0;
56          
57          // If processes scalar, but the count is not 1, no match
58          if (array != null && !array && channel.getElementCount() != 1)
59              return 0;
60          
61          // Everything matches
62          return 1;
63      }
64      
65      private static boolean dbrTypeMatch(DBRType aType, DBRType anotherType) {
66          if (aType.getClass() == null && anotherType.getClass() != null) {
67              return false;
68          }
69          if (aType.getClass() != null && anotherType.getClass() == null) {
70              return false;
71          }
72          return aType.isBYTE() && anotherType.isBYTE() ||
73                  aType.isDOUBLE() && anotherType.isDOUBLE() ||
74                  aType.isENUM() && anotherType.isENUM() ||
75                  aType.isFLOAT() && anotherType.isFLOAT() ||
76                  aType.isINT() && anotherType.isINT() ||
77                  aType.isSHORT() && anotherType.isSHORT() ||
78                  aType.isSTRING() && anotherType.isSTRING();
79      }
80  
81      @Override
82      public Object getSubscriptionParameter(ValueCache cache, JCAConnectionPayload connPayload) {
83          throw new UnsupportedOperationException("Not implemented: JCAChannelHandler is multiplexed, will not use this method");
84      }
85  
86      @Override
87      @SuppressWarnings("unchecked")
88      public boolean updateCache(ValueCache cache, JCAConnectionPayload connPayload, JCAMessagePayload message) {
89          Channel channel = connPayload.getChannel();
90          
91          // If metadata is required and not present, no update
92          if (epicsMetaType != null && message.getMetadata() == null)
93              return false;
94          
95          // If value is not present, no update
96          if (message.getEvent() == null)
97              return false;
98          
99          Object value = createValue(message.getEvent().getDBR(), message.getMetadata(), connPayload);
100         cache.writeValue(value);
101         return true;
102     }
103 
104     /**
105      * Given the value and the (optional) metadata, will create the new value.
106      * 
107      * @param value the value taken from the monitor
108      * @param metadata the value taken as metadata
109      * @param connPayload the connection payload
110      * @return the new value
111      */
112     public abstract Object createValue(DBR value, DBR metadata, JCAConnectionPayload connPayload);
113     
114 }