Package advene :: Package model :: Module package
[hide private]
[frames] | no frames]

Source Code for Module advene.model.package

  1  # 
  2  # Advene: Annotate Digital Videos, Exchange on the NEt 
  3  # Copyright (C) 2008 Olivier Aubert <olivier.aubert@liris.cnrs.fr> 
  4  # 
  5  # Advene is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation; either version 2 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Advene is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Advene; if not, write to the Free Software 
 17  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 18  # 
 19  """A package to manipulate elements from the Advene model. 
 20  """ 
 21   
 22  import os 
 23  import sys 
 24  import urllib 
 25  import re 
 26   
 27  import xml.sax 
 28   
 29  import util.uri 
 30   
 31  from util.auto_properties import auto_properties 
 32   
 33  import advene.core.config as config 
 34  import _impl 
 35  import advene.model.annotation as annotation 
 36  import advene.model.modeled as modeled 
 37  import advene.model.query as query 
 38  import advene.model.schema as schema 
 39  import advene.model.view as view 
 40  import advene.model.viewable as viewable 
 41  from advene.model.zippackage import ZipPackage 
 42  from advene.util.expat import PyExpat 
 43   
 44  from advene.model.bundle import StandardXmlBundle, ImportBundle, InverseDictBundle, SumBundle 
 45  from advene.model.constants import * 
 46  from advene.model.exception import AdveneException 
 47   
 48  # the following constant is used as a default value in in Package.__init__ 
 49  # to know whether the passed uri must be used to get a stream. 
 50  # (source=None has a different meaning) 
 51  # FIXME: should be a "new" parameter in Package.__init__ 
 52  _get_from_uri = object() 
 53   
54 -class Package(modeled.Modeled, viewable.Viewable.withClass('package'), 55 _impl.Authored, _impl.Dated, _impl.Titled, 56 annotation.AnnotationFactory, 57 annotation.RelationFactory, 58 schema.SchemaFactory, 59 query.QueryFactory, 60 view.ViewFactory, 61 ):
62 63 """A package is the container of all the elements of an annotation 64 (schemas, types, annotations, relations, views, queries). It 65 provides factory methods to create attached annotations, views, ...""" 66 67 __metaclass__ = auto_properties 68
69 - def __init__(self, uri, source=_get_from_uri, importer=None):
70 """Calling the constructor with just a URI tries to read the package 71 from this URI. This can be overidden by providing explicitly the 72 source parameter (a URL or a stream). 73 Providing None for the source parameter creates a new Package. 74 """ 75 self.meta_cache={} 76 if isinstance(uri, unicode): 77 uri=uri.encode(sys.getfilesystemencoding()) 78 if re.match('[a-zA-Z]:', uri): 79 # Windows drive: notation. Convert it to 80 # a more URI-compatible syntax 81 uri=urllib.pathname2url(uri) 82 self.__uri = uri 83 self.__importer = importer 84 # Possible container 85 self.__zip = None 86 abs_uri = self.getUri (absolute=True) 87 88 if importer: 89 importer.__pkg_cache[abs_uri] = self 90 self.__pkg_cache = importer.__pkg_cache 91 else: 92 self.__pkg_cache = {abs_uri:self} 93 94 element = None 95 if source is None: 96 element = self._make_model() 97 else: 98 reader = PyExpat.Reader() 99 if source is _get_from_uri: 100 # Determine the package format (plain XML or AZP) 101 # FIXME: should be done by content rather than extension 102 if abs_uri.lower().endswith('.azp') or abs_uri.endswith('/'): 103 # Advene Zip Package. Do some magic. 104 self.__zip = ZipPackage(abs_uri) 105 f=urllib.pathname2url(self.__zip.getContentsFile()) 106 element = reader.fromUri("file://" + f).documentElement 107 else: 108 element = reader.fromUri(abs_uri).documentElement 109 elif hasattr(source, 'read'): 110 element = reader.fromStream(source).documentElement 111 else: 112 if re.match('[a-zA-Z]:', source): 113 # Windows drive: notation. Convert it to 114 # a more URI-compatible syntax 115 source=urllib.pathname2url(source) 116 source_uri = util.uri.urljoin ( 117 'file:%s/' % urllib.pathname2url (os.getcwd ()), 118 str(source) 119 ) 120 121 if source_uri.lower().endswith('.azp') or source_uri.endswith('/'): 122 # Advene Zip Package. Do some magic. 123 self.__zip = ZipPackage(source_uri) 124 f=urllib.pathname2url(self.__zip.getContentsFile()) 125 element = reader.fromUri("file://" + f).documentElement 126 else: 127 element = reader.fromUri(source_uri).documentElement 128 129 modeled.Modeled.__init__(self, element, None) 130 131 self.__imports = None 132 self.__annotations = None 133 self.__queries = None 134 self.__relations = None 135 self.__schemas = None 136 self.__views = None
137
138 - def close(self):
139 if self.__zip: 140 self.__zip.close() 141 return
142
143 - def __str__(self):
144 """Return a nice string representation of the object.""" 145 return "Package (%s)" % self.__uri
146
147 - def _make_model(self):
148 """Build a new empty annotation model""" 149 di = xml.dom.DOMImplementation.DOMImplementation() 150 doc = di.createDocument(adveneNS, "package", None) 151 152 elt = doc.documentElement 153 elt.setAttributeNS(xmlNS, "xml:base", unicode(self.__uri)) 154 elt.setAttributeNS(xmlnsNS, "xmlns", adveneNS) 155 elt.setAttributeNS(xmlnsNS, "xmlns:xlink", xlinkNS) 156 elt.setAttributeNS(xmlnsNS, "xmlns:dc", dcNS) 157 elt.setAttributeNS(dcNS, "dc:creator", "") 158 159 elt.appendChild(doc.createElementNS(adveneNS, "imports")) 160 elt.appendChild(doc.createElementNS(adveneNS, "annotations")) 161 elt.appendChild(doc.createElementNS(adveneNS, "queries")) 162 elt.appendChild(doc.createElementNS(adveneNS, "schemas")) 163 elt.appendChild(doc.createElementNS(adveneNS, "views")) 164 return elt
165
166 - def _get_cached(self, uri):
167 """Return a cached version of the package designated by "uri" """ 168 return self.__pkg_cache.get(uri, None)
169
170 - def getOwnerPackage(self):
171 """Return this package. Used for breaking recursivity in the parenthood tree.""" 172 return self
173
174 - def getAccessPath(self):
175 if self.__importer: 176 r = list(self.__importer.getAccessPath()) 177 r.append(self) 178 return tuple(r) 179 else: 180 return (self,)
181
182 - def getRootPackage(self):
183 if self.__importer: 184 return self.__importer.getRootPackage() 185 else: 186 return self
187
188 - def getUri(self, absolute=True, context=None):
189 """ 190 Return the URI of the package. 191 192 Parameter if _absolute_ is _True_, the URI will be forced absolute. 193 If not, and if _context_ is _None_, the URI will be resolved with 194 respect to the root package URI, whatever its stored form (absolute or 195 relative). 196 If context is given and is a (direct or indirect) importer package, 197 the URI will be resolved with respect to the context URI, whatever its 198 stored form (absolute or relative). 199 200 You would probably rather use the uri read-only property, unless you 201 want to set the parameter _absolute_. 202 """ 203 uri = self.__uri 204 205 if not absolute and context is self: 206 return '' 207 208 importer = self.__importer 209 if importer is not None: 210 uri =