1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from cache_chain_object_store import CacheChainObjectStore
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from environment import GetAppVersion
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from memcache_object_store import MemcacheObjectStore
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from test_object_store import TestObjectStore
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from persistent_object_store import PersistentObjectStore
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)_unspecified = object()
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class ObjectStoreCreator(object):
14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  '''Creates ObjectStores with a namespacing and behaviour configuration.
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  The initial configuration is specified on object store construction. When
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  creating ObjectStores via Create this configuration can be overridden (or
18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  via the variants of Create which do this automatically).
19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  '''
20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  def __init__(self,
21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)               # TODO(kalman): rename start_dirty?
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               start_empty=_unspecified,
23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               # Override for testing. A custom ObjectStore type to construct
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               # on Create(). Useful with TestObjectStore, for example.
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               store_type=None,
26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               # Override for testing. Whether the ObjectStore type specified
27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               # with |store_type| should be wrapped e.g. with Caching. This is
28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               # useful to override when specific state tests/manipulations are
29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               # being done on the underlying object store.
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)               disable_wrappers=False):
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if start_empty is _unspecified:
32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      raise ValueError('start_empty must be specified (typically False)')
33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    self._start_empty = start_empty
34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    self._store_type = store_type
35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if disable_wrappers and store_type is None:
36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      raise ValueError('disable_wrappers much specify a store_type')
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    self._disable_wrappers = disable_wrappers
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  @staticmethod
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  def ForTest(start_empty=False,
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              store_type=TestObjectStore,
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              disable_wrappers=True):
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return ObjectStoreCreator(start_empty=start_empty,
44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              store_type=store_type,
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              disable_wrappers=disable_wrappers)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  def Create(self,
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             cls,
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             category=None,
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             # Override any of these for a custom configuration.
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             start_empty=_unspecified,
52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             app_version=_unspecified):
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    # Resolve namespace components.
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if start_empty is not _unspecified:
55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      start_empty = bool(start_empty)
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else:
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      start_empty = self._start_empty
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if app_version is _unspecified:
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      app_version = GetAppVersion()
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    # Reserve & and = for namespace separators.
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    for component in (category, app_version):
63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if component and ('&' in component or '=' in component):
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        raise ValueError('%s cannot be used in a namespace')
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    namespace = '&'.join(
67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        '%s=%s' % (key, value)
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        for key, value in (('class', cls.__name__),
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           ('category', category),
70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           ('app_version', app_version))
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if value is not None)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if self._disable_wrappers:
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return self._store_type(namespace, start_empty=start_empty)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if self._store_type is not None:
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      chain = (self._store_type(namespace),)
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else:
79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      chain = (MemcacheObjectStore(namespace), PersistentObjectStore(namespace))
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return CacheChainObjectStore(chain, start_empty=start_empty)
81