1
+ /**
2
+ * Copyright (C) 2012 - RandomCoder <randomcoder@randomcoding.co.uk>
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Affero General Public License as
6
+ * published by the Free Software Foundation, either version 3 of the
7
+ * License, or (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ *
17
+ * Contributors:
18
+ * RandomCoder <randomcoder@randomcoding.co.uk> - initial API and implementation and/or initial documentation
19
+ */
20
+ package uk .co .randomcoding .scala .util .lift .mongodb
21
+
22
+ import org .bson .types .ObjectId
23
+ import net .liftweb .mongodb .record .MongoMetaRecord
24
+ import net .liftweb .mongodb .record .MongoRecord
25
+ import net .liftweb .mongodb .record .field .ObjectIdPk
26
+ import com .foursquare .rogue .Rogue
27
+
28
+ /**
29
+ * Provides common functionality for record companion objects to find matching records and find records by id.
30
+ *
31
+ * Requires that the type `T extend MongoRecord[T] with ObjectIdPk[T]`
32
+ *
33
+ * Users of this trait are required to implement the `findById(org.bson.types.ObjectId)` and
34
+ * `matchingRecord(T)` methods.
35
+ *
36
+ * @author RandomCoder <randomcoder@randomcoding.co.uk>
37
+ *
38
+ * Created On: 29 Jul 2012
39
+ */
40
+ trait BaseMongoRecordObject [T <: MongoRecord [T ] with ObjectIdPk [T ]] {
41
+
42
+ /**
43
+ * Find a record by its object id - typically its `id` or `_id` field.
44
+ *
45
+ * Should return `Some(record)` if there is a record of ths type with the given object id or `None` if there is not.
46
+ */
47
+ def findById (oid : ObjectId ): Option [T ]
48
+
49
+ /**
50
+ * Find a record that matched the input one, if one is present in the database.
51
+ *
52
+ * The definition of a match is left up to the implementer, but it is often good to be
53
+ * consistent with the companion classes `equals` method.
54
+ *
55
+ * This method is only required to return a single match, even if there are multiple matches in the database,
56
+ * so the exact match strategy and precedence is left up to the implementor.
57
+ *
58
+ * As this is primarily used (by me) to check that there are no matching records present, then this is sufficient.
59
+ *
60
+ * @return An optional record if there is a match found, or `None` if there are no records that match.
61
+ */
62
+ def matchingRecord (t : T ): Option [T ]
63
+
64
+ /**
65
+ * Updates the record with the given `ObjectId` with the values from the new record.
66
+ *
67
+ * If there is no record with the given `ObjectId` then this method '''should not''' add the
68
+ * new record, it should return `None`.
69
+ *
70
+ * If there is a record with the given `ObjectId` then that record should have all its values set to the
71
+ * ones in the new record. The updated record should be returned inside an Option.
72
+ */
73
+ final def update (oid : ObjectId , newT : T ): Option [T ] = findById(oid) match {
74
+ case Some (record) => newT.id(oid).saveTheRecord
75
+ case _ => None
76
+ }
77
+
78
+ /**
79
+ * Remove the record with the given `ObjectId` from the collection of this type.
80
+ *
81
+ * @return The removed record, or if there is no record with the given `ObjectId`,
82
+ * or if the remove operation fails `None`
83
+ */
84
+ final def remove (oid : ObjectId ): Option [T ] = findById(oid) match {
85
+ case Some (record) => if (record.delete_!) Some (record) else None
86
+ case _ => None
87
+ }
88
+
89
+ /**
90
+ * Finds a ''matching'' record in the database.
91
+ *
92
+ * A ''match'' is made if:
93
+ *
94
+ * - There is another record with the same Object Id
95
+ * - A record is returned from the [[uk.co.randomcoding.scala.util.lift.mongodb.BaseMongoRecordObject#matchingRecord(T) ]]
96
+ *
97
+ * @return The optional match, or `None` if there is no match
98
+ */
99
+ final def findMatching (t : T ): Option [T ] = findById(t.id.get) match {
100
+ case Some (r) => Some (r)
101
+ case _ => matchingRecord(t)
102
+ }
103
+
104
+ /**
105
+ * Add a new record to the database unless there is a matching record.
106
+ *
107
+ * If there is a matching record then '''do not''' add the new one.
108
+ *
109
+ * A match is determined by calling the `findMatching(T)` method,
110
+ * with a return value of Some(t) indicating there is a matching record.
111
+ *
112
+ * @return The optionally added record, or if there is a match then the matched record.
113
+ */
114
+ final def add (t : T ): Option [T ] = findMatching(t) match {
115
+ case Some (t) => Some (t)
116
+ case _ => t.saveTheRecord
117
+ }
118
+ }
0 commit comments