/*
* Copyright (C) 2010 Teleal GmbH, Switzerland
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.teleal.cling.support.lastchange;
import org.teleal.cling.model.types.UnsignedIntegerFourBytes;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Collects all state changes per logical instance.
* <p>
* This class is supposed to be used on a UPnP state variable field,
* on a RenderingControl or AVTransport service. The service then
* sets evented values whenever its state changes, and periodically
* (e.g. in a background loop) fires the "LastChange" XML content
* through its PropertyChangeSupport. (Where the ServiceManager picks
* it up and sends it to all subscribers.)
* </p>
* <p>
* The event subscriber can use this class to marshall the "LastChange"
* content, when the event XML is received.
* </p>
* <p>
* This class is thread-safe.
* </p>
*
* @author Christian Bauer
*/
public class LastChange {
final private Event event;
final private LastChangeParser parser;
private String previousValue;
public LastChange(String s) {
throw new UnsupportedOperationException("This constructor is only for service binding detection");
}
public LastChange(LastChangeParser parser, Event event) {
this.parser = parser;
this.event = event;
}
public LastChange(LastChangeParser parser) {
this(parser, new Event());
}
public LastChange(LastChangeParser parser, String xml) throws Exception {
if (xml != null && xml.length() > 0) {
this.event = parser.parse(xml);
} else {
this.event = new Event();
}
this.parser = parser;
}
synchronized public void reset() {
previousValue = toString();
event.clear();
}
synchronized public void setEventedValue(int instanceID, EventedValue... ev) {
setEventedValue(new UnsignedIntegerFourBytes(instanceID), ev);
}
synchronized public void setEventedValue(UnsignedIntegerFourBytes instanceID, EventedValue... ev) {
for (EventedValue eventedValue : ev) {
if (eventedValue != null)
event.setEventedValue(instanceID, eventedValue);
}
}
synchronized public UnsignedIntegerFourBytes[] getInstanceIDs() {
List<UnsignedIntegerFourBytes> list = new ArrayList();
for (InstanceID instanceID : event.getInstanceIDs()) {
list.add(instanceID.getId());
}
return list.toArray(new UnsignedIntegerFourBytes[list.size()]);
}
synchronized EventedValue[] getEventedValues(UnsignedIntegerFourBytes instanceID) {
InstanceID inst = event.getInstanceID(instanceID);
return inst != null ? inst.getValues().toArray(new EventedValue[inst.getValues().size()]) : null;
}
synchronized public <EV extends EventedValue> EV getEventedValue(int instanceID, Class<EV> type) {
return getEventedValue(new UnsignedIntegerFourBytes(instanceID), type);
}
synchronized public <EV extends EventedValue> EV getEventedValue(UnsignedIntegerFourBytes id, Class<EV> type) {
return event.getEventedValue(id, type);
}
synchronized public void fire(PropertyChangeSupport propertyChangeSupport) {
String lastChanges = toString();
if (lastChanges != null && lastChanges.length() > 0) {
propertyChangeSupport.firePropertyChange("LastChange", previousValue, lastChanges);
reset();
}
}
@Override
synchronized public String toString() {
if (!event.hasChanges()) return "";
try {
return parser.generate(event);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}