1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.fourthline.cling.support.contentdirectory;
16
17 import org.fourthline.cling.binding.annotations.UpnpAction;
18 import org.fourthline.cling.binding.annotations.UpnpInputArgument;
19 import org.fourthline.cling.binding.annotations.UpnpOutputArgument;
20 import org.fourthline.cling.binding.annotations.UpnpService;
21 import org.fourthline.cling.binding.annotations.UpnpServiceId;
22 import org.fourthline.cling.binding.annotations.UpnpServiceType;
23 import org.fourthline.cling.binding.annotations.UpnpStateVariable;
24 import org.fourthline.cling.binding.annotations.UpnpStateVariables;
25 import org.fourthline.cling.model.types.ErrorCode;
26 import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
27 import org.fourthline.cling.model.types.csv.CSV;
28 import org.fourthline.cling.model.types.csv.CSVString;
29 import org.fourthline.cling.support.model.BrowseFlag;
30 import org.fourthline.cling.support.model.BrowseResult;
31 import org.fourthline.cling.support.model.DIDLContent;
32 import org.fourthline.cling.support.model.SortCriterion;
33
34 import java.beans.PropertyChangeSupport;
35 import java.util.ArrayList;
36 import java.util.List;
37
38
39
40
41
42
43
44
45
46
47
48
49 @UpnpService(
50 serviceId = @UpnpServiceId("ContentDirectory"),
51 serviceType = @UpnpServiceType(value = "ContentDirectory", version = 1)
52 )
53
54 @UpnpStateVariables({
55 @UpnpStateVariable(
56 name = "A_ARG_TYPE_ObjectID",
57 sendEvents = false,
58 datatype = "string"),
59 @UpnpStateVariable(
60 name = "A_ARG_TYPE_Result",
61 sendEvents = false,
62 datatype = "string"),
63 @UpnpStateVariable(
64 name = "A_ARG_TYPE_BrowseFlag",
65 sendEvents = false,
66 datatype = "string",
67 allowedValuesEnum = BrowseFlag.class),
68 @UpnpStateVariable(
69 name = "A_ARG_TYPE_Filter",
70 sendEvents = false,
71 datatype = "string"),
72 @UpnpStateVariable(
73 name = "A_ARG_TYPE_SortCriteria",
74 sendEvents = false,
75 datatype = "string"),
76 @UpnpStateVariable(
77 name = "A_ARG_TYPE_Index",
78 sendEvents = false,
79 datatype = "ui4"),
80 @UpnpStateVariable(
81 name = "A_ARG_TYPE_Count",
82 sendEvents = false,
83 datatype = "ui4"),
84 @UpnpStateVariable(
85 name = "A_ARG_TYPE_UpdateID",
86 sendEvents = false,
87 datatype = "ui4"),
88 @UpnpStateVariable(
89 name = "A_ARG_TYPE_URI",
90 sendEvents = false,
91 datatype = "uri"),
92 @UpnpStateVariable(
93 name = "A_ARG_TYPE_SearchCriteria",
94 sendEvents = false,
95 datatype = "string")
96 })
97 public abstract class AbstractContentDirectoryService {
98
99 public static final String CAPS_WILDCARD = "*";
100
101 @UpnpStateVariable(sendEvents = false)
102 final private CSV<String> searchCapabilities;
103
104 @UpnpStateVariable(sendEvents = false)
105 final private CSV<String> sortCapabilities;
106
107 @UpnpStateVariable(
108 sendEvents = true,
109 defaultValue = "0",
110 eventMaximumRateMilliseconds = 200
111 )
112 private UnsignedIntegerFourBytes systemUpdateID = new UnsignedIntegerFourBytes(0);
113
114 final protected PropertyChangeSupport propertyChangeSupport;
115
116 protected AbstractContentDirectoryService() {
117 this(new ArrayList<String>(), new ArrayList<String>(), null);
118 }
119
120 protected AbstractContentDirectoryService(List<String> searchCapabilities, List<String> sortCapabilities) {
121 this(searchCapabilities, sortCapabilities, null);
122 }
123
124 protected AbstractContentDirectoryService(List<String> searchCapabilities, List<String> sortCapabilities,
125 PropertyChangeSupport propertyChangeSupport) {
126 this.propertyChangeSupport = propertyChangeSupport != null ? propertyChangeSupport : new PropertyChangeSupport(this);
127 this.searchCapabilities = new CSVString();
128 this.searchCapabilities.addAll(searchCapabilities);
129 this.sortCapabilities = new CSVString();
130 this.sortCapabilities.addAll(sortCapabilities);
131 }
132
133 @UpnpAction(out = @UpnpOutputArgument(name = "SearchCaps"))
134 public CSV<String> getSearchCapabilities() {
135 return searchCapabilities;
136 }
137
138 @UpnpAction(out = @UpnpOutputArgument(name = "SortCaps"))
139 public CSV<String> getSortCapabilities() {
140 return sortCapabilities;
141 }
142
143 @UpnpAction(out = @UpnpOutputArgument(name = "Id"))
144 synchronized public UnsignedIntegerFourBytes getSystemUpdateID() {
145 return systemUpdateID;
146 }
147
148 public PropertyChangeSupport getPropertyChangeSupport() {
149 return propertyChangeSupport;
150 }
151
152
153
154
155
156
157
158
159 synchronized protected void changeSystemUpdateID() {
160 Long oldUpdateID = getSystemUpdateID().getValue();
161 systemUpdateID.increment(true);
162 getPropertyChangeSupport().firePropertyChange(
163 "SystemUpdateID",
164 oldUpdateID,
165 getSystemUpdateID().getValue()
166 );
167 }
168
169 @UpnpAction(out = {
170 @UpnpOutputArgument(name = "Result",
171 stateVariable = "A_ARG_TYPE_Result",
172 getterName = "getResult"),
173 @UpnpOutputArgument(name = "NumberReturned",
174 stateVariable = "A_ARG_TYPE_Count",
175 getterName = "getCount"),
176 @UpnpOutputArgument(name = "TotalMatches",
177 stateVariable = "A_ARG_TYPE_Count",
178 getterName = "getTotalMatches"),
179 @UpnpOutputArgument(name = "UpdateID",
180 stateVariable = "A_ARG_TYPE_UpdateID",
181 getterName = "getContainerUpdateID")
182 })
183 public BrowseResult browse(
184 @UpnpInputArgument(name = "ObjectID", aliases = "ContainerID") String objectId,
185 @UpnpInputArgument(name = "BrowseFlag") String browseFlag,
186 @UpnpInputArgument(name = "Filter") String filter,
187 @UpnpInputArgument(name = "StartingIndex", stateVariable = "A_ARG_TYPE_Index") UnsignedIntegerFourBytes firstResult,
188 @UpnpInputArgument(name = "RequestedCount", stateVariable = "A_ARG_TYPE_Count") UnsignedIntegerFourBytes maxResults,
189 @UpnpInputArgument(name = "SortCriteria") String orderBy)
190 throws ContentDirectoryException {
191
192 SortCriterion[] orderByCriteria;
193 try {
194 orderByCriteria = SortCriterion.valueOf(orderBy);
195 } catch (Exception ex) {
196 throw new ContentDirectoryException(ContentDirectoryErrorCode.UNSUPPORTED_SORT_CRITERIA, ex.toString());
197 }
198
199 try {
200 return browse(
201 objectId,
202 BrowseFlag.valueOrNullOf(browseFlag),
203 filter,
204 firstResult.getValue(), maxResults.getValue(),
205 orderByCriteria
206 );
207 } catch (ContentDirectoryException ex) {
208 throw ex;
209 } catch (Exception ex) {
210 throw new ContentDirectoryException(ErrorCode.ACTION_FAILED, ex.toString());
211 }
212 }
213
214
215
216
217
218
219
220
221
222
223
224 public abstract BrowseResult browse(String objectID, BrowseFlag browseFlag,
225 String filter,
226 long firstResult, long maxResults,
227 SortCriterion[] orderby) throws ContentDirectoryException;
228
229
230 @UpnpAction(out = {
231 @UpnpOutputArgument(name = "Result",
232 stateVariable = "A_ARG_TYPE_Result",
233 getterName = "getResult"),
234 @UpnpOutputArgument(name = "NumberReturned",
235 stateVariable = "A_ARG_TYPE_Count",
236 getterName = "getCount"),
237 @UpnpOutputArgument(name = "TotalMatches",
238 stateVariable = "A_ARG_TYPE_Count",
239 getterName = "getTotalMatches"),
240 @UpnpOutputArgument(name = "UpdateID",
241 stateVariable = "A_ARG_TYPE_UpdateID",
242 getterName = "getContainerUpdateID")
243 })
244 public BrowseResult search(
245 @UpnpInputArgument(name = "ContainerID", stateVariable = "A_ARG_TYPE_ObjectID") String containerId,
246 @UpnpInputArgument(name = "SearchCriteria") String searchCriteria,
247 @UpnpInputArgument(name = "Filter") String filter,
248 @UpnpInputArgument(name = "StartingIndex", stateVariable = "A_ARG_TYPE_Index") UnsignedIntegerFourBytes firstResult,
249 @UpnpInputArgument(name = "RequestedCount", stateVariable = "A_ARG_TYPE_Count") UnsignedIntegerFourBytes maxResults,
250 @UpnpInputArgument(name = "SortCriteria") String orderBy)
251 throws ContentDirectoryException {
252
253 SortCriterion[] orderByCriteria;
254 try {
255 orderByCriteria = SortCriterion.valueOf(orderBy);
256 } catch (Exception ex) {
257 throw new ContentDirectoryException(ContentDirectoryErrorCode.UNSUPPORTED_SORT_CRITERIA, ex.toString());
258 }
259
260 try {
261 return search(
262 containerId,
263 searchCriteria,
264 filter,
265 firstResult.getValue(), maxResults.getValue(),
266 orderByCriteria
267 );
268 } catch (ContentDirectoryException ex) {
269 throw ex;
270 } catch (Exception ex) {
271 throw new ContentDirectoryException(ErrorCode.ACTION_FAILED, ex.toString());
272 }
273 }
274
275
276
277
278
279
280
281 public BrowseResult search(String containerId, String searchCriteria, String filter,
282 long firstResult, long maxResults, SortCriterion[] orderBy) throws ContentDirectoryException {
283
284 try {
285 return new BrowseResult(new DIDLParser().generate(new DIDLContent()), 0, 0);
286 } catch (Exception ex) {
287 throw new ContentDirectoryException(ErrorCode.ACTION_FAILED, ex.toString());
288 }
289 }
290 }