Merge branch 'master' into resource-container
[platform/upstream/iotivity.git] / service / resource-container / android / resource-container / src / main / java / org / iotivity / service / resourcecontainer / server / RcsLockedAttributes.java
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  ******************************************************************/
20
21 package org.iotivity.service.resourcecontainer.server;
22
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Set;
28
29 import org.iotivity.service.resourcecontainer.RcsException;
30 import org.iotivity.service.resourcecontainer.RcsObject;
31 import org.iotivity.service.resourcecontainer.RcsResourceAttributes;
32 import org.iotivity.service.resourcecontainer.RcsValue;
33
34 public final class RcsLockedAttributes extends RcsObject {
35
36     private static native boolean nativeIsEmpty(RcsResourceObject resourceObj);
37
38     private static native int nativeSize(RcsResourceObject resourceObj);
39
40     private static native boolean nativeRemove(RcsResourceObject resourceObj,
41             String key);
42
43     private static native boolean nativeClear(RcsResourceObject resourceObj);
44
45     private static native boolean nativeContains(RcsResourceObject resourceObj,
46             String key);
47
48     private static native void nativeAddKeys(RcsResourceObject resourceObj,
49             Set<String> set);
50
51     private static native RcsValue nativeAsJavaObject(
52             RcsResourceObject resourceObj, String key);
53
54     private static native void nativeApply(RcsResourceObject resourceObj,
55             Map<String, RcsValue> cache);
56
57     private native void nativeLock(RcsResourceObject resourceObj);
58
59     private native void nativeUnlock();
60
61     private final RcsResourceObject mResourceObject;
62
63     private boolean mIsUnlocked;
64
65     private Map<String, RcsValue> mCache = new HashMap<>();
66
67     RcsLockedAttributes(RcsResourceObject resourceObject) throws RcsException {
68         if (resourceObject == null) {
69             throw new RcsException("Illegal opertaion!");
70         }
71
72         mResourceObject = resourceObject;
73
74         nativeLock(resourceObject);
75     }
76
77     void setUnlockState() {
78         mIsUnlocked = true;
79         mCache = null;
80
81         nativeUnlock();
82     }
83
84     void apply() {
85         nativeApply(mResourceObject, mCache);
86         mCache.clear();
87     }
88
89     private void ensureLocked() throws RcsException {
90         if (mIsUnlocked) {
91             throw new RcsUnlockedException("This attributes is unlocked!");
92         }
93     }
94
95     /**
96      * Returns a unmodifiable Set view of the keys contained in this attributes.
97      *
98      * @return an unmodifiable set view of the keys in this attributes
99      *
100      * @throws RcsUnlockedException
101      *             if the {@link RcsResourceObject.AttributesLock} for this
102      *             object is unlocked
103      */
104     public Set<String> keySet() throws RcsException {
105         ensureLocked();
106
107         final Set<String> keySet = new HashSet<>(mCache.keySet());
108
109         nativeAddKeys(mResourceObject, keySet);
110
111         return Collections.unmodifiableSet(keySet);
112     }
113
114     /**
115      * Returns the value to which the specified key is mapped, or null if this
116      * contains no mapping for the key.
117      *
118      * @param key
119      *            the key whose associated value is to be returned
120      *
121      * @return the value to which the specified key is mapped, or null if this
122      *         contains no mapping for the key
123      *
124      * @throws NullPointerException
125      *             if key is null
126      * @throws RcsUnlockedException
127      *             if the {@link RcsResourceObject.AttributesLock} for this
128      *             object is unlocked
129      */
130     public RcsValue get(String key) throws RcsException {
131         ensureLocked();
132
133         if (key == null) throw new NullPointerException("key is null");
134
135         if (!mCache.containsKey(key) && nativeContains(mResourceObject, key)) {
136             mCache.put(key, nativeAsJavaObject(mResourceObject, key));
137         }
138         return mCache.get(key);
139     }
140
141     /**
142      * Copies all of the mappings from the specified to this
143      *
144      * @param attributes
145      *            attributes to be copied
146      *
147      * @throws RcsUnlockedException
148      *             if the {@link RcsResourceObject.AttributesLock} for this
149      *             object is unlocked
150      *
151      */
152     public RcsLockedAttributes putAll(RcsResourceAttributes attributes)
153             throws RcsException {
154         ensureLocked();
155
156         final Set<String> keys = attributes.keySet();
157
158         for (final String k : keys) {
159             mCache.put(k, attributes.get(k));
160         }
161         return this;
162     }
163
164     /**
165      * Sets the specified value with the specified key.
166      * If the object previously contained a mapping for the key, the old value
167      * is replaced by the specified value.
168      *
169      * @param key
170      *            key with which the specified value is to be associated
171      *
172      * @param value
173      *            value to be associated with the specified key
174      *
175      * @throws NullPointerException
176      *             if key or value is null
177      * @throws RcsUnlockedException
178      *             if the {@link RcsResourceObject.AttributesLock} for this
179      *             object is unlocked
180      *
181      */
182     public RcsLockedAttributes put(String key, RcsValue value)
183             throws RcsException {
184         ensureLocked();
185
186         if (key == null) throw new NullPointerException("key is null");
187         if (value == null) throw new NullPointerException("value is null");
188
189         mCache.put(key, value);
190
191         return this;
192     }
193
194     /**
195      * Sets the specified value with the specified key.
196      * If the object previously contained a mapping for the key, the old value
197      * is replaced by the specified value.
198      *
199      * @param key
200      *            key with which the specified value is to be associated
201      *
202      * @param value
203      *            value to be associated with the specified key
204      *
205      * @throws NullPointerException
206      *             if key or value is null
207      * @throws IllegalArgumentException
208      *             if object is not supported type by {@link RcsValue}
209      * @throws RcsUnlockedException
210      *             if the {@link RcsResourceObject.AttributesLock} for this
211      *             object is unlocked
212      */
213     public void put(String key, Object value) throws RcsException {
214         if (key == null) throw new NullPointerException("key is null");
215
216         put(key, new RcsValue(value));
217     }
218
219     /**
220      * Returns whether attribute is empty.
221      *
222      * @throws RcsUnlockedException
223      *             if the {@link RcsResourceObject.AttributesLock} for this
224      *             object is unlocked
225      */
226     public boolean isEmpty() throws RcsException {
227         ensureLocked();
228
229         return mCache.isEmpty() && nativeIsEmpty(mResourceObject);
230     }
231
232     /**
233      * Returns the number of key-value mappings.
234      *
235      * @throws RcsUnlockedException
236      *             if the {@link RcsResourceObject.AttributesLock} for this
237      *             object is unlocked
238      */
239     public int size() throws RcsException {
240         ensureLocked();
241
242         return mCache.size() + nativeSize(mResourceObject);
243     }
244
245     /**
246      * Removes the mapping for a key from this attributes if it is present.
247      *
248      * @param key
249      *            key whose mapping is to be removed
250      *
251      * @return true if the key is present and the the value mapped is removed.
252      *
253      * @throws RcsUnlockedException
254      *             if the {@link RcsResourceObject.AttributesLock} for this
255      *             object is unlocked
256      */
257     public boolean remove(String key) throws RcsException {
258         ensureLocked();
259
260         if (key == null) throw new NullPointerException("key is null");
261
262         // XXX make sure both cache and native values to be removed.
263         final boolean cacheRemove = mCache.remove(key) != null;
264         final boolean nativeRemove = nativeRemove(mResourceObject, key);
265
266         return cacheRemove || nativeRemove;
267     }
268
269     /**
270      * Removes all elements.
271      *
272      * @throws RcsUnlockedException
273      *             if the {@link RcsResourceObject.AttributesLock} for this
274      *             object is unlocked
275      */
276     public void clear() throws RcsException {
277         ensureLocked();
278
279         nativeClear(mResourceObject);
280     }
281
282     /**
283      * Returns true if this contains a mapping for the specified key.
284      *
285      * @param key
286      *            key whose presence is to be tested
287      *
288      * @return true if this contains a mapping for the specified key.
289      *
290      * @throws NullPointerException
291      *             if key is null
292      * @throws RcsUnlockedException
293      *             if the {@link RcsResourceObject.AttributesLock} for this
294      *             object is unlocked
295      */
296     public boolean contains(String key) throws RcsException {
297         ensureLocked();
298
299         if (key == null) throw new NullPointerException("key is null");
300
301         return mCache.containsKey(key) || nativeContains(mResourceObject, key);
302     }
303 }