Skip to content

Commit 6ac3d3c

Browse files
authored
Merge pull request #224 from dmsl/develop
Develop
2 parents 82361ab + ea2341e commit 6ac3d3c

28 files changed

+31684
-249
lines changed

server/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ This is a latest version of the Anyplace backend, which has been ported to tha s
6464

6565
## SSL and Cluster Configurations for Anyplace Server
6666
+ Install a free certificate from https://letsencrypt.org/ on your Anyplace Server to obtain a secure https connection. SSL is only optional for web functionality. For Android, SSL is a prerequisite!
67+
6768
+ (Optional) Install a free load balancer from [HAProxy](http://www.haproxy.org/) to scale your installation to multiple Anplace servers. In case of Anyplace cluster configuration, please install the certificate on the load balancer.
6869

6970

server/anyplace_views/create-views.sh

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_d
2020

2121
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/dev_nav_spatial -d @spatial_nav.json -u $USERNAME:$PASSWORD
2222

23+
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/dev_heatmaps -d @heatmaps.json -u $USERNAME:$PASSWORD
24+
25+
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/dev_heatmaps_spatial -d @spatial_heatmaps.json -u $USERNAME:$PASSWORD
26+
27+
2328
##########
2429
# PUBLISH
2530
##########
@@ -41,3 +46,7 @@ curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_d
4146
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/radio_spatial -d @spatial_radio.json -u $USERNAME:$PASSWORD
4247

4348
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/nav_spatial -d @spatial_nav.json -u $USERNAME:$PASSWORD
49+
50+
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/heatmaps -d @heatmaps.json -u $USERNAME:$PASSWORD
51+
52+
curl -X PUT -H "Content-Type: application/json" http://localhost:8092/$BUCKET/_design/heatmaps_spatial -d @spatial_heatmaps.json -u $USERNAME:$PASSWORD

server/anyplace_views/heatmaps.json

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"views": {
3+
"heatmap_by_floor_building_level_1": {
4+
"map": "function (doc, meta) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y) {\n emit([doc.buid, doc.floor, doc.x.slice(0,doc.x.length-5), doc.y.slice(0,doc.y.length-5)], doc.rss);\n }\n}",
5+
"reduce": "function (keys, values, rereduce) {\n if(!rereduce) {\n var total = 0,\n count = 0;\n for (v in values) {\n total+= parseInt(values[v]);\n count++;\n }\n } else {\n var count = 0;\n total = 0;\n for (v in values) {\n total += values[v]['total'];\n count += values[v]['count'];\n } \n }\n var average = total / count;\n return {count: count,\n total: total,\n average: average};\n}"
6+
},
7+
"heatmap_by_floor_building_level_2": {
8+
"map": "function (doc, meta) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y) {\n emit([doc.buid, doc.floor, doc.x.slice(0,doc.x.length-4), doc.y.slice(0,doc.y.length-4)], doc.rss);\n }\n}",
9+
"reduce": "function (keys, values, rereduce) {\n if(!rereduce) {\n var total = 0,\n count = 0;\n for (v in values) {\n total+= parseInt(values[v]);\n count++;\n }\n } else {\n var count = 0;\n total = 0;\n for (v in values) {\n total += values[v]['total'];\n count += values[v]['count'];\n } \n }\n var average = total / count;\n return {count: count,\n total: total,\n average: average};\n}"
10+
},
11+
"heatmap_by_floor_building_level_3": {
12+
"map": "function (doc, meta) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y) {\n emit([doc.buid, doc.floor, doc.x, doc.y], doc.rss);\n }\n}",
13+
"reduce": "function (keys, values, rereduce) {\n if(!rereduce) {\n var total = 0,\n count = 0;\n for (v in values) {\n total+= parseInt(values[v]);\n count++;\n }\n } else {\n var count = 0;\n total = 0;\n for (v in values) {\n total += values[v]['total'];\n count += values[v]['count'];\n } \n }\n var average = total / count;\n return {count: count,\n total: total,\n average: average};\n}"
14+
},
15+
"accessPoint_by_floor_building": {
16+
"map": "function (doc, meta) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y) {\n emit([doc.buid, doc.floor, doc.x, doc.y,doc.MAC],doc.rss);\n }\n}",
17+
"reduce": "function (keys, values, rereduce) {\n if(!rereduce) {\n var total = 0,\n count = 0;\n for (v in values) {\n total+= parseInt(values[v]);\n count++;\n }\n } else {\n var count = 0;\n total = 0;\n for (v in values) {\n total += values[v]['total'];\n count += values[v]['count'];\n } \n }\n var average = total / count;\n return {count: count,\n total: total,\n average: average};\n}"
18+
},
19+
"heatmap_by_floor_building": {
20+
"map": "function (doc, meta) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y) {\n emit([doc.buid, doc.floor, doc.x, doc.y], doc.rss);\n }\n}",
21+
"reduce": "function (keys, values, rereduce) {\n if(!rereduce) {\n var total = 0,\n count = 0;\n for (v in values) {\n total+= parseInt(values[v]);\n count++;\n }\n } else {\n var count = 0;\n total = 0;\n for (v in values) {\n total += values[v]['total'];\n count += values[v]['count'];\n } \n }\n var average = total / count;\n return {count: count,\n total: total,\n average: average};\n}"
22+
}
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"spatial":{
3+
"heatmap_by_floor_building":"function (doc) {\n \n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y) {\n if (doc.geometry) {\n \n emit(doc.geometry, {\"info\":[doc.buid, doc.floor, doc.x, doc.y], \"rss\":doc.rss});\n }\n }\n}"
4+
}
5+
}
+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"spatial": {
3-
"building_coordinates": "function (doc) {\n if (doc.geometry && doc.buid && !doc.floor_number && !doc.puid && !doc.rss) {\n //emit(doc.geometry, doc);\n emit(doc.geometry, null);\n }\n}",
43
"raw_radio": "function (doc) {\n if (doc.geometry && doc.MAC && doc.rss && doc.heading) {\n emit(doc.geometry, { \"timestamp\": doc.timestamp, \"floor\": doc.floor, \"rss\": doc.rss, \"MAC\": doc.MAC, \"heading\": doc.heading, \"y\": doc.y, \"x\": doc.x}); }\n}",
5-
"radio_heatmap_bbox_byxy": "function (doc) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y){\n emit(doc.geometry, { \"floor\": doc.floor, \"buid\": doc.buid, \"y\": doc.y, \"x\": doc.x}); }\n}"
4+
"radio_heatmap_bbox_byxy": "function (doc) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y){\n emit(doc.geometry, { \"floor\": doc.floor, \"buid\": doc.buid, \"y\": doc.y, \"x\": doc.x}); }\n}",
5+
"radio_buid_floor":"function (doc,meta) {\n if (doc.buid && doc.floor && doc.rss && doc.MAC && doc.heading && doc.x && doc.y){\n emit(doc.geometry, { \"floor\": doc.floor, \"buid\": doc.buid, \"id\": meta.id}); }\n}"
66

77
}
88
}

server/app/controllers/AnyplaceMapping.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -1091,11 +1091,11 @@ object AnyplaceMapping extends play.api.mvc.Controller {
10911091
}
10921092

10931093
private def isCampusOwner(campus: JsonObject, userId: String): Boolean = { // Admin
1094-
if (userId == ADMIN_ID)
1095-
true
1094+
if (userId.equals(ADMIN_ID))
1095+
return true
10961096
// Check if owner
10971097
if (campus != null && campus.get("owner_id") != null && campus.getString("owner_id").equals(userId))
1098-
true
1098+
return true
10991099
false
11001100
}
11011101

@@ -1353,7 +1353,7 @@ object AnyplaceMapping extends play.api.mvc.Controller {
13531353
owner_id = appendToOwnerId(owner_id)
13541354
json = json.as[JsObject] + ("owner_id" -> Json.toJson(owner_id))
13551355
val puid = (json \ "puid").as[String]
1356-
val buid = (json \ "puid").as[String]
1356+
val buid = (json \ "buid").as[String]
13571357
try {
13581358
val stored_building = ProxyDataSource.getIDatasource.getFromKeyAsJson(buid)
13591359
if (stored_building == null) return AnyResponseHelper.bad_request("Building does not exist or could not be retrieved!")

server/app/db_models/Building.scala

+127-124
Original file line numberDiff line numberDiff line change
@@ -45,135 +45,138 @@ import play.api.libs.json.JsValue
4545

4646
class Building(hm: HashMap[String, String]) extends AbstractModel {
4747

48-
private var json: JsonObject = _
49-
50-
private var lat: Double = _
51-
52-
private var lng: Double = _
53-
54-
private var admins: Array[String] = Array()
55-
56-
this.fields = hm
57-
58-
def this() {
59-
this(new HashMap[String, String])
60-
fields.put("username_creator", "")
61-
fields.put("buid", "")
62-
fields.put("is_published", "")
63-
fields.put("name", "")
64-
fields.put("description", "")
65-
fields.put("url", "")
66-
fields.put("address", "")
67-
fields.put("coordinates_lat", "")
68-
fields.put("coordinates_lon", "")
69-
fields.put("bucode", "")
70-
}
71-
72-
def this(json: JsonObject) {
73-
this()
74-
fields.put("username_creator", json.getString("username_creator"))
75-
fields.put("owner_id", json.getString("owner_id"))
76-
fields.put("buid", json.getString("buid"))
77-
fields.put("is_published", json.getString("is_published"))
78-
fields.put("name", json.getString("name"))
79-
fields.put("description", json.getString("description"))
80-
fields.put("url", json.getString("url"))
81-
fields.put("address", json.getString("address"))
82-
fields.put("coordinates_lat", json.getString("coordinates_lat"))
83-
fields.put("coordinates_lon", json.getString("coordinates_lon"))
84-
fields.put("bucode", json.getString("bucode"))
85-
this.json = json
86-
this.lat = java.lang.Double.parseDouble(json.getString("coordinates_lat"))
87-
this.lng = java.lang.Double.parseDouble(json.getString("coordinates_lon"))
88-
}
89-
90-
def this(json: JsonObject, owner: String) {
91-
this(json)
92-
fields.put("owner_id", owner)
48+
private var json: JsonObject = _
49+
50+
private var lat: Double = _
51+
52+
private var lng: Double = _
53+
54+
private var admins: Array[String] = Array("112997031510415584062_google")
55+
56+
private var co_owners = JsonArray.empty()
57+
58+
this.fields = hm
59+
60+
def this() {
61+
this(new HashMap[String, String])
62+
fields.put("username_creator", "")
63+
fields.put("buid", "")
64+
fields.put("is_published", "")
65+
fields.put("name", "")
66+
fields.put("description", "")
67+
fields.put("url", "")
68+
fields.put("address", "")
69+
fields.put("coordinates_lat", "")
70+
fields.put("coordinates_lon", "")
71+
fields.put("bucode", "")
72+
}
73+
74+
def this(json: JsonObject) {
75+
this()
76+
fields.put("username_creator", json.getString("username_creator"))
77+
fields.put("owner_id", json.getString("owner_id"))
78+
fields.put("buid", json.getString("buid"))
79+
fields.put("is_published", json.getString("is_published"))
80+
fields.put("name", json.getString("name"))
81+
fields.put("description", json.getString("description"))
82+
fields.put("url", json.getString("url"))
83+
fields.put("address", json.getString("address"))
84+
fields.put("coordinates_lat", json.getString("coordinates_lat"))
85+
fields.put("coordinates_lon", json.getString("coordinates_lon"))
86+
fields.put("bucode", json.getString("bucode"))
87+
co_owners= json.getArray("co_owners")
88+
this.json = json
89+
this.lat = java.lang.Double.parseDouble(json.getString("coordinates_lat"))
90+
this.lng = java.lang.Double.parseDouble(json.getString("coordinates_lon"))
91+
}
92+
93+
def this(json: JsonObject, owner: String) {
94+
this(json)
95+
fields.put("owner_id", owner)
96+
}
97+
98+
def getId(): String = {
99+
var buid: String = fields.get("buid")
100+
if (buid == null || buid.isEmpty || buid == "") {
101+
val finalId = LPUtils.getRandomUUID + "_" + System.currentTimeMillis()
102+
fields.put("buid", "building_" + finalId)
103+
buid = fields.get("buid")
104+
this.json.put("buid", buid)
93105
}
94-
95-
def getId(): String = {
96-
var buid: String = fields.get("buid")
97-
if (buid==null||buid.isEmpty || buid == "") {
98-
val finalId = LPUtils.getRandomUUID + "_" + System.currentTimeMillis()
99-
fields.put("buid", "building_" + finalId)
100-
buid = fields.get("buid")
101-
this.json.put("buid", buid)
106+
buid
107+
}
108+
109+
def toValidCouchJson(): JsonObject = {
110+
// initialize id if not initialized
111+
getId()
112+
JsonObject.from(this.getFields()).put("co_owners",co_owners)
113+
}
114+
115+
def toCouchGeoJSON(): String = {
116+
val sb = new StringBuilder()
117+
val json = toValidCouchJson()
118+
try {
119+
json.put("geometry", new GeoJSONPoint(java.lang.Double.parseDouble(fields.get("coordinates_lat")),
120+
java.lang.Double.parseDouble(fields.get("coordinates_lon")))
121+
.toGeoJSON())
122+
if (json.getArray("co_owners") == null || json.getArray("co_owners").isEmpty) {
123+
val ja = JsonArray.empty()
124+
for (i <- admins.indices) {
125+
ja.add(admins(i))
102126
}
103-
buid
104-
}
105-
106-
def toValidCouchJson(): JsonObject = {
107-
// initialize id if not initialized
108-
getId()
109-
JsonObject.from(this.getFields())
127+
json.put("co_owners", ja)
128+
}
129+
json.removeKey("username")
130+
} catch {
131+
case e: IOException => e.printStackTrace()
110132
}
111-
112-
def toCouchGeoJSON(): String = {
113-
val sb = new StringBuilder()
114-
val json= toValidCouchJson()
115-
try {
116-
json.put("geometry", new GeoJSONPoint(java.lang.Double.parseDouble(fields.get("coordinates_lat")),
117-
java.lang.Double.parseDouble(fields.get("coordinates_lon")))
118-
.toGeoJSON())
119-
if (json.get("co_owners") == null) {
120-
val ja = JsonArray.empty()
121-
for (i <- 0 until admins.length) {
122-
ja.add(admins(i))
123-
}
124-
json.put("co_owners",ja)
125-
}
126-
json.removeKey("username")
127-
} catch {
128-
case e: IOException => e.printStackTrace()
133+
sb.append(json.toString)
134+
sb.toString
135+
}
136+
137+
def appendCoOwners(jsonReq: JsValue): String = {
138+
val sb = new StringBuilder()
139+
var json = toValidCouchJson()
140+
try {
141+
json = JsonObject.empty()
142+
if (json.get("owner_id") == null || json.getString("owner_id") != jsonReq.\\("owner_id").mkString) {
143+
return json.toString
144+
}
145+
val ja = JsonArray.empty()
146+
for (i <- 0 until admins.length) {
147+
ja.add(admins(i))
148+
}
149+
val it = jsonReq.\("co_owners").get.productIterator
150+
while (it.hasNext) {
151+
val curr = it.next()
152+
if (curr != null) {
153+
ja.add(curr.toString)
129154
}
130-
sb.append(json.toString)
131-
sb.toString
155+
}
156+
json.put("co_owners", ja)
157+
} catch {
158+
case e: IOException => e.printStackTrace()
132159
}
133-
134-
def appendCoOwners(jsonReq: JsValue): String = {
135-
val sb = new StringBuilder()
136-
var json= toValidCouchJson()
137-
try {
138-
json = JsonObject.empty()
139-
if (json.get("owner_id") == null || json.getString("owner_id") != jsonReq.\\("owner_id").mkString) {
140-
return json.toString
141-
}
142-
val ja = JsonArray.empty()
143-
for (i <- 0 until admins.length) {
144-
ja.add(admins(i))
145-
}
146-
val it = jsonReq.\("co_owners").get.productIterator
147-
while (it.hasNext) {
148-
val curr = it.next()
149-
if (curr != null) {
150-
ja.add(curr.toString)
151-
}
152-
}
153-
json.put("co_owners",ja)
154-
} catch {
155-
case e: IOException => e.printStackTrace()
156-
}
157-
sb.append(json.toString)
158-
sb.toString
159-
}
160-
161-
def changeOwner(newOwnerId: String): String = {
162-
val sb = new StringBuilder()
163-
var json = toValidCouchJson()
164-
try {
165-
this.fields.put("owner_id", newOwnerId)
166-
val ja = JsonArray.empty()
167-
for (i <- 0 until admins.length) {
168-
ja.add(admins(i))
169-
}
170-
json.put("co_owners",ja)
171-
} catch {
172-
case e: IOException => e.printStackTrace()
173-
}
174-
sb.append(json.toString)
175-
sb.toString
160+
sb.append(json.toString)
161+
sb.toString
162+
}
163+
164+
def changeOwner(newOwnerId: String): String = {
165+
val sb = new StringBuilder()
166+
var json = toValidCouchJson()
167+
try {
168+
this.fields.put("owner_id", newOwnerId)
169+
val ja = JsonArray.empty()
170+
for (i <- 0 until admins.length) {
171+
ja.add(admins(i))
172+
}
173+
json.put("co_owners", ja)
174+
} catch {
175+
case e: IOException => e.printStackTrace()
176176
}
177+
sb.append(json.toString)
178+
sb.toString
179+
}
177180

178-
override def toString(): String = toValidCouchJson().toString
181+
override def toString(): String = toValidCouchJson().toString
179182
}

server/app/db_models/BuildingSet.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class BuildingSet(hm: HashMap[String, String]) extends AbstractModel {
4949

5050
private var lng: Double = _
5151

52-
private var admins: Array[String] = Array()
52+
private var admins: Array[String] = Array("112997031510415584062_google")
5353

5454
this.fields = hm
5555

server/app/utils/JsonUtils.scala

+15-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import java.util.HashMap
4242
import java.util.List
4343

4444
import com.couchbase.client.java.document.json.JsonObject
45-
import play.api.libs.json.JsValue
45+
import play.api.libs.json.{JsArray, JsValue}
4646

4747
object JsonUtils {
4848

@@ -96,8 +96,20 @@ object JsonUtils {
9696
}
9797
val notFound = new util.ArrayList[String]()
9898
for (k <- keys) {
99-
val value = (json \ k).toString
100-
if (value == null || 0 == value.trim().length) notFound.add(k)
99+
val value = json \ k
100+
if (value == null)
101+
notFound.add(k)
102+
else {
103+
val svalue = value.asOpt[String].getOrElse("")
104+
if (svalue.isEmpty) {
105+
val avalue = value.asOpt[JsArray].orNull
106+
if (avalue == null) {
107+
val ovalue = value.asOpt[JsValue].orNull
108+
if (ovalue == null)
109+
notFound.add(k)
110+
}
111+
}
112+
}
101113
}
102114
notFound
103115
}

0 commit comments

Comments
 (0)