1 /******************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
21 * @file RCSResourceObject.java
23 * This file contains the resource object APIs provided to the developers.
24 * RCSResourceObject is a part of the server builder module.
28 package org.iotivity.service.server;
30 import java.lang.ref.WeakReference;
32 import org.iotivity.service.RcsDestroyedObjectException;
33 import org.iotivity.service.RcsException;
34 import org.iotivity.service.RcsIllegalStateException;
35 import org.iotivity.service.RcsObject;
36 import org.iotivity.service.RcsPlatformException;
37 import org.iotivity.service.RcsResourceAttributes;
38 import org.iotivity.service.RcsValue;
41 * RCSResourceObject represents a resource. It handles any requests from clients
42 * automatically with attributes.
44 * It also provides an auto notification mechanism that notifies to the
45 * observers. Requests are handled automatically by defaultAction of
46 * {@link RcsGetResponse} and {@link RcsSetResponse}. You can override them and
47 * send your own response with {@link GetRequestHandler} and
48 * {@link SetRequestHandler}.
50 * For simple resources, they are simply required to notify whenever attributes
51 * are changed by a set request. In this case, add an
52 * {@link OnAttributeUpdatedListener} with a key interested in instead of
53 * overriding {@link SetRequestHandler}.
57 public final class RcsResourceObject extends RcsObject {
59 * This is a builder to create resource with properties and attributes.
61 * The resource will be observable and discoverable by default, to make them
63 * set these properties explicitly with setDiscoverable and setObservable.
66 public static class Builder {
67 private final String mUri;
68 private final String mType;
69 private final String mInterface;
70 private boolean mIsObservable = true;
71 private boolean mIsDiscovervable = true;
72 private RcsResourceAttributes mAttributes;
75 * Constructs a Builder.
81 * @param resourceInterface
84 * @throws NullPointerException
85 * if any parameter is null
87 public Builder(String uri, String resourceType,
88 String resourceInterface) {
90 throw new NullPointerException("uri is null.");
92 if (resourceType == null) {
93 throw new NullPointerException("resourceType is null.");
95 if (resourceInterface == null) {
96 throw new NullPointerException("resourceInterface is null.");
100 mType = resourceType;
101 mInterface = resourceInterface;
105 * Sets whether the resource is discoverable.
107 * @param isDiscoverable
108 * whether to be discoverable or not
111 public Builder setDiscoverable(boolean isDiscoverable) {
112 mIsDiscovervable = isDiscoverable;
117 * Sets the observable(OC_OBSERVABLE) property of the resource.
119 * @param isObservable
120 * whether to be observable or not
123 public Builder setObservable(boolean isObservable) {
124 mIsObservable = isObservable;
129 * Sets attributes foe the resource.
132 public Builder setAttributes(RcsResourceAttributes attributes) {
133 mAttributes = attributes;
138 * Register a resource and returns a RCSResourceObject.
140 * @throws RcsPlatformException
141 * If registering a resource is failed.
144 public RcsResourceObject build() {
145 return nativeBuild(mUri, mType, mInterface, mIsObservable,
146 mIsDiscovervable, mAttributes);
151 * This provides the way to get the attributes of RcsResourceObject with
153 * When a thread holds the lock, the other threads will be pending until the
154 * lock is released by unlock.
156 * Here is the standard idiom for AttributesLock:
160 * AttributesLock lock = rcsResourceObject.getAttributesLock();
174 public static class AttributesLock {
176 private final WeakReference<RcsResourceObject> mResourceObjectRef;
178 private RcsLockedAttributes mCurrentAttributes;
180 private AttributesLock(RcsResourceObject resourceObj) {
181 mResourceObjectRef = new WeakReference<RcsResourceObject>(
185 private RcsResourceObject ensureResourceObject() throws RcsException {
186 final RcsResourceObject object = mResourceObjectRef.get();
188 if (object == null || object.isDestroyed()) {
189 throw new RcsDestroyedObjectException(
190 "The object is already destroyed!");
197 * Locks the attributes of the RcsResourceObject and returns locked
198 * attributes that can be modified until unlocked.
200 * @return Locked attributes.
202 * @throws RcsException
203 * if the RcsResourceObject is destroyed
205 public RcsLockedAttributes lock() throws RcsException {
206 return mCurrentAttributes = new RcsLockedAttributes(
207 ensureResourceObject());
211 * Changes the state to unlock of the attributes of the
215 public void unlock() {
216 if (mCurrentAttributes == null) return;
218 mCurrentAttributes.setUnlockState();
219 mCurrentAttributes = null;
223 * Applies the modified attributes to the RcsResourceObject.
225 * @throws RcsIllegalStateException
226 * if not in locked state
228 public void apply() throws RcsIllegalStateException {
229 if (mCurrentAttributes == null) {
230 throw new RcsIllegalStateException("it is not locked state.");
232 mCurrentAttributes.apply();
236 private static native RcsResourceObject nativeBuild(String uri,
237 String resourceType, String resourceInterface, boolean isObservable,
238 boolean isDiscoverable, RcsResourceAttributes attributes);
240 private native void nativeSetAttribute(String key, RcsValue value);
242 private native RcsValue nativeGetAttributeValue(String key);
244 private native boolean nativeRemoveAttribute(String key);
246 private native boolean nativeContainsAttribute(String key);
248 private native RcsResourceAttributes nativeGetAttributes();
250 private native boolean nativeIsObservable();
252 private native boolean nativeIsDiscoverable();
254 private native void nativeNotify();
256 private native void nativeSetAutoNotifyPolicy(AutoNotifyPolicy policy);
258 private native AutoNotifyPolicy nativeGetAutoNotifyPolicy();
260 private native void nativeSetSetRequestHandlerPolicy(
261 SetRequestHandlerPolicy policy);
263 private native SetRequestHandlerPolicy nativeGetSetRequestHandlerPolicy();
265 private native void nativeSetGetRequestHandler(GetRequestHandler handler);
267 private native void nativeSetSetRequestHandler(SetRequestHandler handler);
269 private native void nativeAddAttributeUpdatedListener(String key,
270 OnAttributeUpdatedListener listener);
272 private native boolean nativeRemoveAttributeUpdatedListener(String key);
274 private RcsResourceObject() {
278 * Represents the policy of AutoNotify function of RCSResourceObject class
279 * In accord with this, observers are notified of attributes that are
280 * changed or updated.
283 * Attributes are changed or updated according to execution of some
284 * functions which modify attributes or receipt of set requests.
287 * @see removeAttribute
288 * @see getAttributesLock
291 public enum AutoNotifyPolicy {
298 /** When attributes are changed */
303 * Represents the policy of set-request handler.
304 * In accord with this, the RCSResourceObject decides whether a set-request
308 public enum SetRequestHandlerPolicy {
310 * Requests will be ignored if attributes of the request contain
311 * a new key or a value that has different type from the current
317 * The attributes of the request will be applied unconditionally
318 * even if there are new name or type conflicts.
324 * Interface definition for a handler to be invoked when a get request is
327 * The handler will be called first when a get request is received, before
328 * the RCSResourceObject handles.
330 * @see setGetRequestHandler
332 public interface GetRequestHandler {
335 * Called when received a get request from the client.
338 * Request information.
340 * The attributes of the request.
342 * @return A response to be sent.
344 * @see RcsGetResponse
346 RcsGetResponse onGetRequested(RcsRequest request,
347 RcsResourceAttributes attributes);
352 * Interface definition for a handler to be invoked when a set request is
355 * The handler will be called first when a get request is received, before
356 * the RCSResourceObject handles. If the attributes are modified in the
357 * callback, the modified attributes will be set in the RCSResourceObject if
358 * the request is not ignored.
360 * @see setGetRequestHandler
362 public interface SetRequestHandler {
365 * Called when received a set request from the client.
368 * request information
370 * the attributes of the request.
371 * it will be applied to the RcsResourceObject
373 * @return A response indicating how to handle this request.
375 * @see RcsSetResponse
377 RcsSetResponse onSetRequested(RcsRequest request,
378 RcsResourceAttributes attributes);
383 * Interface definition for a callback to be invoked when an attribute is
386 public interface OnAttributeUpdatedListener {
389 * Called when an attribute value is updated.
392 * the attribute value before updated
394 * the current resource attribute value
396 void onAttributeUpdated(RcsValue oldValue, RcsValue newValue);
399 private void assertAlive() throws RcsException {
401 throw new RcsDestroyedObjectException(
402 "The object is already destroyed!");
407 * Sets a particular attribute value.
410 * key with which the specified value is to be associated
412 * value to be associated with the specified key
414 * @throws RcsDestroyedObjectException
415 * if the object is destroyed
416 * @throws NullPointerException
417 * if key or value is null
420 public void setAttribute(String key, RcsValue value) throws RcsException {
423 if (key == null) throw new NullPointerException("key is null");
424 if (value == null) throw new NullPointerException("value is null");
426 nativeSetAttribute(key, value);
430 * Returns a copied attribute value associated with the supplied key.
433 * the key whose associated value is to be returned
435 * @return the value to which the specified key is mapped, or null if no
436 * attribute for the key
438 * @throws RcsDestroyedObjectException
439 * if the object is destroyed
440 * @throws NullPointerException
443 public RcsValue getAttributeValue(String key) throws RcsException {
446 if (key == null) throw new NullPointerException("key is null");
447 return nativeGetAttributeValue(key);
451 * Removes the mapping for a key from the attributes if it is present.
454 * key whose mapping is to be removed
456 * @return true if the key is present and the the value mapped is removed.
458 * @throws RcsDestroyedObjectException
459 * if the object is destroyed
460 * @throws NullPointerException
463 public boolean removeAttribute(String key) throws RcsException {
466 if (key == null) throw new NullPointerException("key is null");
467 return nativeRemoveAttribute(key);
471 * Returns true if the attributes contains a mapping for the specified key.
474 * key whose presence is to be tested
476 * @return true if the attributes contains a mapping for the specified key.
478 * @throws RcsDestroyedObjectException
479 * if the object is destroyed
480 * @throws NullPointerException
483 public boolean containsAttribute(String key) throws RcsException {
486 if (key == null) throw new NullPointerException("key is null");
487 return nativeContainsAttribute(key);
491 * Returns a copied attributes of the RCSResourceObject.
492 * To modify the attributes, use {@link AttributesLock}.
494 * @throws RcsDestroyedObjectException
495 * if the object is destroyed
497 * @see getAttributesLock
499 public RcsResourceAttributes getAttributes() throws RcsException {
502 return nativeGetAttributes();
506 * Returns an AttributesLock for this RcsResourceObject.
508 * @throws RcsDestroyedObjectException
509 * if the object is destroyed
511 public AttributesLock getAttributesLock() throws RcsException {
514 return new AttributesLock(this);
518 * Checks whether the resource is observable or not.
520 * @throws RcsDestroyedObjectException
521 * if the object is destroyed
523 public boolean isObservable() throws RcsException {
526 return nativeIsObservable();
530 * Checks whether the resource is discoverable or not.
532 * @throws RcsDestroyedObjectException
533 * if the object is destroyed
535 public boolean isDiscoverable() throws RcsException {
538 return nativeIsDiscoverable();
542 * Sets the get request handler. To remove handler, pass null.
544 * Default behavior is {@link RcsGetResponse#defaultAction()}.
546 * @throws RcsDestroyedObjectException
547 * if the object is destroyed
549 public void setGetRequestHandler(GetRequestHandler handler)
550 throws RcsException {
553 nativeSetGetRequestHandler(handler);
557 * Sets the set request handler. To remove handler, pass null.
559 * Default behavior is {@link RcsSetResponse#defaultAction()}.
561 * @throws RcsDestroyedObjectException
562 * if the object is destroyed
565 public void setSetRequestHandler(SetRequestHandler handler)
566 throws RcsException {
569 nativeSetSetRequestHandler(handler);
573 * Adds a listener for a particular attribute updated.
576 * the interested attribute's key
578 * listener to be invoked
580 * @throws NullPointerException
581 * if key or listener is null
582 * @throws RcsDestroyedObjectException
583 * if the object is destroyed
585 public void addAttributeUpdatedListener(String key,
586 OnAttributeUpdatedListener listener) throws RcsException {
590 throw new NullPointerException("key is null.");
592 if (listener == null) {
593 throw new NullPointerException("listener is null.");
596 nativeAddAttributeUpdatedListener(key, listener);
600 * Removes a listener for a particular attribute updated.
603 * key the key associated with the listener to be removed
605 * @return true if the listener added with same key exists and is removed.
607 * @throws RcsDestroyedObjectException
608 * if the object is destroyed
609 * @throws NullPointerException
612 public boolean removeAttributeUpdatedListener(String key)
613 throws RcsException {
616 if (key == null) throw new NullPointerException("key is null");
617 return nativeRemoveAttributeUpdatedListener(key);
621 * Notifies all observers of the current attributes.
623 * @throws RcsDestroyedObjectException
624 * if the object is destroyed
625 * @throws RcsPlatformException
626 * if the operation failed
628 public void notifyObservers() throws RcsException {
635 * Sets auto notify policy
640 * @throws RcsDestroyedObjectException
641 * if the object is destroyed
644 public void setAutoNotifyPolicy(AutoNotifyPolicy policy)
645 throws RcsException {
648 if (policy == null) throw new NullPointerException("policy is null");
649 nativeSetAutoNotifyPolicy(policy);
653 * Returns the current policy
655 * @throws RcsDestroyedObjectException
656 * if the object is destroyed
659 public AutoNotifyPolicy getAutoNotifyPolicy() throws RcsException {
662 return nativeGetAutoNotifyPolicy();
666 * Sets the policy for handling a set request.
671 * @throws RcsDestroyedObjectException
672 * if the object is destroyed
675 public void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy)
676 throws RcsException {
679 if (policy == null) throw new NullPointerException("policy is null");
680 nativeSetSetRequestHandlerPolicy(policy);
684 * Returns the current policy.
686 * @throws RcsDestroyedObjectException
687 * if the object is destroyed
689 public SetRequestHandlerPolicy getSetRequestHandlerPolicy()
690 throws RcsException {
693 return nativeGetSetRequestHandlerPolicy();
696 private boolean isDestroyed() {
701 * Unregister the resource and reclaims all resources used by this object.
702 * This must be called if the resource is not used any longer.
705 public void destroy() {