diff options
author | Grzegorz Kossakowski <grek@google.com> | 2009-08-14 18:32:38 -0700 |
---|---|---|
committer | Grzegorz Kossakowski <grek@google.com> | 2009-08-14 18:32:38 -0700 |
commit | 489874e17eca60e806f0c7d92838ac55884d02c2 (patch) | |
tree | d4edcf93d9971c1674169fb9a79102f42db05ec8 | |
parent | 73c749b3c9b2d2bd76dd32d0b66bbc61fe304de3 (diff) | |
download | gimd-489874e17eca60e806f0c7d92838ac55884d02c2.tar.gz |
Introduced concept of Handlers that are returned along with query results.
MessageQuery returns List[(Handler, U)] instead of just List[U]. The
purpose of returning handlers is to keep track of mapping between instance
of U and relevant place in Gimd's datastructure. This allows to implement
casual operations like delete, add, modify in an efficient and easy way.
Handlers can be implemented in a specific way to a given Database
implementation which can carry additional information useful for
optimization purposes.
Adapted MessageQueryTestCases to these changes. Apart from changes strictly
related to that adaption SimpleMessageType and ChildType has been changed
to be objects as they are really always singletons carrying configuration
only.
Signed-off-by: Grzegorz Kossakowski <grek@google.com>
7 files changed, 127 insertions, 17 deletions
diff --git a/src/main/scala/com/google/gimd/jgit/JGitFileHandler.scala b/src/main/scala/com/google/gimd/jgit/JGitFileHandler.scala new file mode 100644 index 0000000..6e6c31b --- /dev/null +++ b/src/main/scala/com/google/gimd/jgit/JGitFileHandler.scala @@ -0,0 +1,17 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gimd.jgit + +case class JGitFileHandler[T](file: JGitFile[T]) extends query.FileHandler(file) diff --git a/src/main/scala/com/google/gimd/jgit/JGitMessageHandler.scala b/src/main/scala/com/google/gimd/jgit/JGitMessageHandler.scala new file mode 100644 index 0000000..4c7e170 --- /dev/null +++ b/src/main/scala/com/google/gimd/jgit/JGitMessageHandler.scala @@ -0,0 +1,21 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gimd.jgit + +import query.{Handler, MessageHandler} + +case class JGitMessageHandler[T](parent: Either[JGitFileHandler[T], JGitMessageHandler[T]], + message: Message) + extends MessageHandler(parent.fold[Handler](identity, identity), message) diff --git a/src/main/scala/com/google/gimd/query/FileHandler.scala b/src/main/scala/com/google/gimd/query/FileHandler.scala new file mode 100644 index 0000000..1546db9 --- /dev/null +++ b/src/main/scala/com/google/gimd/query/FileHandler.scala @@ -0,0 +1,19 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gimd.query + +import file.File + +abstract class FileHandler[T](file: File[T]) extends Handler diff --git a/src/main/scala/com/google/gimd/query/Handler.scala b/src/main/scala/com/google/gimd/query/Handler.scala new file mode 100644 index 0000000..c0840a4 --- /dev/null +++ b/src/main/scala/com/google/gimd/query/Handler.scala @@ -0,0 +1,17 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gimd.query + +abstract class Handler diff --git a/src/main/scala/com/google/gimd/query/MessageHandler.scala b/src/main/scala/com/google/gimd/query/MessageHandler.scala new file mode 100644 index 0000000..5b83e64 --- /dev/null +++ b/src/main/scala/com/google/gimd/query/MessageHandler.scala @@ -0,0 +1,21 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gimd.query + +abstract class MessageHandler(parent: Handler, message: Message) extends Handler + +object MessageHandler { + type Factory = ((Handler, Message) => MessageHandler) +} diff --git a/src/main/scala/com/google/gimd/query/MessageQuery.scala b/src/main/scala/com/google/gimd/query/MessageQuery.scala index ec3e0ca..967dd33 100644 --- a/src/main/scala/com/google/gimd/query/MessageQuery.scala +++ b/src/main/scala/com/google/gimd/query/MessageQuery.scala @@ -16,20 +16,24 @@ package com.google.gimd.query object MessageQuery { - def simpleQuery[U, W](ut: UserType[W], m: Message, p: Predicate[U]): List[U] = { + def simpleQuery[U, W](ut: UserType[W], m: Message, p: Predicate[U], parent: Handler, + factory: MessageHandler.Factory): List[(MessageHandler,U)] = { + val handler = factory(parent, m) + val matched = if (p.isType(ut.userTypeClass)) { val value = ut.toUserObject(m).asInstanceOf[U] if (p.isMatch(value)) - List(value) + List((handler, value)) else Nil } else Nil - val childMatches = ut.children.flatMap( - (nm: NestedMember[_]) => Message.filterMessageFields(m.filter(_.name == nm.name)). - flatMap(simpleQuery(nm.userType, _, p)) - ) + val childMatches = (for { + nm <- ut.children + childMessageFields = Message.filterMessageFields(m.all(nm.name)) + matches = childMessageFields.flatMap(simpleQuery(nm.userType, _, p, handler, factory)) + } yield matches).flatMap(identity[List[(MessageHandler,U)]]) matched ++ childMatches } diff --git a/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala b/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala index 2753320..4b49ca7 100644 --- a/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala +++ b/src/test/scala/com/google/gimd/query/MessageQueryTestCase.scala @@ -14,7 +14,7 @@ package com.google.gimd.query - +import file.{File, FileType} import org.junit.Test import org.junit.Assert._ @@ -22,7 +22,7 @@ class MessageQueryTestCase { case class Child(name: String, property1: Boolean) - class ChildType extends UserType[Child] { + object ChildType extends UserType[Child] { def toMessageBuffer(child: Child) = (new MessageBuffer()) ++ List(Field("name", child.name), Field("property1", child.property1.toString)) def toUserObject(m: Message): Child = @@ -32,18 +32,21 @@ class MessageQueryTestCase { case class SimpleMessage(name: String, children: List[Child]) - class SimpleMessageType extends UserType[SimpleMessage] { + object SimpleMessageType extends UserType[SimpleMessage] { def toMessageBuffer(sm: SimpleMessage) = (new MessageBuffer()) ++ List(Field("name", sm.name)) def toUserObject(m: Message): SimpleMessage = { - val childType = new ChildType() - val children = m.all("child").map(_.messageField.value).map(childType.toUserObject(_)) + val children = m.all("child").map(_.messageField.value).map(ChildType.toUserObject(_)) val name = m.one("name").stringField.value new SimpleMessage(name, children.toList) } - override def children = Seq(new NestedMember("child", new ChildType())) + override def children = Seq(new NestedMember("child", ChildType)) } + object MockParentHandler extends Handler + case class MockMessageHandler(parent: Handler, message: Message) + extends MessageHandler(parent, message) + @Test def simpleQuery = { import Predicate.functionLiteral2Predicate @@ -51,11 +54,19 @@ class MessageQueryTestCase { this.getClass.getResourceAsStream("simpleMessage.gimd") ) val message = gimd.text.Parser.parse(reader) - val queryResult = MessageQuery.simpleQuery(new SimpleMessageType(), message, - (child: Child) => child.property1 == true) - val expectedResult = List(Child("Child1", true), Child("Child3", true), - Child("Child5", true)) - assertEquals(expectedResult, queryResult) + val factory = MockMessageHandler(_, _) + val messageHandler = factory(MockParentHandler, message) + + val predicate = (child: Child) => child.property1 == true + val queryResult = MessageQuery.simpleQuery(SimpleMessageType, message, predicate, + MockParentHandler, factory) + + val expectedChildren = List(Child("Child1", true), Child("Child3", true), Child("Child5", true)) + val expectedMessages = expectedChildren.map(ChildType.toMessageBuffer(_).readOnly) + val handlers = expectedMessages.map(factory(messageHandler, _)) + val expectedResult = handlers zip expectedChildren + + assertEquals(Set(expectedResult: _*), Set(queryResult: _*)) } } |