2 # Thierry Parmentelat - INRIA
5 # just a placeholder for storing accessor-related tag checkers
6 # this is filled by the accessors factory
8 # NOTE. If you ever come to manually delete a TagType that was created
9 # by the Factory, you need to restart your python instance / web server
10 # as the cached information then becomes wrong
12 from PLC.Debug import log
14 from PLC.TagTypes import TagTypes, TagType
15 from PLC.Roles import Roles, Role
18 class Accessor (object) :
19 """This is placeholder for storing accessor-related tag checkers.
20 Methods in this class are defined by the accessors factory
22 This is implemented as a singleton, so we can cache results over time"""
28 def __init__ (self, api):
32 self.hash_name_to_role=dict ( [ (role['name'],role) for role in Roles(api)] )
34 def has_cache (self,tagname): return self.cache.has_key(tagname)
35 def get_cache (self,tagname): return self.cache[tagname]
36 def set_cache (self,tagname,tag_type): self.cache[tagname]=tag_type
38 def locate_or_create_tag (self, tagname, category, description, roles, enforce=False):
39 "search tag type from tagname & create if needed"
42 if self.has_cache (tagname):
43 return self.get_cache(tagname)
45 tag_types = TagTypes (self.api, {'tagname':tagname})
47 tag_type = tag_types[0]
48 # enforce should only be set by the 'service plc start accessors' sequence
51 tag_type.update({'category':category,'description':description})
53 roles_to_add = set(roles).difference(set(tag_type['roles']))
54 for rolename in roles_to_add:
55 tag_type.add_role(self.hash_name_to_role[rolename])
56 roles_to_delete = set(tag_type['roles']).difference(set(roles))
57 for rolename in roles_to_delete:
58 tag_type.remove_role(self.hash_name_to_role[rolename])
60 # this goes in boot.log ...
61 print >> log, "WARNING, Could not enforce tag type, tagname=%s\n"%tagname
62 traceback.print_exc(file=log)
65 # not found: create it
66 tag_type_fields = {'tagname':tagname,
67 'category' : category,
68 'description' : description}
69 tag_type = TagType (self.api, tag_type_fields)
73 role_obj=Roles (self.api, role)[0]
74 tag_type.add_role(role_obj)
76 # xxx todo find a more appropriate way of notifying this
77 print "Accessor.locate_or_create_tag: Could not add role %r to tag_type %s"%(role,tagname)
78 self.set_cache(tagname,tag_type)
81 # a locator is a function that retrieves - or creates - a tag_type instance
83 def register_tag_locator (name, tag_locator):
84 Accessor.tag_locators[name]=tag_locator
87 def retrieve_tag_locator (name):
88 return Accessor.tag_locators[name]
90 # this is designed to be part of the 'service plc start' sequence
91 # it ensures the creation of all the tagtypes defined
92 # in the various accessors, and enforces consistency to the DB
93 # it's not easy to have define_accessors do this because at
94 # load-time as we do not have an instance of API yet
95 def run_all_tag_locators (self):
96 for (name, tag_locator) in Accessor.tag_locators.items():
97 tag_locator(self,enforce=True)
100 # make it a singleton so we can cache stuff in there over time
101 def AccessorSingleton (api):
102 if not Accessor._instance:
103 Accessor._instance = Accessor(api)
104 return Accessor._instance