View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  package example.localservice;
16  
17  import org.fourthline.cling.binding.annotations.*;
18  
19  /**
20   * Mapping state variables
21   * <p>
22   * The following example only has a single field named <code>power</code>,
23   * however, the UPnP service requires two state variables. In this case
24   * you declare the UPnP state variables with annotations on the class:
25   * </p>
26   * <a class="citation" href="javacode://this" style="include:INC1"/>
27   * <p>
28   * The <code>power</code> field is not mapped to the state variables and
29   * you are free to design your service internals as you like. Did you
30   * notice that you never declared the datatype of your state variables?
31   * Also, how can Cling read the "current state" of your service for GENA
32   * subscribers or when a "query state variable" action is received?
33   * Both questions have the same answer.
34   * </p>
35   * <p>
36   * Let's consider GENA eventing first. This example has an evented
37   * state variable called <code>Status</code>, and if a control point
38   * subscribes to the service to be notified of changes, how
39   * will Cling obtain the current status? If you'd have used
40   * <code>@UpnpStateVariable</code> on your fields, Cling would then
41   * directly access field values through Java Reflection. On the other
42   * hand if you declare state variables not on fields but on your service
43   * class, Cling will during binding detect any JavaBean-style getter
44   * method that matches the derived property name of the state variable.
45   * </p>
46   * <p>
47   * In other words, Cling will discover that your class has a
48   * <code>getStatus()</code> method. It doesn't matter if that method
49   * is also an action-mapped method, the important thing is that it
50   * matches JavaBean property naming conventions. The <code>Status</code>
51   * UPnP state variable maps to the <code>status</code> property, which
52   * is expected to have a <code>getStatus()</code> accessor method.
53   * Cling will use this method to read the current state of your
54   * service for GENA subscribers and when the state variable is
55   * manually queried.
56   * </p>
57   * <p>
58   * If you do not provide a UPnP datatype name in your
59   * <code>@UpnpStateVariable</code> annotation, Cling will use the type
60   * of the annotated field or discovered JavaBean getter method to
61   * figure out the type. The supported default mappings between Java types
62   * and UPnP datatypes are shown in the following table:
63   * </p>
64   * <table class="infotable halfwidth" border="1">
65   * <thead><tr>
66   * <th>Java Type</th>
67   * <th class="halfwidth">UPnP Datatype</th>
68   * </tr></thead>
69   * <tbody>
70   * <tr><td><code>java.lang.Boolean</code></td><td><code>boolean</code></td></tr>
71   * <tr><td><code>boolean</code></td><td><code>boolean</code></td></tr>
72   * <tr><td><code>java.lang.Short</code></td><td><code>i2</code></td></tr>
73   * <tr><td><code>short</code></td><td><code>i2</code></td></tr>
74   * <tr><td><code>java.lang.Integer</code></td><td><code>i4</code></td></tr>
75   * <tr><td><code>int</code></td><td><code>i4</code></td></tr>
76   * <tr><td><code>org.fourthline.cling.model.types.UnsignedIntegerOneByte</code></td><td><code>ui1</code></td></tr>
77   * <tr><td><code>org.fourthline.cling.model.types.UnsignedIntegerTwoBytes</code></td><td><code>ui2</code></td></tr>
78   * <tr><td><code>org.fourthline.cling.model.types.UnsignedIntegerFourBytes</code></td><td><code>ui4</code></td></tr>
79   * <tr><td><code>java.lang.Float</code></td><td><code>r4</code></td></tr>
80   * <tr><td><code>float</code></td><td><code>r4</code></td></tr>
81   * <tr><td><code>java.lang.Double</code></td><td><code>float</code></td></tr>
82   * <tr><td><code>double</code></td><td><code>float</code></td></tr>
83   * <tr><td><code>java.lang.Character</code></td><td><code>char</code></td></tr>
84   * <tr><td><code>char</code></td><td><code>char</code></td></tr>
85   * <tr><td><code>java.lang.String</code></td><td><code>string</code></td></tr>
86   * <tr><td><code>java.util.Calendar</code></td><td><code>datetime</code></td></tr>
87   * <tr><td><code>byte[]</code></td><td><code>bin.base64</code></td></tr>
88   * <tr><td><code>java.net.URI</code></td><td><code>uri</code></td></tr>
89   * </tbody>
90   * </table>
91   *
92   */
93  @UpnpService(                                                                   // DOC:INC1
94          serviceId = @UpnpServiceId("SwitchPower"),
95          serviceType = @UpnpServiceType(value = "SwitchPower", version = 1)
96  
97  )
98  @UpnpStateVariables(
99          {
100                 @UpnpStateVariable(
101                         name = "Target",
102                         defaultValue = "0",
103                         sendEvents = false
104                 ),
105                 @UpnpStateVariable(
106                         name = "Status",
107                         defaultValue = "0"
108                 )
109         }
110 )
111 public class SwitchPowerAnnotatedClass {
112 
113     private boolean power;
114 
115     @UpnpAction
116     public void setTarget(@UpnpInputArgument(name = "NewTargetValue")
117                           boolean newTargetValue) {
118         power = newTargetValue;
119         System.out.println("Switch is: " + power);
120     }
121 
122     @UpnpAction(out = @UpnpOutputArgument(name = "RetTargetValue"))
123     public boolean getTarget() {
124         return power;
125     }
126 
127     @UpnpAction(out = @UpnpOutputArgument(name = "ResultStatus"))
128     public boolean getStatus() {
129         return power;
130     }
131 }                                                                               // DOC:INC1