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  
16  package org.fourthline.cling.support.lastchange;
17  
18  import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
19  
20  import java.beans.PropertyChangeSupport;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  /**
25   * Collects all state changes per logical instance.
26   * <p>
27   * This class is supposed to be used on a UPnP state variable field,
28   * on a RenderingControl or AVTransport service. The service then
29   * sets evented values whenever its state changes, and periodically
30   * (e.g. in a background loop) fires the "LastChange" XML content
31   * through its PropertyChangeSupport. (Where the ServiceManager picks
32   * it up and sends it to all subscribers.)
33   * </p>
34   * <p>
35   * The event subscriber can use this class to marshall the "LastChange"
36   * content, when the event XML is received.
37   * </p>
38   * <p>
39   * This class is thread-safe.
40   * </p>
41   *
42   * @author Christian Bauer
43   */
44  public class LastChange {
45  
46      final private Event event;
47      final private LastChangeParser parser;
48      private String previousValue;
49  
50      public LastChange(String s) {
51          throw new UnsupportedOperationException("This constructor is only for service binding detection");
52      }
53  
54      public LastChange(LastChangeParser parser, Event event) {
55          this.parser = parser;
56          this.event = event;
57      }
58  
59      public LastChange(LastChangeParser parser) {
60          this(parser, new Event());
61      }
62  
63      public LastChange(LastChangeParser parser, String xml) throws Exception {
64          if (xml != null && xml.length() > 0) {
65              this.event = parser.parse(xml);
66          } else {
67              this.event = new Event();
68          }
69          this.parser = parser;
70      }
71  
72      synchronized public void reset() {
73          previousValue = toString();
74          event.clear();
75      }
76  
77      synchronized public void setEventedValue(int instanceID, EventedValue... ev) {
78          setEventedValue(new UnsignedIntegerFourBytes(instanceID), ev);
79      }
80  
81      synchronized public void setEventedValue(UnsignedIntegerFourBytes instanceID, EventedValue... ev) {
82          for (EventedValue eventedValue : ev) {
83              if (eventedValue != null)
84                  event.setEventedValue(instanceID, eventedValue);
85  
86          }
87      }
88  
89      synchronized public UnsignedIntegerFourBytes[] getInstanceIDs() {
90          List<UnsignedIntegerFourBytes> list = new ArrayList<>();
91          for (InstanceID instanceID : event.getInstanceIDs()) {
92              list.add(instanceID.getId());
93          }
94          return list.toArray(new UnsignedIntegerFourBytes[list.size()]);
95      }
96  
97      synchronized EventedValue[] getEventedValues(UnsignedIntegerFourBytes instanceID) {
98          InstanceID inst = event.getInstanceID(instanceID);
99          return inst != null ? inst.getValues().toArray(new EventedValue[inst.getValues().size()]) : null;
100     }
101 
102     synchronized public <EV extends EventedValue> EV getEventedValue(int instanceID, Class<EV> type) {
103         return getEventedValue(new UnsignedIntegerFourBytes(instanceID), type);
104     }
105 
106     synchronized public <EV extends EventedValue> EV getEventedValue(UnsignedIntegerFourBytes id, Class<EV> type) {
107         return event.getEventedValue(id, type);
108     }
109 
110     synchronized public void fire(PropertyChangeSupport propertyChangeSupport) {
111         String lastChanges = toString();
112         if (lastChanges != null && lastChanges.length() > 0) {
113             propertyChangeSupport.firePropertyChange("LastChange", previousValue, lastChanges);
114             reset();
115         }
116     }
117 
118     @Override
119     synchronized public String toString() {
120         if (!event.hasChanges()) return "";
121         try {
122             return parser.generate(event);
123         } catch (Exception ex) {
124             throw new RuntimeException(ex);
125         }
126     }
127 }