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
227 * @throws RcsPlatformException
228 * if auto notify failed
230 public void apply() throws RcsIllegalStateException {
231 if (mCurrentAttributes == null) {
232 throw new RcsIllegalStateException("it is not locked state.");
234 mCurrentAttributes.apply();
238 private static native RcsResourceObject nativeBuild(String uri,
239 String resourceType, String resourceInterface, boolean isObservable,
240 boolean isDiscoverable, RcsResourceAttributes attributes);
242 private native void nativeSetAttribute(String key, RcsValue value);
244 private native RcsValue nativeGetAttributeValue(String key);
246 private native boolean nativeRemoveAttribute(String key);
248 private native boolean nativeContainsAttribute(String key);
250 private native RcsResourceAttributes nativeGetAttributes();
252 private native boolean nativeIsObservable();
254 private native boolean nativeIsDiscoverable();
256 private native void nativeNotify();
258 private native void nativeSetAutoNotifyPolicy(AutoNotifyPolicy policy);
260 private native AutoNotifyPolicy nativeGetAutoNotifyPolicy();
262 private native void nativeSetSetRequestHandlerPolicy(
263 SetRequestHandlerPolicy policy);
265 private native SetRequestHandlerPolicy nativeGetSetRequestHandlerPolicy();
267 private native void nativeSetGetRequestHandler(GetRequestHandler handler);
269 private native void nativeSetSetRequestHandler(SetRequestHandler handler);
271 private native void nativeAddAttributeUpdatedListener(String key,
272 OnAttributeUpdatedListener listener);
274 private native boolean nativeRemoveAttributeUpdatedListener(String key);
276 private RcsResourceObject() {
280 * Represents the policy of AutoNotify function of RCSResourceObject class
281 * In accord with this, observers are notified of attributes that are
282 * changed or updated.
285 * Attributes are changed or updated according to execution of some
286 * functions which modify attributes or receipt of set requests.
289 * @see removeAttribute
290 * @see getAttributesLock
293 public enum AutoNotifyPolicy {
300 /** When attributes are changed */
305 * Represents the policy of set-request handler.
306 * In accord with this, the RCSResourceObject decides whether a set-request
310 public enum SetRequestHandlerPolicy {
312 * Requests will be ignored if attributes of the request contain
313 * a new key or a value that has different type from the current
319 * The attributes of the request will be applied unconditionally
320 * even if there are new name or type conflicts.
326 * Interface definition for a handler to be invoked when a get request is
329 * The handler will be called first when a get request is received, before
330 * the RCSResourceObject handles.
332 * @see setGetRequestHandler
334 public interface GetRequestHandler {
337 * Called when received a get request from the client.
340 * Request information.
342 * The attributes of the request.
344 * @return A response to be sent.
346 * @see RcsGetResponse
348 RcsGetResponse onGetRequested(RcsRequest request,
349 RcsResourceAttributes attributes);
354 * Interface definition for a handler to be invoked when a set request is
357 * The handler will be called first when a get request is received, before
358 * the RCSResourceObject handles. If the attributes are modified in the
359 * callback, the modified attributes will be set in the RCSResourceObject if
360 * the request is not ignored.
362 * @see setGetRequestHandler
364 public interface SetRequestHandler {
367 * Called when received a set request from the client.
370 * request information
372 * the attributes of the request.
373 * it will be applied to the RcsResourceObject
375 * @return A response indicating how to handle this request.
377 * @see RcsSetResponse
379 RcsSetResponse onSetRequested(RcsRequest request,
380 RcsResourceAttributes attributes);
385 * Interface definition for a callback to be invoked when an attribute is
388 public interface OnAttributeUpdatedListener {
391 * Called when an attribute value is updated.
394 * the attribute value before updated
396 * the current resource attribute value
398 void onAttributeUpdated(RcsValue oldValue, RcsValue newValue);
401 private void assertAlive() throws RcsException {
403 throw new RcsDestroyedObjectException(
404 "The object is already destroyed!");
409 * Sets a particular attribute value.
412 * key with which the specified value is to be associated
414 * value to be associated with the specified key
416 * @throws RcsDestroyedObjectException
417 * if the object is destroyed
418 * @throws NullPointerException
419 * if key or value is null
422 public void setAttribute(String key, RcsValue value) throws RcsException {
425 if (key == null) throw new NullPointerException("key is null");
426 if (value == null) throw new NullPointerException("value is null");
428 nativeSetAttribute(key, value);
432 * Returns a copied attribute value associated with the supplied key.
435 * the key whose associated value is to be returned
437 * @return the value to which the specified key is mapped, or null if no
438 * attribute for the key
440 * @throws RcsDestroyedObjectException
441 * if the object is destroyed
442 * @throws NullPointerException
445 public RcsValue getAttributeValue(String key) throws RcsException {
448 if (key == null) throw new NullPointerException("key is null");
449 return nativeGetAttributeValue(key);
453 * Removes the mapping for a key from the attributes if it is present.
456 * key whose mapping is to be removed
458 * @return true if the key is present and the the value mapped is removed.
460 * @throws RcsDestroyedObjectException
461 * if the object is destroyed
462 * @throws NullPointerException
465 public boolean removeAttribute(String key) throws RcsException {
468 if (key == null) throw new NullPointerException("key is null");
469 return nativeRemoveAttribute(key);
473 * Returns true if the attributes contains a mapping for the specified key.
476 * key whose presence is to be tested
478 * @return true if the attributes contains a mapping for the specified key.
480 * @throws RcsDestroyedObjectException
481 * if the object is destroyed
482 * @throws NullPointerException
485 public boolean containsAttribute(String key) throws RcsException {
488 if (key == null) throw new NullPointerException("key is null");
489 return nativeContainsAttribute(key);
493 * Returns a copied attributes of the RCSResourceObject.
494 * To modify the attributes, use {@link AttributesLock}.
496 * @throws RcsDestroyedObjectException
497 * if the object is destroyed
499 * @see getAttributesLock
501 public RcsResourceAttributes getAttributes() throws RcsException {
504 return nativeGetAttributes();
508 * Returns an AttributesLock for this RcsResourceObject.
510 * @throws RcsDestroyedObjectException
511 * if the object is destroyed
513 public AttributesLock getAttributesLock() throws RcsException {
516 return new AttributesLock(this);
520 * Checks whether the resource is observable or not.
522 * @throws RcsDestroyedObjectException
523 * if the object is destroyed
525 public boolean isObservable() throws RcsException {
528 return nativeIsObservable();
532 * Checks whether the resource is discoverable or not.
534 * @throws RcsDestroyedObjectException
535 * if the object is destroyed
537 public boolean isDiscoverable() throws RcsException {
540 return nativeIsDiscoverable();
544 * Sets the get request handler. To remove handler, pass null.
546 * Default behavior is {@link RcsGetResponse#defaultAction()}.
548 * @throws RcsDestroyedObjectException
549 * if the object is destroyed
551 public void setGetRequestHandler(GetRequestHandler handler)
552 throws RcsException {
555 nativeSetGetRequestHandler(handler);
559 * Sets the set request handler. To remove handler, pass null.
561 * Default behavior is {@link RcsSetResponse#defaultAction()}.
563 * @throws RcsDestroyedObjectException
564 * if the object is destroyed
567 public void setSetRequestHandler(SetRequestHandler handler)
568 throws RcsException {
571 nativeSetSetRequestHandler(handler);
575 * Adds a listener for a particular attribute updated.
578 * the interested attribute's key
580 * listener to be invoked
582 * @throws NullPointerException
583 * if key or listener is null
584 * @throws RcsDestroyedObjectException
585 * if the object is destroyed
587 public void addAttributeUpdatedListener(String key,
588 OnAttributeUpdatedListener listener) throws RcsException {
592 throw new NullPointerException("key is null.");
594 if (listener == null) {
595 throw new NullPointerException("listener is null.");
598 nativeAddAttributeUpdatedListener(key, listener);
602 * Removes a listener for a particular attribute updated.
605 * key the key associated with the listener to be removed
607 * @return true if the listener added with same key exists and is removed.
609 * @throws RcsDestroyedObjectException
610 * if the object is destroyed
611 * @throws NullPointerException
614 public boolean removeAttributeUpdatedListener(String key)
615 throws RcsException {
618 if (key == null) throw new NullPointerException("key is null");
619 return nativeRemoveAttributeUpdatedListener(key);
623 * Notifies all observers of the current attributes.
625 * @throws RcsDestroyedObjectException
626 * if the object is destroyed
627 * @throws RcsPlatformException
628 * if the operation failed
630 public void notifyObservers() throws RcsException {
637 * Sets auto notify policy
642 * @throws RcsDestroyedObjectException
643 * if the object is destroyed
646 public void setAutoNotifyPolicy(AutoNotifyPolicy policy)
647 throws RcsException {
650 if (policy == null) throw new NullPointerException("policy is null");
651 nativeSetAutoNotifyPolicy(policy);
655 * Returns the current policy
657 * @throws RcsDestroyedObjectException
658 * if the object is destroyed
661 public AutoNotifyPolicy getAutoNotifyPolicy() throws RcsException {
664 return nativeGetAutoNotifyPolicy();
668 * Sets the policy for handling a set request.
673 * @throws RcsDestroyedObjectException
674 * if the object is destroyed
677 public void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy)
678 throws RcsException {
681 if (policy == null) throw new NullPointerException("policy is null");
682 nativeSetSetRequestHandlerPolicy(policy);
686 * Returns the current policy.
688 * @throws RcsDestroyedObjectException
689 * if the object is destroyed
691 public SetRequestHandlerPolicy getSetRequestHandlerPolicy()
692 throws RcsException {
695 return nativeGetSetRequestHandlerPolicy();
698 private boolean isDestroyed() {
703 * Unregister the resource and reclaims all resources used by this object.
704 * This must be called if the resource is not used any longer.
707 public void destroy() {