/*
* 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.contentdirectory.callback;
import org.teleal.cling.controlpoint.ActionCallback;
import org.teleal.cling.model.action.ActionException;
import org.teleal.cling.model.action.ActionInvocation;
import org.teleal.cling.model.meta.Service;
import org.teleal.cling.model.types.ErrorCode;
import org.teleal.cling.model.types.UnsignedIntegerFourBytes;
import org.teleal.cling.support.contentdirectory.DIDLParser;
import org.teleal.cling.support.model.BrowseFlag;
import org.teleal.cling.support.model.BrowseResult;
import org.teleal.cling.support.model.DIDLContent;
import org.teleal.cling.support.model.SortCriterion;
import java.util.logging.Logger;
/**
* Invokes a "Browse" action, parses the result.
*
* @author Christian Bauer
*/
public abstract class Browse extends ActionCallback {
public static final String CAPS_WILDCARD = "*";
public enum Status {
NO_CONTENT("No Content"),
LOADING("Loading..."),
OK("OK");
private String defaultMessage;
Status(String defaultMessage) {
this.defaultMessage = defaultMessage;
}
public String getDefaultMessage() {
return defaultMessage;
}
}
private static Logger log = Logger.getLogger(Browse.class.getName());
/**
* Browse with first result 0 and {@link #getDefaultMaxResults()}, filters with {@link #CAPS_WILDCARD}.
*/
public Browse(Service service, String containerId, BrowseFlag flag) {
this(service, containerId, flag, CAPS_WILDCARD, 0, null);
}
/**
* @param maxResults Can be <code>null</code>, then {@link #getDefaultMaxResults()} is used.
*/
public Browse(Service service, String objectID, BrowseFlag flag,
String filter, long firstResult, Long maxResults, SortCriterion... orderBy) {
super(new ActionInvocation(service.getAction("Browse")));
log.fine("Creating browse action for object ID: " + objectID);
getActionInvocation().setInput("ObjectID", objectID);
getActionInvocation().setInput("BrowseFlag", flag.toString());
getActionInvocation().setInput("Filter", filter);
getActionInvocation().setInput("StartingIndex", new UnsignedIntegerFourBytes(firstResult));
getActionInvocation().setInput("RequestedCount",
new UnsignedIntegerFourBytes(maxResults == null ? getDefaultMaxResults() : maxResults)
);
getActionInvocation().setInput("SortCriteria", SortCriterion.toString(orderBy));
}
@Override
public void run() {
updateStatus(Status.LOADING);
super.run();
}
public void success(ActionInvocation invocation) {
log.fine("Successful browse action, reading output argument values");
BrowseResult result = new BrowseResult(
invocation.getOutput("Result").getValue().toString(),
(UnsignedIntegerFourBytes) invocation.getOutput("NumberReturned").getValue(),
(UnsignedIntegerFourBytes) invocation.getOutput("TotalMatches").getValue(),
(UnsignedIntegerFourBytes) invocation.getOutput("UpdateID").getValue()
);
boolean proceed = receivedRaw(invocation, result);
if (proceed && result.getCountLong() > 0 && result.getResult().length() > 0) {
try {
DIDLParser didlParser = new DIDLParser();
DIDLContent didl = didlParser.parse(result.getResult());
received(invocation, didl);
updateStatus(Status.OK);
} catch (Exception ex) {
invocation.setFailure(
new ActionException(ErrorCode.ACTION_FAILED, "Can't parse DIDL XML response: " + ex, ex)
);
failure(invocation, null);
}
} else {
received(invocation, new DIDLContent());
updateStatus(Status.NO_CONTENT);
}
}
/**
* Some media servers will crash if there is no limit on the maximum number of results.
*
* @return The default limit, 999.
*/
public long getDefaultMaxResults() {
return 999;
}
public boolean receivedRaw(ActionInvocation actionInvocation, BrowseResult browseResult) {
/*
if (log.isLoggable(Level.FINER)) {
log.finer("-------------------------------------------------------------------------------------");
log.finer("\n" + XML.pretty(browseResult.getDidl()));
log.finer("-------------------------------------------------------------------------------------");
}
*/
return true;
}
public abstract void received(ActionInvocation actionInvocation, DIDLContent didl);
public abstract void updateStatus(Status status);
}