1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.support.contentdirectory.callback;
17
18 import org.fourthline.cling.controlpoint.ActionCallback;
19 import org.fourthline.cling.model.action.ActionException;
20 import org.fourthline.cling.model.action.ActionInvocation;
21 import org.fourthline.cling.model.meta.Service;
22 import org.fourthline.cling.model.types.ErrorCode;
23 import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
24 import org.fourthline.cling.support.contentdirectory.DIDLParser;
25 import org.fourthline.cling.support.model.DIDLContent;
26 import org.fourthline.cling.support.model.SearchResult;
27 import org.fourthline.cling.support.model.SortCriterion;
28
29 import java.util.logging.Logger;
30
31
32
33
34
35
36 public abstract class Search extends ActionCallback {
37
38 public static final String CAPS_WILDCARD = "*";
39
40 public enum Status {
41 NO_CONTENT("No Content"),
42 LOADING("Loading..."),
43 OK("OK");
44
45 private String defaultMessage;
46
47 Status(String defaultMessage) {
48 this.defaultMessage = defaultMessage;
49 }
50
51 public String getDefaultMessage() {
52 return this.defaultMessage;
53 }
54 }
55
56 private static Logger log = Logger.getLogger(Search.class.getName());
57
58
59
60
61 public Search(Service service, String containerId, String searchCriteria) {
62 this(service, containerId, searchCriteria, CAPS_WILDCARD, 0, null);
63 }
64
65
66
67
68 public Search(Service service, String containerId, String searchCriteria, String filter,
69 long firstResult, Long maxResults, SortCriterion... orderBy) {
70 super(new ActionInvocation(service.getAction("Search")));
71
72 log.fine("Creating browse action for container ID: " + containerId);
73
74 getActionInvocation().setInput("ContainerID", containerId);
75 getActionInvocation().setInput("SearchCriteria", searchCriteria);
76 getActionInvocation().setInput("Filter", filter);
77 getActionInvocation().setInput("StartingIndex", new UnsignedIntegerFourBytes(firstResult));
78 getActionInvocation().setInput(
79 "RequestedCount",
80 new UnsignedIntegerFourBytes(maxResults == null ? getDefaultMaxResults() : maxResults)
81 );
82 getActionInvocation().setInput("SortCriteria", SortCriterion.toString(orderBy));
83 }
84
85 @Override
86 public void run() {
87 updateStatus(Status.LOADING);
88 super.run();
89 }
90
91 @Override
92 public void success(ActionInvocation actionInvocation) {
93 log.fine("Successful search action, reading output argument values");
94
95 SearchResult result = new SearchResult(
96 actionInvocation.getOutput("Result").getValue().toString(),
97 (UnsignedIntegerFourBytes) actionInvocation.getOutput("NumberReturned").getValue(),
98 (UnsignedIntegerFourBytes) actionInvocation.getOutput("TotalMatches").getValue(),
99 (UnsignedIntegerFourBytes) actionInvocation.getOutput("UpdateID").getValue());
100
101 boolean proceed = receivedRaw(actionInvocation, result);
102
103 if (proceed && result.getCountLong() > 0 && result.getResult().length() > 0) {
104 try {
105 DIDLParser didlParser = new DIDLParser();
106 DIDLContent didl = didlParser.parse(result.getResult());
107 received(actionInvocation, didl);
108 updateStatus(Status.OK);
109 } catch (Exception ex) {
110 actionInvocation.setFailure(
111 new ActionException(ErrorCode.ACTION_FAILED, "Can't parse DIDL XML response: " + ex, ex)
112 );
113 failure(actionInvocation, null);
114 }
115 } else {
116 received(actionInvocation, new DIDLContent());
117 updateStatus(Status.NO_CONTENT);
118 }
119 }
120
121
122
123
124
125
126 public Long getDefaultMaxResults() {
127 return 999L;
128 }
129
130 public boolean receivedRaw(ActionInvocation actionInvocation, SearchResult searchResult) {
131 return true;
132 }
133
134 public abstract void received(ActionInvocation actionInvocation, DIDLContent didl);
135
136 public abstract void updateStatus(Status status);
137 }