16c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen# Copyright (C) 2010 Google Inc. All rights reserved.
2cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#
3cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# Redistribution and use in source and binary forms, with or without
4cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# modification, are permitted provided that the following conditions are
5cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# met:
6cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#
7cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#     * Redistributions of source code must retain the above copyright
8cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# notice, this list of conditions and the following disclaimer.
9cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#     * Redistributions in binary form must reproduce the above
10cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# copyright notice, this list of conditions and the following disclaimer
11cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# in the documentation and/or other materials provided with the
12cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# distribution.
13cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#     * Neither the name of Google Inc. nor the names of its
14cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# contributors may be used to endorse or promote products derived from
15cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# this software without specific prior written permission.
16cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#
17cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
296c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenfrom google.appengine.ext import db
30cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochfrom model.queuepropertymixin import QueuePropertyMixin
32cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochclass WorkItems(db.Model, QueuePropertyMixin):
356c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    queue_name = db.StringProperty()
366c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    item_ids = db.ListProperty(int)
376c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    date = db.DateTimeProperty(auto_now_add=True)
38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    @classmethod
402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    def key_for_queue(cls, queue_name):
412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return "work-items-%s" % (queue_name)
422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    @classmethod
442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    def lookup_by_queue(cls, queue_name):
452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return cls.get_or_insert(key_name=cls.key_for_queue(queue_name), queue_name=queue_name)
462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    def display_position_for_attachment(self, attachment_id):
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        """Returns a 1-based index corresponding to the position
49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        of the attachment_id in the queue.  If the attachment is
50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        not in this queue, this returns None"""
51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if attachment_id in self.item_ids:
52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return self.item_ids.index(attachment_id) + 1
53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return None
54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    @staticmethod
56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    def _unguarded_add(key, attachment_id):
57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        work_items = db.get(key)
58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if attachment_id in work_items.item_ids:
59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return
60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        work_items.item_ids.append(attachment_id)
61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        work_items.put()
62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
6328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    # Because this uses .key() self.is_saved() must be True or this will throw NotSavedError.
64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    def add_work_item(self, attachment_id):
65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        db.run_in_transaction(self._unguarded_add, self.key(), attachment_id)
66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    @staticmethod
68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    def _unguarded_remove(key, attachment_id):
69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        work_items = db.get(key)
70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if attachment_id in work_items.item_ids:
71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            # We should never have more than one entry for a work item, so we only need remove the first.
72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            work_items.item_ids.remove(attachment_id)
73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        work_items.put()
74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
7528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    # Because this uses .key() self.is_saved() must be True or this will throw NotSavedError.
76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    def remove_work_item(self, attachment_id):
77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        db.run_in_transaction(self._unguarded_remove, self.key(), attachment_id)
78