ZSI-2.1-a1/0000755000175100017510000000000010712455110010512 5ustar zsizsiZSI-2.1-a1/samples/0000755000175100017510000000000010712455110012156 5ustar zsizsiZSI-2.1-a1/samples/README0000644000175100017510000000014307400741162013041 0ustar zsizsiSample code, no copyright; use as you see fit. ZSI tips and techniques. Self-commented, if at all. ZSI-2.1-a1/samples/WSGI/0000755000175100017510000000000010712455110012727 5ustar zsizsiZSI-2.1-a1/samples/WSGI/echo_client.py0000644000175100017510000000075310712205420015557 0ustar zsizsi# # # from EchoServer_client import * import sys, time TRACE=None loc = EchoServerLocator() port = loc.getEchoServer(url='http://localhost:8000/echo', tracefile=TRACE) msg = EchoRequest() msg.Value = 1 rsp = port.Echo(msg) print "INTEGER: ", rsp.Value msg.Value = "HI" rsp = port.Echo(msg) print "STRING: ", rsp.Value msg.Value = 1.10000 rsp = port.Echo(msg) print "FLOAT: ", rsp.Value msg.Value = dict(milk=dict(cost=3.15, unit="gal")) rsp = port.Echo(msg) print "DICT: ", rsp.Value ZSI-2.1-a1/samples/WSGI/README0000644000175100017510000000134010712205420013602 0ustar zsizsi================== WSGI Code is unstable, and currently server-side stubs are NOT generated for you. ================== python wsgi example run the SimpleEcho service out of python's wsgi ================== % ./echo_setup.sh % python echo_server.py >& server.log & [1] 3455 % python echo_client.py INTEGER: 1 STRING: HI FLOAT: 1.1 DICT: {'milk': {'cost': 3.1499999999999999, 'unit': 'gal'}} ================== twisted.web2.wsgi example run the SimpleEcho service out of twisted's web2 wsgi ================== % ./echo_setup.sh % python echo_server.py twisted >& server.log & [1] 3459 % python echo_client.py INTEGER: 1 STRING: HI FLOAT: 1.1 DICT: {'milk': {'cost': 3.1499999999999999, 'unit': 'gal'}} ZSI-2.1-a1/samples/WSGI/echo_server.py0000644000175100017510000000272010712205420015603 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: __init__.py 1132 2006-02-17 01:55:41Z boverhof $ ########################################################################### import sys from EchoServer_client import * from ZSI.twisted.wsgi import SOAPApplication, soapmethod, SOAPHandlerChainFactory class EchoService(SOAPApplication): factory = SOAPHandlerChainFactory wsdl_content = dict(name='Echo', targetNamespace='urn:echo', imports=(), portType='') @soapmethod(EchoRequest.typecode, EchoResponse.typecode, operation='Echo', soapaction='Echo') def soap_Echo(self, request, response, **kw): response = request return request,response def main(): from wsgiref.simple_server import make_server, demo_app from ZSI.twisted.wsgi import WSGIApplication application = WSGIApplication() httpd = make_server('', 8000, application) application['echo'] = EchoService() httpd.serve_forever() def main_twisted(): from ZSI.twisted.wsgi import test, WSGIApplication app = WSGIApplication() app['echo'] = EchoService() test(app, port=8000) if __name__ == '__main__': if len(sys.argv) == 1: main() else: var = sys.argv[1] try: getattr(sys.modules[__name__], 'main_%s' %var)(*sys.argv[2:]) except Exception, ex: print>>sys.stderr, ex sys.exit(1) ZSI-2.1-a1/samples/WSGI/SimpleEcho.wsdl0000644000175100017510000000311410712205420015646 0ustar zsizsi ZSI-2.1-a1/samples/WSGI/echo_setup.py0000755000175100017510000000004510712205420015436 0ustar zsizsi#!/bin/sh wsdl2py -b SimpleEcho.wsdl ZSI-2.1-a1/setup.cfg0000644000175100017510000000034310712455110012333 0ustar zsizsi[bdist_rpm] release = 1 requires = doc_files = README CHANGES doc/zsi.css doc/zsi.html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [version] major = 2 candidate = 0 beta = 0 minor = 1 alpha = 1 patchlevel = 0 ZSI-2.1-a1/Copyright0000644000175100017510000000056407730126512012421 0ustar zsizsiUgh. I hate paperwork. :) Most of ZSI is covered by an MIT/X Consortium copyright, as found in doc/zsi.tex. The wsdl2python tools are covered by an LBNL BSD-style license, as found in ZSI/LBNLCopyright. Most of the code in wstools is covered by the Zope Public License, which is a certified open source license that is GPL compatible. See ZSI/wstools/ZPL for details. ZSI-2.1-a1/CHANGES0000644000175100017510000002363410712434035011520 0ustar zsizsiChange for xxx released xxx: - Make XMLSchema.py work in cases where threading isn't built in - Add client-side Cookie Support (Jorgen Frojk Kjaersgaard) - For cookies, getheaders() is Python 2.3; use getallmatchingheaders - In SoapWriter, put nsdecls on body, not envelope - Record facets (restrictions) in XMLSchema.py - Remove Send()'s kwargs out of _args list Change for 2.1.0_a1 released 31-Oct-2007: - No PyXML Dependency, use minidom by default (much faster) - samples/WSGI, server and client examples using python wsgi and twisted.web2.wsgi Change for 2.0.0 released xxx: - no more wsdl2dispatch, wsdl2py does it all - simplified and consolidated various wsdl2py script options - wsdl2py added some soapheader support to client code. - wsdl2py changed Locator accessors names to match the "port.name" rather than the "portType.name" - wsdl2py changed generated Binding class names to match the "binding.name" rather than the "portType.name" Change for 2.0.0rc3 released xxx: - Updated ZSI developers guide - Added ZSI wsdl2py users guide - Added support for setuptools in setup script. If setuptools is installed use it, else revert to distutils. - Removed "requestclass" keyword argument to Binding.Send - simplified and retooled Binding/NamedParamBinding and dispatch, added "typesmodule" back into Binding. Now it's mirror image of dispatch. - Microseconds to TCtime - BUG [ 1525567 ] Amazon ECommerce Issues: local element declarations overriding global element declarations with the same name within the same namespace. - new module "schema", contains "all" the code for dealing with global Schema instance. Change for 2.0.0rc2 released 28-March-2006: - Replace many/most id() with _get_idstr() to hide negative numbers - Added ZSI.twisted package w/client and server, requires Python 2.4 - If Python >= 2.4, build/install ZSI.twisted package - Add Typecode.typed to control xsi:type data system-wide - Replace many/most id() with _get_idstr() to hide negative numbers Changes for 1.7 released 16-Feb-2005: - Add support for jonpy (http://jonpy.sourceforge.net) FastCGI courtesy of Guan Yang - Avoid FutureWarning with Python 2.3.x - Make sure generated ID values are legal IDs under Python 2.3 and newer - Don't need _textunprotect (via Grahame Bowland) - Fix ZSI.wstools.XMLname.toXMLname() so namespace prefix isn't lost Changes for 1.5, released 10-Mar-2004: - TypeCode honoring for response parameters - String adherence to wsdl for request/response params via ServiceProxy - wsdl2py bug fixes - Numerous bug fixes Changes for 1.4.1 released 11-Nov-2003: - Make "docstyle" work for returning data, too (Alexis Marrero-Narvaez) - TC.Struct.typed will output xsi:type parameter now. - Numerous bug fixes Changes for 1.4, released 09-Sep-2003: - Ouput XML prolog in SoapWriter - Added nsdict parameter to dispatch.AsCGI and dispatch.AsServer - Fixed bug where xmlns attribute was included in closing elements - Added support for "wrapped" complexTypes in response messages - TypeCode enabled classes now support parameters in the constructor - Automatic parsing of ComplexTypes in response messages - WSDL Parsing and operation invocation via ServiceProxy - Tuple returned from dates and times (instead of a list) - Arrays of ComplexTypes can now be deserialized - User can specify which module contains complex type definitions - Mod_Python support for dispatch to multiple functions within a module - In client.py, try to get port from URL if available (Wichert Akkerman) - Add ZSIException as parent for ZSI exception classes, FaultException class, and raise that if we get unexpected fault in client (Wichert) - Add auth_header keyword param to client Send method (Phillip Pearson) - Added support for conversion between WSDL and Python classes Changes for 1.3, released xx-May-2002: - Fixed parsing bug evidenced by dW article - Style: use defaulted parameters not kw.get() - Style: avoid __dict__ and use standard attribute fetch - Fix dispatch to actually dispatch (Laroche Denis) - Fix some typo's (thanks adalke) - In TCCompound, include class name in exception, not just object name - ZSI homepage is at pywebsvcs.sf.net now, not www.zolera.com (sigh...) - Add nsdict parameter to dispatch's AsServer() Changes for 1.2, released 05-Mar-2002: - Replace with X copyright; GNU compatible now - newver writes date into version.tex - Use "raise x(a)" always, never "raise x, a" (that's oldschool:) - Don't delete tb in FaultFromException; add try/except for robustness - Ignore -1 values for DST, etc., in Python time tuples - Remove needless __init__ when just calling parent __init__ - Added 'undeclared' parameter to TC.Array - Added 'repeatable' parameter to TC.TypeCode - Add 'aname' parameter to TC.Typecode - Move 'unique' keyword from TC.String up to TC.TypeCode - Add 'wrapped' keyword to TC.XML - Added _find_attr lambda - Had path backwards in backtrace, add [1] to uniqify when needed - Complain if extra elements in TC.Struct and hasextras=0 - Duration.lex_pattern was wrong (old schema) - Newline after output gDateTime, not a space - Newline before Base64string - Incorrect test in RegisterType - Add Boolean.serialize - Anchor all TCtime lex_pattern's - Allow class object (not just class name) in TC.seriallist - TC.Void can serialize None (useful for TC.Any) - RegisterType(TC.Void) - Fix consistency and interop in dispatching - Array interop fix - SOAPAction header needs quotes - Add Apache SOAPArray - Properly use 'ns' in client to set default namespace - Convert client.py to use "new" HTTP objects - Sign isn't optional on numeric timezones in dates - Document limits on date/time conversions. - Add TC.XML.copyit and 'copyit' keyword to constructor - Spelt EvaluateException wrong in dispatch.py - xsi:nil not xsi:null in TC.Void - Address issues with client/dispatch and None - Use formatted output, not strftime - TC.Any defaults to optional if not set, for None - TC.Any tries to serialize its datatype as its tagname - Add 'typed' support to TC.Any - Allow keyword args in Fault.AsSOAP, passed to SoapWriter ctor - SoapWriter's self.memo always uses id() (even for strings) - Add SoapWriter.Forget() - Add 'envelope' and 'encoding' keywords to SoapWriter - Added 'mutable' parameter to TC.Struct - TC.oname now properly defaults to TC.pname - Remove "None" if it was second arg to dictionary get() method - Add 'format' parameter to TC.Decimal and TC.Integer - Fix TC.Decimal to work where float('INF') doesn't - Fix TC.Decimal to handle NaN more portably - Add samples directory - Binding() omits typing from the outermost RPC wrapper - Fix HTML docs to include the ZSI schema - Add readerclass parameter to client Binding - Ignore <> around Content-ID in resolver; fix test to have it - Docfix for Placer.typecode (paul@prescod.net) - TC.Any will call pyobj's typecode if attr exists (paul@prescod.net) - Binding replytype is optional; standards replytype not replyclass - Document other tests to-do in interop/README - Document ZSI typecode naming better. - Add 'docstyle' to AsServer - Handle HTTP 100 responses (httplib should...) (aspinei@internal.metawings.com) Changes for 1.1, released 14-Sep-2001: - Works with PyXML0.6 now! - Create this CHANGES file, include it in doc files - Lots of editing and new material in the documentation - Fix TC.String to handle empty strings - Renamed NodeBacktrace to _backtrace - Renamed HasValidEncoding to _valid_encoding - Add 'textprotect' keyword argument to TC.String - TC.Any() can now serialize dictionaries, lists, tuples - TC.Any() can now parse arrays - Add aslist to TC.Any() - Add TC.Apache.Map typecode - GetMyHeaderElements includes header with no actor attribute - Fix formatting of error message when TC.Struct caught eval exception - Fix TC.Struct for case when all kids are optional (could-be-zero-sized) - Fix SimpleHREF calling sequence; boolean, Gregorian, duration now work - Fix typo when generating backtrace on EvaluateException - Exception backtraces are now in XPath syntax - Fix zsi.xsd to conform to proper XSD-Rec style - Fix zsi.xsd nits found by free IBM schema quality checker - Added Z:BasicAuth to zsi.xsd - CIDResolver now takes an optional "next" parameter, instead of creating a NetworkResolver automatically; the "prefixes" parameter is gone from the CIDResolver constructor - Rename CIDResolver to MIMEResolver, and add Content-Location handling - Changed resolver.seekable default from 1 to 0 - Resolvers raise EvaluateException, not TypeError - Fix FindLocalHREF to search the serialization root, too - Use and prefer Fault.AsSOAP, although Fault.AsSoap still exists - Change FindLocalHREF to cache all id's as it finds them - Add boolean, decimal, and hexbinary to interop server - Add simple CGI dispatching - Put version in setup.cfg and make newver use it for version.{py,tex} - Add ZSI.Version() to retrieve version tuple - Use len(_children(elt)) not elt.hasChildNodes() ZSI-2.1-a1/setup.py0000755000175100017510000000360410712434035012235 0ustar zsizsi#! /usr/bin/env python # $Header$ import sys try: from setuptools import setup hasSetuptools = True except ImportError: from distutils.core import setup hasSetuptools = False _url = "http://pywebsvcs.sf.net/" import ConfigParser cf = ConfigParser.ConfigParser() cf.read('setup.cfg') major = cf.getint('version', 'major') minor = cf.getint('version', 'minor') patchlevel = cf.getint('version', 'patchlevel') candidate = cf.getint('version', 'candidate') alpha = cf.getint('version', 'alpha') beta = cf.getint('version', 'beta') _version = "%d.%d" % ( major, minor ) if patchlevel: _version += '.%d' % patchlevel if candidate: _version += '_rc%d' % candidate elif alpha: _version += '_a%d' % alpha elif beta: _version += '_b%d' % beta try: open('ZSI/version.py', 'r').close() except: print 'ZSI/version.py not found; run "make"' sys.exit(1) _packages = [ "ZSI", "ZSI.generate", "ZSI.wstools"] if sys.version_info[0:2] >= (2, 4): _packages.append("ZSI.twisted") # setuptools specific logic additional_params = {} if hasSetuptools: additional_params['entry_points'] = { 'console_scripts': [ 'wsdl2py = ZSI.generate.commands:wsdl2py', ], } additional_params['setup_requires'] = [ "setuptools >= 0.6c3", ] additional_params['dependency_links'] = [ "http://sourceforge.net/project/showfiles.php?group_id=6473&package_id=6541&release_id=286213", ] else: additional_params['scripts'] = ["scripts/wsdl2py",] setup( name="ZSI", version=_version, license="Python", packages=_packages, description="Zolera SOAP Infrastructure", author="Rich Salz, et al", author_email="rsalz@datapower.com", maintainer="Rich Salz, et al", maintainer_email="pywebsvcs-talk@lists.sf.net", url=_url, long_description="For additional information, please see " + _url, **additional_params ) ZSI-2.1-a1/PKG-INFO0000644000175100017510000000045210712455110011610 0ustar zsizsiMetadata-Version: 1.0 Name: ZSI Version: 2.1-a1 Summary: Zolera SOAP Infrastructure Home-page: http://pywebsvcs.sf.net/ Author: Rich Salz, et al Author-email: pywebsvcs-talk@lists.sf.net License: Python Description: For additional information, please see http://pywebsvcs.sf.net/ Platform: UNKNOWN ZSI-2.1-a1/README0000644000175100017510000000274410700756665011421 0ustar zsizsi============================== The Zolera SOAP Infrastructure ============================== ZSI, the Zolera SOAP Infrastructure, is a pure-Python module that provides an implementation of SOAP messaging, as described in SOAP 1.1 Specification (see http://www.w3.org/TR/soap). It can also be used to build applications using SOAP Messages with Attachments (see http://www.w3.org/TR/SOAP-attachments). ZSI is intended to make it easier to write web services in Python. In particular, ZSI parses and generates SOAP messages, and converts between native Python datatypes and SOAP syntax. Simple dispatch and invocation methods are supported. There are no known bugs. It's only known limitation is that it cannot handle multi-dimensional arrays. ZSI is built on top of DOM. It requires Python 2.3 or later. It is open source. We hope you find it useful. The ZSI.twisted package will only be built if you're using Python >= 2.4, and in order to use it you'll need twisted >= 2.0 and twistedWeb >= 0.5.0 The documentation (in PDF and HTML) is accurate. We should probably restructure the document as a HOWTO. You probably can't usefully edit the docs without having the Python2.0 sources and some other utilities (TeX, pdfLaTeX, latex2html) on a Unix or Cygwin installation. If you want to format or revise the docs, see "Documentation Tools" in the file RELEASE. /rich $alz rsalz@datapower.com Things To Do ------------ Any volunteers? - Use isinstance() for types. - Update to SOAPv1.2. ZSI-2.1-a1/ZSI/0000755000175100017510000000000010712455110011157 5ustar zsizsiZSI-2.1-a1/ZSI/digest_auth.py0000644000175100017510000000634710556234235014054 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Utilities for HTTP Digest Authentication ''' import re from md5 import md5 import random import time import httplib random.seed(int(time.time()*10)) def H(val): return md5(val).hexdigest() def KD(secret,data): return H('%s:%s' % (secret,data)) def A1(username,realm,passwd,nonce=None,cnonce=None): if nonce and cnonce: return '%s:%s:%s:%s:%s' % (username,realm,passwd,nonce,cnonce) else: return '%s:%s:%s' % (username,realm,passwd) def A2(method,uri): return '%s:%s' % (method,uri) def dict_fetch(d,k,defval=None): if d.has_key(k): return d[k] return defval def generate_response(chaldict,uri,username,passwd,method='GET',cnonce=None): """ Generate an authorization response dictionary. chaldict should contain the digest challenge in dict form. Use fetch_challenge to create a chaldict from a HTTPResponse object like this: fetch_challenge(res.getheaders()). returns dict (the authdict) Note. Use build_authorization_arg() to turn an authdict into the final Authorization header value. """ authdict = {} qop = dict_fetch(chaldict,'qop') domain = dict_fetch(chaldict,'domain') nonce = dict_fetch(chaldict,'nonce') stale = dict_fetch(chaldict,'stale') algorithm = dict_fetch(chaldict,'algorithm','MD5') realm = dict_fetch(chaldict,'realm','MD5') opaque = dict_fetch(chaldict,'opaque') nc = "00000001" if not cnonce: cnonce = H(str(random.randint(0,10000000)))[:16] if algorithm.lower()=='md5-sess': a1 = A1(username,realm,passwd,nonce,cnonce) else: a1 = A1(username,realm,passwd) a2 = A2(method,uri) secret = H(a1) data = '%s:%s:%s:%s:%s' % (nonce,nc,cnonce,qop,H(a2)) authdict['username'] = '"%s"' % username authdict['realm'] = '"%s"' % realm authdict['nonce'] = '"%s"' % nonce authdict['uri'] = '"%s"' % uri authdict['response'] = '"%s"' % KD(secret,data) authdict['qop'] = '"%s"' % qop authdict['nc'] = nc authdict['cnonce'] = '"%s"' % cnonce return authdict def fetch_challenge(http_header): """ apparently keywords Basic and Digest are not being checked anywhere and decisions are being made based on authorization configuration of client, so I guess you better know what you are doing. Here I am requiring one or the other be specified. challenge Basic auth_param challenge Digest auth_param """ m = fetch_challenge.wwwauth_header_re.match(http_header) if m is None: raise RuntimeError, 'expecting "WWW-Authenticate header [Basic,Digest]"' d = dict(challenge=m.groups()[0]) m = fetch_challenge.auth_param_re.search(http_header) while m is not None: k,v = http_header[m.start():m.end()].split('=') d[k.lower()] = v[1:-1] m = fetch_challenge.auth_param_re.search(http_header, m.end()) return d fetch_challenge.wwwauth_header_re = re.compile(r'\s*([bB]asic|[dD]igest)\s+(?:[\w]+="[^"]+",?\s*)?') fetch_challenge.auth_param_re = re.compile(r'[\w]+="[^"]+"') def build_authorization_arg(authdict): """ Create an "Authorization" header value from an authdict (created by generate_response()). """ vallist = [] for k in authdict.keys(): vallist += ['%s=%s' % (k,authdict[k])] return 'Digest '+', '.join(vallist) if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/TCnumbers.py0000644000175100017510000001252110514021301013423 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Typecodes for numbers. ''' import types from ZSI import _copyright, _inttypes, _floattypes, _seqtypes, \ EvaluateException from ZSI.TC import TypeCode, Integer, Decimal from ZSI.wstools.Namespaces import SCHEMA class IunsignedByte(Integer): '''Unsigned 8bit value. ''' type = (SCHEMA.XSD3, "unsignedByte") parselist = [ (None, "unsignedByte") ] seriallist = [ ] class IunsignedShort(Integer): '''Unsigned 16bit value. ''' type = (SCHEMA.XSD3, "unsignedShort") parselist = [ (None, "unsignedShort") ] seriallist = [ ] class IunsignedInt(Integer): '''Unsigned 32bit value. ''' type = (SCHEMA.XSD3, "unsignedInt") parselist = [ (None, "unsignedInt") ] seriallist = [ ] class IunsignedLong(Integer): '''Unsigned 64bit value. ''' type = (SCHEMA.XSD3, "unsignedLong") parselist = [ (None, "unsignedLong") ] seriallist = [ ] class Ibyte(Integer): '''Signed 8bit value. ''' type = (SCHEMA.XSD3, "byte") parselist = [ (None, "byte") ] seriallist = [ ] class Ishort(Integer): '''Signed 16bit value. ''' type = (SCHEMA.XSD3, "short") parselist = [ (None, "short") ] seriallist = [ ] class Iint(Integer): '''Signed 32bit value. ''' type = (SCHEMA.XSD3, "int") parselist = [ (None, "int") ] seriallist = [ types.IntType ] class Ilong(Integer): '''Signed 64bit value. ''' type = (SCHEMA.XSD3, "long") parselist = [(None, "long")] seriallist = [ types.LongType ] class InegativeInteger(Integer): '''Value less than zero. ''' type = (SCHEMA.XSD3, "negativeInteger") parselist = [ (None, "negativeInteger") ] seriallist = [ ] class InonPositiveInteger(Integer): '''Value less than or equal to zero. ''' type = (SCHEMA.XSD3, "nonPositiveInteger") parselist = [ (None, "nonPositiveInteger") ] seriallist = [ ] class InonNegativeInteger(Integer): '''Value greater than or equal to zero. ''' type = (SCHEMA.XSD3, "nonNegativeInteger") parselist = [ (None, "nonNegativeInteger") ] seriallist = [ ] class IpositiveInteger(Integer): '''Value greater than zero. ''' type = (SCHEMA.XSD3, "positiveInteger") parselist = [ (None, "positiveInteger") ] seriallist = [ ] class Iinteger(Integer): '''Integer value. ''' type = (SCHEMA.XSD3, "integer") parselist = [ (None, "integer") ] seriallist = [ ] class IEnumeration(Integer): '''Integer value, limited to a specified set of values. ''' def __init__(self, choices, pname=None, **kw): Integer.__init__(self, pname, **kw) self.choices = choices t = type(choices) if t in _seqtypes: self.choices = tuple(choices) elif TypeCode.typechecks: raise TypeError( 'Enumeration choices must be list or sequence, not ' + str(t)) if TypeCode.typechecks: for c in self.choices: if type(c) not in _inttypes: raise TypeError('Enumeration choice "' + str(c) + '" is not an integer') def parse(self, elt, ps): val = Integer.parse(self, elt, ps) if val not in self.choices: raise EvaluateException('Value "' + str(val) + \ '" not in enumeration list', ps.Backtrace(elt)) return val def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): if pyobj not in self.choices: raise EvaluateException('Value not in int enumeration list', ps.Backtrace(elt)) Integer.serialize(self, elt, sw, pyobj, name=name, orig=orig, **kw) class FPfloat(Decimal): '''IEEE 32bit floating point value. ''' type = (SCHEMA.XSD3, "float") parselist = [ (None, "float") ] seriallist = [ types.FloatType ] class FPdouble(Decimal): '''IEEE 64bit floating point value. ''' type = (SCHEMA.XSD3, "double") parselist = [ (None, "double") ] seriallist = [ ] class FPEnumeration(FPfloat): '''Floating point value, limited to a specified set of values. ''' def __init__(self, choices, pname=None, **kw): FPfloat.__init__(self, pname, **kw) self.choices = choices t = type(choices) if t in _seqtypes: self.choices = tuple(choices) elif TypeCode.typechecks: raise TypeError( 'Enumeration choices must be list or sequence, not ' + str(t)) if TypeCode.typechecks: for c in self.choices: if type(c) not in _floattypes: raise TypeError('Enumeration choice "' + str(c) + '" is not floating point number') def parse(self, elt, ps): val = Decimal.parse(self, elt, ps) if val not in self.choices: raise EvaluateException('Value "' + str(val) + \ '" not in enumeration list', ps.Backtrace(elt)) return val def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): if pyobj not in self.choices: raise EvaluateException('Value not in int enumeration list', ps.Backtrace(elt)) Decimal.serialize(self, elt, sw, pyobj, name=name, orig=orig, **kw) if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/parse.py0000644000175100017510000003516710700756665012677 0ustar zsizsi#! /usr/bin/env python # $Header$ '''SOAP messaging parsing. ''' from xml.dom import expatbuilder from ZSI import _copyright, _children, _attrs, _child_elements, _stringtypes, \ _backtrace, EvaluateException, ParseException, _valid_encoding, \ _Node, _find_attr, _resolve_prefix from ZSI.TC import AnyElement import types from ZSI.wstools.Namespaces import SOAP, XMLNS from ZSI.wstools.Utility import SplitQName _find_actor = lambda E: E.getAttributeNS(SOAP.ENV, "actor") or None _find_mu = lambda E: E.getAttributeNS(SOAP.ENV, "mustUnderstand") _find_root = lambda E: E.getAttributeNS(SOAP.ENC, "root") _find_id = lambda E: _find_attr(E, 'id') class DefaultReader: """ExpatReaderClass""" fromString = staticmethod(expatbuilder.parseString) fromStream = staticmethod(expatbuilder.parse) class ParsedSoap: '''A Parsed SOAP object. Convert the text to a DOM tree and parse SOAP elements. Instance data: reader -- the DOM reader dom -- the DOM object ns_cache -- dictionary (by id(node)) of namespace dictionaries id_cache -- dictionary (by XML ID attr) of elements envelope -- the node holding the SOAP Envelope header -- the node holding the SOAP Header (or None) body -- the node holding the SOAP Body body_root -- the serialization root in the SOAP Body data_elements -- list of non-root elements in the SOAP Body trailer_elements -- list of elements following the SOAP body ''' defaultReaderClass = DefaultReader def __init__(self, input, readerclass=None, keepdom=False, trailers=False, resolver=None, envelope=True, **kw): '''Initialize. Keyword arguments: trailers -- allow trailer elments (default is zero) resolver -- function (bound method) to resolve URI's readerclass -- factory class to create a reader keepdom -- do not release the DOM envelope -- look for a SOAP envelope. ''' self.readerclass = readerclass self.keepdom = keepdom if not self.readerclass: self.readerclass = self.defaultReaderClass try: self.reader = self.readerclass() if type(input) in _stringtypes: self.dom = self.reader.fromString(input) else: self.dom = self.reader.fromStream(input) except Exception, e: # Is this in the header? Your guess is as good as mine. #raise ParseException("Can't parse document (" + \ # str(e.__class__) + "): " + str(e), 0) raise self.ns_cache = { id(self.dom): { 'xml': XMLNS.XML, 'xmlns': XMLNS.BASE, '': '' } } self.trailers, self.resolver, self.id_cache = trailers, resolver, {} # Exactly one child element c = [ E for E in _children(self.dom) if E.nodeType == _Node.ELEMENT_NODE] if len(c) == 0: raise ParseException("Document has no Envelope", 0) if len(c) != 1: raise ParseException("Document has extra child elements", 0) if envelope is False: self.body_root = c[0] return # And that one child must be the Envelope elt = c[0] if elt.localName != "Envelope" \ or elt.namespaceURI != SOAP.ENV: raise ParseException('Document has "' + elt.localName + \ '" element, not Envelope', 0) self._check_for_legal_children("Envelope", elt) for a in _attrs(elt): name = a.nodeName if name.find(":") == -1 and name not in [ "xmlns", "id" ]: raise ParseException('Unqualified attribute "' + \ name + '" in Envelope', 0) self.envelope = elt if not _valid_encoding(self.envelope): raise ParseException("Envelope has invalid encoding", 0) # Get Envelope's child elements. c = [ E for E in _children(self.envelope) if E.nodeType == _Node.ELEMENT_NODE ] if len(c) == 0: raise ParseException("Envelope is empty (no Body)", 0) # Envelope's first child might be the header; if so, nip it off. elt = c[0] if elt.localName == "Header" \ and elt.namespaceURI == SOAP.ENV: self._check_for_legal_children("Header", elt) self._check_for_pi_nodes(_children(elt), 1) self.header = c.pop(0) self.header_elements = _child_elements(self.header) else: self.header, self.header_elements = None, [] # Now the first child must be the body if len(c) == 0: raise ParseException("Envelope has header but no Body", 0) elt = c.pop(0) if elt.localName != "Body" \ or elt.namespaceURI != SOAP.ENV: if self.header: raise ParseException('Header followed by "' + \ elt.localName + \ '" element, not Body', 0, elt, self.dom) else: raise ParseException('Document has "' + \ elt.localName + \ '" element, not Body', 0, elt, self.dom) self._check_for_legal_children("Body", elt, 0) self._check_for_pi_nodes(_children(elt), 0) self.body = elt if not _valid_encoding(self.body): raise ParseException("Body has invalid encoding", 0) # Trailer elements. if not self.trailers: if len(c): raise ParseException("Element found after Body", 0, elt, self.dom) # Don't set self.trailer_elements = []; if user didn't ask # for trailers we *want* to throw an exception. else: self.trailer_elements = c for elt in self.trailer_elements: if not elt.namespaceURI: raise ParseException('Unqualified trailer element', 0, elt, self.dom) # Find the serialization root. Divide the Body children into # root (root=1), no (root=0), maybe (no root attribute). self.body_root, no, maybe = None, [], [] for elt in _child_elements(self.body): root = _find_root(elt) if root == "1": if self.body_root: raise ParseException("Multiple seralization roots found", 0, elt, self.dom) self.body_root = elt elif root == "0": no.append(elt) elif not root: maybe.append(elt) else: raise ParseException('Illegal value for root attribute', 0, elt, self.dom) # If we didn't find a root, get the first one that didn't # say "not me", unless they all said "not me." if self.body_root is None: if len(maybe): self.body_root = maybe[0] else: raise ParseException('No serialization root found', 0, self.body, self.dom) if not _valid_encoding(self.body_root): raise ParseException("Invalid encoding", 0, elt, self.dom) # Now get all the non-roots (in order!). rootid = id(self.body_root) self.data_elements = [ E for E in _child_elements(self.body) if id(E) != rootid ] self._check_for_pi_nodes(self.data_elements, 0) def __del__(self): try: if not self.keepdom: self.reader.releaseNode(self.dom) except: pass def _check_for_legal_children(self, name, elt, mustqualify=1): '''Check if all children of this node are elements or whitespace-only text nodes. ''' inheader = name == "Header" for n in _children(elt): t = n.nodeType if t == _Node.COMMENT_NODE: continue if t != _Node.ELEMENT_NODE: if t == _Node.TEXT_NODE and n.nodeValue.strip() == "": continue raise ParseException("Non-element child in " + name, inheader, elt, self.dom) if mustqualify and not n.namespaceURI: raise ParseException('Unqualified element "' + \ n.nodeName + '" in ' + name, inheader, elt, self.dom) def _check_for_pi_nodes(self, list, inheader): '''Raise an exception if any of the list descendants are PI nodes. ''' list = list[:] while list: elt = list.pop() t = elt.nodeType if t == _Node.PROCESSING_INSTRUCTION_NODE: raise ParseException('Found processing instruction ""', inheader, elt.parentNode, self.dom) elif t == _Node.DOCUMENT_TYPE_NODE: raise ParseException('Found DTD', inheader, elt.parentNode, self.dom) list += _children(elt) def Backtrace(self, elt): '''Return a human-readable "backtrace" from the document root to the specified element. ''' return _backtrace(elt, self.dom) def FindLocalHREF(self, href, elt, headers=1): '''Find a local HREF in the data elements. ''' if href[0] != '#': raise EvaluateException( 'Absolute HREF ("%s") not implemented' % href, self.Backtrace(elt)) frag = href[1:] # Already found? e = self.id_cache.get(frag) if e: return e # Do a breadth-first search, in the data first. Most likely # to find multi-ref targets shallow in the data area. list = self.data_elements[:] + [self.body_root] if headers: list.extend(self.header_elements) while list: e = list.pop() if e.nodeType == _Node.ELEMENT_NODE: nodeid = _find_id(e) if nodeid: self.id_cache[nodeid] = e if nodeid == frag: return e list += _children(e) raise EvaluateException('''Can't find node for HREF "%s"''' % href, self.Backtrace(elt)) def ResolveHREF(self, uri, tc, **keywords): r = getattr(tc, 'resolver', self.resolver) if not r: raise EvaluateException('No resolver for "' + uri + '"') try: if type(uri) == types.UnicodeType: uri = str(uri) retval = r(uri, tc, self, **keywords) except Exception, e: raise EvaluateException('''Can't resolve "''' + uri + '" (' + \ str(e.__class__) + "): " + str(e)) return retval def GetMyHeaderElements(self, actorlist=None): '''Return a list of all elements intended for these actor(s). ''' if actorlist is None: actorlist = [None, SOAP.ACTOR_NEXT] else: actorlist = list(actorlist) + [None, SOAP.ACTOR_NEXT] return [ E for E in self.header_elements if _find_actor(E) in actorlist ] def GetElementNSdict(self, elt): '''Get a dictionary of all the namespace attributes for the indicated element. The dictionaries are cached, and we recurse up the tree as necessary. ''' d = self.ns_cache.get(id(elt)) if not d: if elt != self.dom: d = self.GetElementNSdict(elt.parentNode) for a in _attrs(elt): if a.namespaceURI == XMLNS.BASE: if a.localName == "xmlns": d[''] = a.nodeValue else: d[a.localName] = a.nodeValue self.ns_cache[id(elt)] = d return d.copy() def GetDomAndReader(self): '''Returns a tuple containing the dom and reader objects. (dom, reader) Unless keepdom is true, the dom and reader objects will go out of scope when the ParsedSoap instance is deleted. If keepdom is true, the reader object is needed to properly clean up the dom tree with reader.releaseNode(dom). ''' return (self.dom, self.reader) def IsAFault(self): '''Is this a fault message? ''' e = self.body_root if not e: return 0 return e.namespaceURI == SOAP.ENV and e.localName == 'Fault' def Parse(self, how): '''Parse the message. ''' if type(how) == types.ClassType: how = how.typecode return how.parse(self.body_root, self) def WhatMustIUnderstand(self): '''Return a list of (uri,localname) tuples for all elements in the header that have mustUnderstand set. ''' return [ ( E.namespaceURI, E.localName ) for E in self.header_elements if _find_mu(E) == "1" ] def WhatActorsArePresent(self): '''Return a list of URI's of all the actor attributes found in the header. The special actor "next" is ignored. ''' results = [] for E in self.header_elements: a = _find_actor(E) if a not in [ None, SOAP.ACTOR_NEXT ]: results.append(a) return results def ParseHeaderElements(self, ofwhat): '''Returns a dictionary of pyobjs. ofhow -- list of typecodes w/matching nspname/pname to the header_elements. ''' d = {} lenofwhat = len(ofwhat) c, crange = self.header_elements[:], range(len(self.header_elements)) for i,what in [ (i, ofwhat[i]) for i in range(lenofwhat) ]: if isinstance(what, AnyElement): raise EvaluateException, 'not supporting as child of SOAP-ENC:Header' v = [] occurs = 0 namespaceURI,tagName = what.nspname,what.pname for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]: prefix,name = SplitQName(c_elt.tagName) nsuri = _resolve_prefix(c_elt, prefix) if tagName == name and namespaceURI == nsuri: pyobj = what.parse(c_elt, self) else: continue v.append(pyobj) c[j] = None if what.minOccurs > len(v) > what.maxOccurs: raise EvaluateException, 'number of occurances(%d) doesnt fit constraints (%d,%s)'\ %(len(v),what.minOccurs,what.maxOccurs) if what.maxOccurs == 1: if len(v) == 0: v = None else: v = v[0] d[(what.nspname,what.pname)] = v return d if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/TC.py0000644000175100017510000020063610647242563012063 0ustar zsizsi#! /usr/bin/env python # $Header$ '''General typecodes. ''' from ZSI import _copyright, _children, _child_elements, \ _floattypes, _stringtypes, _seqtypes, _find_attr, _find_attrNS, _find_attrNodeNS, \ _find_arraytype, _find_default_namespace, _find_href, _find_encstyle, \ _resolve_prefix, _find_xsi_attr, _find_type, \ _find_xmlns_prefix, _get_element_nsuri_name, _get_idstr, \ _Node, EvaluateException, UNICODE_ENCODING, \ _valid_encoding, ParseException from ZSI.wstools.Namespaces import SCHEMA, SOAP from ZSI.wstools.Utility import SplitQName from ZSI.wstools.c14n import Canonicalize from ZSI.wstools.logging import getLogger as _GetLogger import re, types, time, copy from base64 import decodestring as b64decode, encodestring as b64encode from urllib import unquote as urldecode, quote as urlencode from binascii import unhexlify as hexdecode, hexlify as hexencode try: from cStringIO import StringIO except ImportError: from StringIO import StringIO _is_xsd_or_soap_ns = lambda ns: ns in [ SCHEMA.XSD3, SOAP.ENC, SCHEMA.XSD1, SCHEMA.XSD2, ] _find_nil = lambda E: _find_xsi_attr(E, "null") or _find_xsi_attr(E, "nil") def _get_xsitype(pyclass): '''returns the xsi:type as a tuple, coupled with ZSI.schema ''' if hasattr(pyclass,'type') and type(pyclass.type) in _seqtypes: return pyclass.type elif hasattr(pyclass,'type') and hasattr(pyclass, 'schema'): return (pyclass.schema, pyclass.type) return (None,None) # value returned when xsi:nil="true" Nilled = None UNBOUNDED = 'unbounded' class TypeCode: '''The parent class for all parseable SOAP types. Class data: typechecks -- do init-time type checking if non-zero Class data subclasses may define: tag -- global element declaration type -- global type definition parselist -- list of valid SOAP types for this class, as (uri,name) tuples, where a uri of None means "all the XML Schema namespaces" errorlist -- parselist in a human-readable form; will be generated if/when needed seriallist -- list of Python types or user-defined classes that this typecode can serialize. logger -- logger instance for this class. ''' tag = None type = (None,None) typechecks = True attribute_typecode_dict = None logger = _GetLogger('ZSI.TC.TypeCode') def __init__(self, pname=None, aname=None, minOccurs=1, maxOccurs=1, nillable=False, typed=True, unique=True, pyclass=None, attrs_aname='_attrs', **kw): '''Baseclass initialization. Instance data (and usually keyword arg) pname -- the parameter name (localname). nspname -- the namespace for the parameter; None to ignore the namespace typed -- output xsi:type attribute unique -- data item is not aliased (no href/id needed) minOccurs -- min occurances maxOccurs -- max occurances nillable -- is item nillable? attrs_aname -- This is variable name to dictionary of attributes encoded -- encoded namespaceURI (specify if use is encoded) ''' if type(pname) in _seqtypes: self.nspname, self.pname = pname else: self.nspname, self.pname = None, pname if self.pname: self.pname = str(self.pname).split(':')[-1] self.aname = aname or self.pname self.minOccurs = minOccurs self.maxOccurs = maxOccurs self.nillable = nillable self.typed = typed self.unique = unique self.attrs_aname = attrs_aname self.pyclass = pyclass # Need this stuff for rpc/encoded. encoded = kw.get('encoded') if encoded is not None: self.nspname = kw['encoded'] def parse(self, elt, ps): ''' Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' raise EvaluateException("Unimplemented evaluation", ps.Backtrace(elt)) def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): ''' Parameters: elt -- the current DOMWrapper element sw -- soapWriter object pyobj -- python object to serialize ''' raise EvaluateException("Unimplemented evaluation", sw.Backtrace(elt)) def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. Parameters: text -- text content elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' raise EvaluateException("Unimplemented evaluation", ps.Backtrace(elt)) def serialize_as_nil(self, elt): ''' Parameters: elt -- the current DOMWrapper element ''' elt.setAttributeNS(SCHEMA.XSI3, 'nil', '1') def SimpleHREF(self, elt, ps, tag): '''Simple HREF for non-string and non-struct and non-array. Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. tag -- ''' if len(_children(elt)): return elt href = _find_href(elt) if not href: if self.minOccurs is 0: return None raise EvaluateException('Required' + tag + ' missing', ps.Backtrace(elt)) return ps.FindLocalHREF(href, elt, 0) def get_parse_and_errorlist(self): """Get the parselist and human-readable version, errorlist is returned, because it is used in error messages. """ d = self.__class__.__dict__ parselist = d.get('parselist') errorlist = d.get('errorlist') if parselist and not errorlist: errorlist = [] for t in parselist: if t[1] not in errorlist: errorlist.append(t[1]) errorlist = ' or '.join(errorlist) d['errorlist'] = errorlist return (parselist, errorlist) def checkname(self, elt, ps): '''See if the name and type of the "elt" element is what we're looking for. Return the element's type. Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' parselist,errorlist = self.get_parse_and_errorlist() ns, name = _get_element_nsuri_name(elt) if ns == SOAP.ENC: # Element is in SOAP namespace, so the name is a type. if parselist and \ (None, name) not in parselist and (ns, name) not in parselist: raise EvaluateException( 'Element mismatch (got %s wanted %s) (SOAP encoding namespace)' % \ (name, errorlist), ps.Backtrace(elt)) return (ns, name) # Not a type, check name matches. if self.nspname and ns != self.nspname: raise EvaluateException('Element NS mismatch (got %s wanted %s)' % \ (ns, self.nspname), ps.Backtrace(elt)) if self.pname and name != self.pname: raise EvaluateException('Element Name mismatch (got %s wanted %s)' % \ (name, self.pname), ps.Backtrace(elt)) return self.checktype(elt, ps) def checktype(self, elt, ps): '''See if the type of the "elt" element is what we're looking for. Return the element's type. Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' typeName = _find_type(elt) if typeName is None or typeName == "": return (None,None) # Parse the QNAME. prefix,typeName = SplitQName(typeName) uri = ps.GetElementNSdict(elt).get(prefix) if uri is None: raise EvaluateException('Malformed type attribute (bad NS)', ps.Backtrace(elt)) #typeName = list[1] parselist,errorlist = self.get_parse_and_errorlist() if not parselist or \ (uri,typeName) in parselist or \ (_is_xsd_or_soap_ns(uri) and (None,typeName) in parselist): return (uri,typeName) raise EvaluateException( 'Type mismatch (%s namespace) (got %s wanted %s)' % \ (uri, typeName, errorlist), ps.Backtrace(elt)) def name_match(self, elt): '''Simple boolean test to see if we match the element name. Parameters: elt -- the DOM element being parsed ''' return self.pname == elt.localName and \ self.nspname in [None, '', elt.namespaceURI] def nilled(self, elt, ps): '''Is the element NIL, and is that okay? Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' if _find_nil(elt) not in [ "true", "1"]: return False if self.nillable is False: raise EvaluateException('Non-nillable element is NIL', ps.Backtrace(elt)) return True def simple_value(self, elt, ps, mixed=False): '''Get the value of the simple content of this element. Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. mixed -- ignore element content, optional text node ''' if not _valid_encoding(elt): raise EvaluateException('Invalid encoding', ps.Backtrace(elt)) c = _children(elt) if mixed is False: if len(c) == 0: raise EvaluateException('Value missing', ps.Backtrace(elt)) for c_elt in c: if c_elt.nodeType == _Node.ELEMENT_NODE: raise EvaluateException('Sub-elements in value', ps.Backtrace(c_elt)) # It *seems* to be consensus that ignoring comments and # concatenating the text nodes is the right thing to do. return ''.join([E.nodeValue for E in c if E.nodeType in [ _Node.TEXT_NODE, _Node.CDATA_SECTION_NODE ]]) def parse_attributes(self, elt, ps): '''find all attributes specified in the attribute_typecode_dict in current element tag, if an attribute is found set it in the self.attributes dictionary. Default to putting in String. Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' if self.attribute_typecode_dict is None: return attributes = {} for attr,what in self.attribute_typecode_dict.items(): namespaceURI,localName = None,attr if type(attr) in _seqtypes: namespaceURI,localName = attr value = _find_attrNodeNS(elt, namespaceURI, localName) self.logger.debug("Parsed Attribute (%s,%s) -- %s", namespaceURI, localName, value) # For Now just set it w/o any type interpretation. if value is None: continue attributes[attr] = what.text_to_data(value, elt, ps) return attributes def set_attributes(self, el, pyobj): '''Instance data attributes contains a dictionary of keys (namespaceURI,localName) and attribute values. These values can be self-describing (typecode), or use attribute_typecode_dict to determine serialization. Paramters: el -- MessageInterface representing the element pyobj -- ''' if not hasattr(pyobj, self.attrs_aname): return if not isinstance(getattr(pyobj, self.attrs_aname), dict): raise TypeError,\ 'pyobj.%s must be a dictionary of names and values'\ % self.attrs_aname for attr, value in getattr(pyobj, self.attrs_aname).items(): namespaceURI,localName = None, attr if type(attr) in _seqtypes: namespaceURI, localName = attr what = None if getattr(self, 'attribute_typecode_dict', None) is not None: what = self.attribute_typecode_dict.get(attr) if what is None and namespaceURI is None: what = self.attribute_typecode_dict.get(localName) # allow derived type if hasattr(value, 'typecode') and not isinstance(what, AnyType): if what is not None and not isinstance(value.typecode, what): raise EvaluateException, \ 'self-describing attribute must subclass %s'\ %what.__class__ what = value.typecode self.logger.debug("attribute create -- %s", value) if isinstance(what, QName): what.set_prefix(el, value) #format the data if what is None: value = str(value) else: value = what.get_formatted_content(value) el.setAttributeNS(namespaceURI, localName, value) def set_attribute_xsi_type(self, el, **kw): '''if typed, set the xsi:type attribute Paramters: el -- MessageInterface representing the element ''' if kw.get('typed', self.typed): namespaceURI,typeName = kw.get('type', _get_xsitype(self)) if namespaceURI and typeName: self.logger.debug("attribute: (%s, %s)", namespaceURI, typeName) el.setAttributeType(namespaceURI, typeName) def set_attribute_href(self, el, objid): '''set href attribute Paramters: el -- MessageInterface representing the element objid -- ID type, unique id ''' el.setAttributeNS(None, 'href', "#%s" %objid) def set_attribute_id(self, el, objid): '''set id attribute Paramters: el -- MessageInterface representing the element objid -- ID type, unique id ''' if self.unique is False: el.setAttributeNS(None, 'id', "%s" %objid) def get_name(self, name, objid): ''' Paramters: name -- element tag objid -- ID type, unique id ''' if type(name) is tuple: return name ns = self.nspname n = name or self.pname or ('E' + objid) return ns,n def has_attributes(self): '''Return True if Attributes are declared outside the scope of SOAP ('root', 'id', 'href'), and some attributes automatically handled (xmlns, xsi:type). ''' if self.attribute_typecode_dict is None: return False return len(self.attribute_typecode_dict) > 0 class SimpleType(TypeCode): '''SimpleType -- consist exclusively of a tag, attributes, and a value class attributes: empty_content -- value representing an empty element. ''' empty_content = None logger = _GetLogger('ZSI.TC.SimpleType') def parse(self, elt, ps): self.checkname(elt, ps) if len(_children(elt)) == 0: href = _find_href(elt) if not href: if self.nilled(elt, ps) is False: # No content, no HREF, not NIL: empty string return self.text_to_data(self.empty_content, elt, ps) # No content, no HREF, and is NIL... if self.nillable is True: return Nilled raise EvaluateException('Requiredstring missing', ps.Backtrace(elt)) if href[0] != '#': return ps.ResolveHREF(href, self) elt = ps.FindLocalHREF(href, elt) self.checktype(elt, ps) if self.nilled(elt, ps): return Nilled if len(_children(elt)) == 0: v = self.empty_content else: v = self.simple_value(elt, ps) else: v = self.simple_value(elt, ps) pyobj = self.text_to_data(v, elt, ps) # parse all attributes contained in attribute_typecode_dict # (user-defined attributes), the values (if not None) will # be keyed in self.attributes dictionary. if self.attribute_typecode_dict is not None: attributes = self.parse_attributes(elt, ps) if attributes: setattr(pyobj, self.attrs_aname, attributes) return pyobj def get_formatted_content(self, pyobj): raise NotImplementedError, 'method get_formatted_content is not implemented' def serialize_text_node(self, elt, sw, pyobj): '''Serialize without an element node. ''' textNode = None if pyobj is not None: text = self.get_formatted_content(pyobj) if type(text) not in _stringtypes: raise TypeError, 'pyobj must be a formatted string' textNode = elt.createAppendTextNode(text) return textNode def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): '''Handles the start and end tags, and attributes. callout to get_formatted_content to get the textNode value. Parameters: elt -- ElementProxy/DOM element sw -- SoapWriter instance pyobj -- processed content KeyWord Parameters: name -- substitute name, (nspname,name) or name orig -- ''' objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) # nillable el = elt.createAppendElement(ns, n) if self.nillable is True and pyobj is Nilled: self.serialize_as_nil(el) return None # other attributes self.set_attributes(el, pyobj) # soap href attribute unique = self.unique or kw.get('unique', False) if unique is False and sw.Known(orig or pyobj): self.set_attribute_href(el, objid) return None # xsi:type attribute if kw.get('typed', self.typed) is True: self.set_attribute_xsi_type(el, **kw) # soap id attribute if self.unique is False: self.set_attribute_id(el, objid) #Content, c self.serialize_text_node(el, sw, pyobj) return el class Any(TypeCode): '''When the type isn't defined in the schema, but must be specified in the incoming operation. parsemap -- a type to class mapping (updated by descendants), for parsing serialmap -- same, for (outgoing) serialization ''' logger = _GetLogger('ZSI.TC.Any') parsemap, serialmap = {}, {} def __init__(self, pname=None, aslist=False, minOccurs=0, unique=False, **kw): TypeCode.__init__(self, pname, minOccurs=minOccurs, unique=unique, **kw) self.aslist = aslist self.kwargs = dict(aslist=aslist, unique=unique) self.kwargs.update(kw) # input arg v should be a list of tuples (name, value). def listify(self, v): if self.aslist: return [ k for j,k in v ] return dict(v) def parse_into_dict_or_list(self, elt, ps): c = _child_elements(elt) count = len(c) v = [] if count == 0: href = _find_href(elt) if not href: return v elt = ps.FindLocalHREF(href, elt) self.checktype(elt, ps) c = _child_elements(elt) count = len(c) if count == 0: return self.listify(v) if self.nilled(elt, ps): return Nilled for c_elt in c: v.append((str(c_elt.localName), self.__class__(**self.kwargs).parse(c_elt, ps))) return self.listify(v) def parse(self, elt, ps): (ns,type) = self.checkname(elt, ps) if not type and self.nilled(elt, ps): return Nilled if len(_children(elt)) == 0: href = _find_href(elt) if not href: if self.minOccurs < 1: if _is_xsd_or_soap_ns(ns): parser = Any.parsemap.get((None,type)) if parser: return parser.parse(elt, ps) if ((ns,type) == (SOAP.ENC,'Array') or (_find_arraytype(elt) or '').endswith('[0]')): return [] return None raise EvaluateException('Required Any missing', ps.Backtrace(elt)) elt = ps.FindLocalHREF(href, elt) (ns,type) = self.checktype(elt, ps) if not type and elt.namespaceURI == SOAP.ENC: ns,type = SOAP.ENC, elt.localName if not type or (ns,type) == (SOAP.ENC,'Array'): if self.aslist or _find_arraytype(elt): return [ self.__class__(**self.kwargs).parse(e, ps) for e in _child_elements(elt) ] if len(_child_elements(elt)) == 0: #raise EvaluateException("Any cannot parse untyped element", # ps.Backtrace(elt)) return self.simple_value(elt, ps) return self.parse_into_dict_or_list(elt, ps) parser = Any.parsemap.get((ns,type)) if not parser and _is_xsd_or_soap_ns(ns): parser = Any.parsemap.get((None,type)) if not parser: raise EvaluateException('''Any can't parse element''', ps.Backtrace(elt)) return parser.parse(elt, ps) def get_formatted_content(self, pyobj): tc = type(pyobj) if tc == types.InstanceType: tc = pyobj.__class__ if hasattr(pyobj, 'typecode'): #serializer = pyobj.typecode.serialmap.get(tc) serializer = pyobj.typecode else: serializer = Any.serialmap.get(tc) if not serializer: tc = (types.ClassType, pyobj.__class__.__name__) serializer = Any.serialmap.get(tc) else: serializer = Any.serialmap.get(tc) if not serializer and isinstance(pyobj, time.struct_time): from ZSI.TCtimes import gDateTime serializer = gDateTime() if serializer: return serializer.get_formatted_content(pyobj) raise EvaluateException, 'Failed to find serializer for pyobj %s' %pyobj def serialize(self, elt, sw, pyobj, name=None, **kw): if hasattr(pyobj, 'typecode') and pyobj.typecode is not self: pyobj.typecode.serialize(elt, sw, pyobj, **kw) return objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) kw.setdefault('typed', self.typed) tc = type(pyobj) self.logger.debug('Any serialize -- %s', tc) if tc in _seqtypes: if self.aslist: array = elt.createAppendElement(ns, n) array.setAttributeType(SOAP.ENC, "Array") array.setAttributeNS(self.nspname, 'SOAP-ENC:arrayType', "xsd:anyType[" + str(len(pyobj)) + "]" ) for o in pyobj: #TODO maybe this should take **self.kwargs... serializer = getattr(o, 'typecode', Any(**self.kwargs)) serializer.serialize(array, sw, o, name='element', **kw) else: struct = elt.createAppendElement(ns, n) for o in pyobj: #TODO maybe this should take **self.kwargs... serializer = getattr(o, 'typecode', Any(**self.kwargs)) serializer.serialize(struct, sw, o, **kw) return kw['name'] = (ns,n) if tc == types.DictType: el = elt.createAppendElement(ns, n) parentNspname = self.nspname # temporarily clear nspname for dict elements self.nspname = None for o,m in pyobj.items(): if type(o) != types.StringType and type(o) != types.UnicodeType: raise Exception, 'Dictionary implementation requires keys to be of type string (or unicode).' %pyobj kw['name'] = o kw.setdefault('typed', True) self.serialize(el, sw, m, **kw) # restore nspname self.nspname = parentNspname return if tc == types.InstanceType: tc = pyobj.__class__ if hasattr(pyobj, 'typecode'): #serializer = pyobj.typecode.serialmap.get(tc) serializer = pyobj.typecode else: serializer = Any.serialmap.get(tc) if not serializer: tc = (types.ClassType, pyobj.__class__.__name__) serializer = Any.serialmap.get(tc) else: serializer = Any.serialmap.get(tc) if not serializer and isinstance(pyobj, time.struct_time): from ZSI.TCtimes import gDateTime serializer = gDateTime() if not serializer: # Last-chance; serialize instances as dictionary if pyobj is None: self.serialize_as_nil(elt.createAppendElement(ns, n)) elif type(pyobj) != types.InstanceType: raise EvaluateException('''Any can't serialize ''' + \ repr(pyobj)) else: self.serialize(elt, sw, pyobj.__dict__, **kw) else: # Try to make the element name self-describing tag = getattr(serializer, 'tag', None) if self.pname is not None: #serializer.nspname = self.nspname #serializer.pname = self.pname if "typed" not in kw: kw['typed'] = False elif tag: if tag.find(':') == -1: tag = 'SOAP-ENC:' + tag kw['name'] = tag kw['typed'] = False serializer.unique = self.unique serializer.serialize(elt, sw, pyobj, **kw) # Reset TypeCode #serializer.nspname = None #serializer.pname = None class String(SimpleType): '''A string type. ''' empty_content = '' parselist = [ (None,'string') ] seriallist = [ types.StringType, types.UnicodeType ] type = (SCHEMA.XSD3, 'string') logger = _GetLogger('ZSI.TC.String') def __init__(self, pname=None, strip=True, **kw): TypeCode.__init__(self, pname, **kw) if kw.has_key('resolver'): self.resolver = kw['resolver'] self.strip = strip def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. Encode all strings as UTF-8, which will be type 'str' not 'unicode' ''' if self.strip: text = text.strip() if self.pyclass is not None: return self.pyclass(text.encode(UNICODE_ENCODING)) return text.encode(UNICODE_ENCODING) def get_formatted_content(self, pyobj): if type(pyobj) not in _stringtypes: pyobj = str(pyobj) if type(pyobj) == unicode: return pyobj.encode(UNICODE_ENCODING) return pyobj class URI(String): '''A URI. Class data: reserved -- urllib.quote will escape all reserved characters regardless of whether they are used for the reserved purpose. ''' parselist = [ (None,'anyURI'),(SCHEMA.XSD3, 'anyURI')] type = (SCHEMA.XSD3, 'anyURI') logger = _GetLogger('ZSI.TC.URI') reserved = ";/?:@&=+$," def text_to_data(self, text, elt, ps): '''text --> typecode specific data. ''' return String.text_to_data(self, urldecode(text), elt, ps) def get_formatted_content(self, pyobj): '''typecode data --> text ''' u = urlencode(pyobj, self.reserved) return String.get_formatted_content(self, u) class QName(String): '''A QName type ''' parselist = [ (None,'QName') ] type = (SCHEMA.XSD3, 'QName') logger = _GetLogger('ZSI.TC.QName') def __init__(self, pname=None, strip=1, **kw): String.__init__(self, pname, strip, **kw) self.prefix = None def get_formatted_content(self, pyobj): value = pyobj if isinstance(pyobj, tuple): namespaceURI,localName = pyobj if self.prefix is not None: value = "%s:%s" %(self.prefix,localName) return String.get_formatted_content(self, value) def set_prefix(self, elt, pyobj): '''use this method to set the prefix of the QName, method looks in DOM to find prefix or set new prefix. This method must be called before get_formatted_content. ''' if isinstance(pyobj, tuple): namespaceURI,localName = pyobj self.prefix = elt.getPrefix(namespaceURI) def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' prefix,localName = SplitQName(text) nsdict = ps.GetElementNSdict(elt) prefix = prefix or '' try: namespaceURI = nsdict[prefix] except KeyError, ex: raise EvaluateException('cannot resolve prefix(%s)'%prefix, ps.Backtrace(elt)) v = (namespaceURI,localName) if self.pyclass is not None: return self.pyclass(v) return v def serialize_text_node(self, elt, sw, pyobj): '''Serialize without an element node. ''' self.set_prefix(elt, pyobj) return String.serialize_text_node(self, elt, sw, pyobj) class Token(String): '''an xsd:token type ''' parselist = [ (None, 'token') ] type = (SCHEMA.XSD3, 'token') logger = _GetLogger('ZSI.TC.Token') class Base64String(String): '''A Base64 encoded string. ''' parselist = [ (None,'base64Binary'), (SOAP.ENC, 'base64') ] type = (SOAP.ENC, 'base64') logger = _GetLogger('ZSI.TC.Base64String') def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' val = b64decode(text.replace(' ', '').replace('\n','').replace('\r','')) if self.pyclass is not None: return self.pyclass(val) return val def get_formatted_content(self, pyobj): pyobj = '\n' + b64encode(pyobj) return String.get_formatted_content(self, pyobj) class Base64Binary(String): parselist = [ (None,'base64Binary'), ] type = (SCHEMA.XSD3, 'base64Binary') logger = _GetLogger('ZSI.TC.Base64Binary') def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' val = b64decode(text) if self.pyclass is not None: return self.pyclass(val) return val def get_formatted_content(self, pyobj): pyobj = b64encode(pyobj).strip() return pyobj class HexBinaryString(String): '''Hex-encoded binary (yuk). ''' parselist = [ (None,'hexBinary') ] type = (SCHEMA.XSD3, 'hexBinary') logger = _GetLogger('ZSI.TC.HexBinaryString') def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' val = hexdecode(text) if self.pyclass is not None: return self.pyclass(val) return val def get_formatted_content(self, pyobj): pyobj = hexencode(pyobj).upper() return String.get_formatted_content(self, pyobj) class XMLString(String): '''A string that represents an XML document ''' logger = _GetLogger('ZSI.TC.XMLString') def __init__(self, pname=None, readerclass=None, **kw): String.__init__(self, pname, **kw) self.readerclass = readerclass def parse(self, elt, ps): if not self.readerclass: from xml.dom.ext.reader import PyExpat self.readerclass = PyExpat.Reader v = String.parse(self, elt, ps) return self.readerclass().fromString(v) def get_formatted_content(self, pyobj): #pyobj = Canonicalize(pyobj) return String.get_formatted_content(self, pyobj) class Enumeration(String): '''A string type, limited to a set of choices. ''' logger = _GetLogger('ZSI.TC.Enumeration') def __init__(self, choices, pname=None, **kw): String.__init__(self, pname, **kw) t = type(choices) if t in _seqtypes: self.choices = tuple(choices) elif TypeCode.typechecks: raise TypeError( 'Enumeration choices must be list or sequence, not ' + str(t)) if TypeCode.typechecks: for c in self.choices: if type(c) not in _stringtypes: raise TypeError( 'Enumeration choice ' + str(c) + ' is not a string') def parse(self, elt, ps): val = String.parse(self, elt, ps) if val not in self.choices: raise EvaluateException('Value not in enumeration list', ps.Backtrace(elt)) return val def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): if pyobj not in self.choices: raise EvaluateException('Value not in enumeration list', sw.Backtrace(elt)) String.serialize(self, elt, sw, pyobj, name=name, orig=orig, **kw) # This is outside the Integer class purely for code esthetics. _ignored = [] class Integer(SimpleType): '''Common handling for all integers. ''' ranges = { 'unsignedByte': (0, 255), 'unsignedShort': (0, 65535), 'unsignedInt': (0, 4294967295L), 'unsignedLong': (0, 18446744073709551615L), 'byte': (-128, 127), 'short': (-32768, 32767), 'int': (-2147483648L, 2147483647), 'long': (-9223372036854775808L, 9223372036854775807L), 'negativeInteger': (_ignored, -1), 'nonPositiveInteger': (_ignored, 0), 'nonNegativeInteger': (0, _ignored), 'positiveInteger': (1, _ignored), 'integer': (_ignored, _ignored) } parselist = [ (None,k) for k in ranges.keys() ] seriallist = [ types.IntType, types.LongType ] logger = _GetLogger('ZSI.TC.Integer') def __init__(self, pname=None, format='%d', **kw): TypeCode.__init__(self, pname, **kw) self.format = format def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' if self.pyclass is not None: v = self.pyclass(text) else: try: v = int(text) except: try: v = long(text) except: raise EvaluateException('Unparseable integer', ps.Backtrace(elt)) return v def parse(self, elt, ps): (ns,type) = self.checkname(elt, ps) if self.nilled(elt, ps): return Nilled elt = self.SimpleHREF(elt, ps, 'integer') if not elt: return None if type is None: type = self.type[1] elif self.type[1] is not None and type != self.type[1]: raise EvaluateException('Integer type mismatch; ' \ 'got %s wanted %s' % (type,self.type[1]), ps.Backtrace(elt)) v = self.simple_value(elt, ps) v = self.text_to_data(v, elt, ps) (rmin, rmax) = Integer.ranges.get(type, (_ignored, _ignored)) if rmin != _ignored and v < rmin: raise EvaluateException('Underflow, less than ' + repr(rmin), ps.Backtrace(elt)) if rmax != _ignored and v > rmax: raise EvaluateException('Overflow, greater than ' + repr(rmax), ps.Backtrace(elt)) return v def get_formatted_content(self, pyobj): return self.format %pyobj # See credits, below. def _make_inf(): x = 2.0 x2 = x * x i = 0 while i < 100 and x != x2: x = x2 x2 = x * x i = i + 1 if x != x2: raise ValueError("This machine's floats go on forever!") return x # This is outside the Decimal class purely for code esthetics. _magicnums = { } try: _magicnums['INF'] = float('INF') _magicnums['-INF'] = float('-INF') except: _magicnums['INF'] = _make_inf() _magicnums['-INF'] = -_magicnums['INF'] # The following comment and code was written by Tim Peters in # article <001401be92d2$09dcb800$5fa02299@tim> in comp.lang.python, # also available at the following URL: # http://groups.google.com/groups?selm=001401be92d2%2409dcb800%245fa02299%40tim # Thanks, Tim! # NaN-testing. # # The usual method (x != x) doesn't work. # Python forces all comparisons thru a 3-outcome cmp protocol; unordered # isn't a possible outcome. The float cmp outcome is essentially defined # by this C expression (combining some cross-module implementation # details, and where px and py are pointers to C double): # px == py ? 0 : *px < *py ? -1 : *px > *py ? 1 : 0 # Comparing x to itself thus always yields 0 by the first clause, and so # x != x is never true. # If px and py point to distinct NaN objects, a strange thing happens: # 1. On scrupulous 754 implementations, *px < *py returns false, and so # does *px > *py. Python therefore returns 0, i.e. "equal"! # 2. On Pentium HW, an unordered outcome sets an otherwise-impossible # combination of condition codes, including both the "less than" and # "equal to" flags. Microsoft C generates naive code that accepts # the "less than" flag at face value, and so the *px < *py clause # returns true, and Python returns -1, i.e. "not equal". # So with a proper C 754 implementation Python returns the wrong result, # and under MS's improper 754 implementation Python yields the right # result -- both by accident. It's unclear who should be shot . # # Anyway, the point of all that was to convince you it's tricky getting # the right answer in a portable way! def isnan(x): """x -> true iff x is a NaN.""" # multiply by 1.0 to create a distinct object (x < x *always* # false in Python, due to object identity forcing equality) if x * 1.0 < x: # it's a NaN and this is MS C on a Pentium return 1 # Else it's non-NaN, or NaN on a non-MS+Pentium combo. # If it's non-NaN, then x == 1.0 and x == 2.0 can't both be true, # so we return false. If it is NaN, then assuming a good 754 C # implementation Python maps both unordered outcomes to true. return 1.0 == x and x == 2.0 class Decimal(SimpleType): '''Parent class for floating-point numbers. ''' parselist = [ (None,'decimal'), (None,'float'), (None,'double') ] seriallist = _floattypes type = None ranges = { 'float': ( 7.0064923216240861E-46, -3.4028234663852886E+38, 3.4028234663852886E+38 ), 'double': ( 2.4703282292062327E-324, -1.7976931348623158E+308, 1.7976931348623157E+308), } zeropat = re.compile('[1-9]') logger = _GetLogger('ZSI.TC.Decimal') def __init__(self, pname=None, format='%f', **kw): TypeCode.__init__(self, pname, **kw) self.format = format def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' v = text if self.pyclass is not None: return self.pyclass(v) m = _magicnums.get(v) if m: return m try: return float(v) except: raise EvaluateException('Unparseable floating point number', ps.Backtrace(elt)) def parse(self, elt, ps): (ns,type) = self.checkname(elt, ps) elt = self.SimpleHREF(elt, ps, 'floating-point') if not elt: return None tag = getattr(self.__class__, 'type') if tag: if type is None: type = tag elif tag != (ns,type): raise EvaluateException('Floating point type mismatch; ' \ 'got (%s,%s) wanted %s' % (ns,type,tag), ps.Backtrace(elt)) # Special value? if self.nilled(elt, ps): return Nilled v = self.simple_value(elt, ps) try: fp = self.text_to_data(v, elt, ps) except EvaluateException, ex: ex.args.append(ps.Backtrace(elt)) raise ex m = _magicnums.get(v) if m: return m if str(fp).lower() in [ 'inf', '-inf', 'nan', '-nan' ]: raise EvaluateException('Floating point number parsed as "' + \ str(fp) + '"', ps.Backtrace(elt)) if fp == 0 and Decimal.zeropat.search(v): raise EvaluateException('Floating point number parsed as zero', ps.Backtrace(elt)) (rtiny, rneg, rpos) = Decimal.ranges.get(type, (None, None, None)) if rneg and fp < 0 and fp < rneg: raise EvaluateException('Negative underflow', ps.Backtrace(elt)) if rtiny and fp > 0 and fp < rtiny: raise EvaluateException('Positive underflow', ps.Backtrace(elt)) if rpos and fp > 0 and fp > rpos: raise EvaluateException('Overflow', ps.Backtrace(elt)) return fp def get_formatted_content(self, pyobj): if pyobj == _magicnums['INF']: return 'INF' elif pyobj == _magicnums['-INF']: return '-INF' elif isnan(pyobj): return 'NaN' else: return self.format %pyobj class Boolean(SimpleType): '''A boolean. ''' parselist = [ (None,'boolean') ] seriallist = [ bool ] type = (SCHEMA.XSD3, 'boolean') logger = _GetLogger('ZSI.TC.Boolean') def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' v = text if v == 'false': if self.pyclass is None: return False return self.pyclass(False) if v == 'true': if self.pyclass is None: return True return self.pyclass(True) try: v = int(v) except: try: v = long(v) except: raise EvaluateException('Unparseable boolean', ps.Backtrace(elt)) if v: if self.pyclass is None: return True return self.pyclass(True) if self.pyclass is None: return False return self.pyclass(False) def parse(self, elt, ps): self.checkname(elt, ps) elt = self.SimpleHREF(elt, ps, 'boolean') if not elt: return None if self.nilled(elt, ps): return Nilled v = self.simple_value(elt, ps).lower() return self.text_to_data(v, elt, ps) def get_formatted_content(self, pyobj): if pyobj: return 'true' return 'false' #XXX NOT FIXED YET class XML(TypeCode): '''Opaque XML which shouldn't be parsed. comments -- preserve comments inline -- don't href/id when serializing resolver -- object to resolve href's wrapped -- put a wrapper element around it ''' # Clone returned data? copyit = 0 logger = _GetLogger('ZSI.TC.XML') def __init__(self, pname=None, comments=0, inline=0, wrapped=True, **kw): TypeCode.__init__(self, pname, **kw) self.comments = comments self.inline = inline if kw.has_key('resolver'): self.resolver = kw['resolver'] self.wrapped = wrapped self.copyit = kw.get('copyit', XML.copyit) def parse(self, elt, ps): if self.wrapped is False: return elt c = _child_elements(elt) if not c: href = _find_href(elt) if not href: if self.minOccurs == 0: return None raise EvaluateException('Embedded XML document missing', ps.Backtrace(elt)) if href[0] != '#': return ps.ResolveHREF(href, self) elt = ps.FindLocalHREF(href, elt) c = _child_elements(elt) if _find_encstyle(elt) != "": #raise EvaluateException('Embedded XML has unknown encodingStyle', # ps.Backtrace(elt) pass if len(c) != 1: raise EvaluateException('Embedded XML has more than one child', ps.Backtrace(elt)) if self.copyit: return c[0].cloneNode(1) return c[0] def serialize(self, elt, sw, pyobj, name=None, unsuppressedPrefixes=[], **kw): objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) xmlelt = elt if self.wrapped: xmlelt = elt.createAppendElement(ns, n) #if type(pyobj) in _stringtypes: # self.set_attributes(xmlelt, pyobj) # self.set_attribute_href(xmlelt, objid) #elif kw.get('inline', self.inline): # self.cb(xmlelt, sw, pyobj, unsuppressedPrefixes) #else: # self.set_attributes(xmlelt, pyobj) # self.set_attribute_href(xmlelt, objid) # sw.AddCallback(self.cb, elt, sw, pyobj, unsuppressedPrefixes) self.cb(xmlelt, sw, pyobj, unsuppressedPrefixes) def cb(self, elt, sw, pyobj, unsuppressedPrefixes=[]): """pyobj -- xml.dom.Node.ELEMENT_NODE """ #if sw.Known(pyobj): # return if type(pyobj) in _stringtypes: elt.createAppendTextNode(pyobj) return ## grab document and import node, and append it doc = elt.getDocument() node = doc.importNode(pyobj, deep=1) child = elt.node.appendChild(node) ## copy xmlns: attributes into appended node parent = pyobj.parentNode while parent.nodeType == _Node.ELEMENT_NODE: for attr in filter(lambda a: a.name.startswith('xmlns:') and a.name not in child.attributes.keys(), parent.attributes): child.setAttributeNode(attr.cloneNode(1)) parent = parent.parentNode class AnyType(TypeCode): """XML Schema xsi:anyType type definition wildCard. class variables: all -- specifies use of all namespaces. other -- specifies use of other namespaces type -- """ all = '#all' other = '#other' type = (SCHEMA.XSD3, 'anyType') logger = _GetLogger('ZSI.TC.AnyType') def __init__(self, pname=None, namespaces=['#all'], minOccurs=1, maxOccurs=1, strip=1, **kw): TypeCode.__init__(self, pname=pname, minOccurs=minOccurs, maxOccurs=maxOccurs, **kw) self.namespaces = namespaces def get_formatted_content(self, pyobj): # TODO: not sure this makes sense, # parse side will be clueless, but oh well.. what = getattr(pyobj, 'typecode', Any()) return what.get_formatted_content(pyobj) def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. Used only with attributes so will not know anything about this content so why guess? Parameters: text -- text content elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' return text def serialize(self, elt, sw, pyobj, **kw): nsuri,typeName = _get_xsitype(pyobj) if self.all not in self.namespaces and nsuri not in self.namespaces: raise EvaluateException( ' unsupported use of namespaces "%s"' %self.namespaces) what = getattr(pyobj, 'typecode', None) if what is None: # TODO: resolve this, "strict" processing but no # concrete schema makes little sense. #what = _AnyStrict(pname=(self.nspname,self.pname)) what = Any(pname=(self.nspname,self.pname), unique=True, aslist=False) kw['typed'] = True what.serialize(elt, sw, pyobj, **kw) return # Namespace if element AnyType was namespaced. what.serialize(elt, sw, pyobj, name=(self.nspname or what.nspname, self.pname or what.pname), **kw) def parse(self, elt, ps): #element name must be declared .. nspname,pname = _get_element_nsuri_name(elt) if nspname != self.nspname or pname != self.pname: raise EvaluateException(' instance is (%s,%s) found (%s,%s)' %( self.nspname,self.pname,nspname,pname), ps.Backtrace(elt)) #locate xsi:type prefix, typeName = SplitQName(_find_type(elt)) namespaceURI = _resolve_prefix(elt, prefix) pyclass = GTD(namespaceURI, typeName) if not pyclass: if _is_xsd_or_soap_ns(namespaceURI): pyclass = Any elif (str(namespaceURI).lower()==str(Apache.Map.type[0]).lower())\ and (str(typeName).lower() ==str(Apache.Map.type[1]).lower()): pyclass = Apache.Map else: # Unknown type, so parse into a dictionary pyobj = Any().parse_into_dict_or_list(elt, ps) return pyobj what = pyclass(pname=(self.nspname,self.pname)) pyobj = what.parse(elt, ps) return pyobj class AnyElement(AnyType): """XML Schema xsi:any element declaration wildCard. class variables: tag -- global element declaration """ tag = (SCHEMA.XSD3, 'any') logger = _GetLogger('ZSI.TC.AnyElement') def __init__(self, namespaces=['#all'],pname=None, minOccurs=1, maxOccurs=1, strip=1, processContents='strict', **kw): if processContents not in ('lax', 'skip', 'strict'): raise ValueError('processContents(%s) must be lax, skip, or strict') self.processContents = processContents AnyType.__init__(self, namespaces=namespaces,pname=pname, minOccurs=minOccurs, maxOccurs=maxOccurs, strip=strip, **kw) def serialize(self, elt, sw, pyobj, **kw): '''Must provice typecode to AnyElement for serialization, else try to use TC.Any to serialize instance which will serialize based on the data type of pyobj w/o reference to XML schema instance. ''' if isinstance(pyobj, TypeCode): raise TypeError, 'pyobj is a typecode instance.' what = getattr(pyobj, 'typecode', None) if what is not None and type(pyobj) is types.InstanceType: tc = pyobj.__class__ what = Any.serialmap.get(tc) if not what: tc = (types.ClassType, pyobj.__class__.__name__) what = Any.serialmap.get(tc) self.logger.debug('processContents: %s', self.processContents) # failed to find a registered type for class if what is None: #TODO: seems incomplete. what about facets. #if self.processContents == 'strict': what = Any(pname=(self.nspname,self.pname)) self.logger.debug('serialize with %s', what.__class__.__name__) what.serialize(elt, sw, pyobj, **kw) def parse(self, elt, ps): ''' processContents -- 'lax' | 'skip' | 'strict', 'strict' 1) if 'skip' check namespaces, and return the DOM node. 2) if 'lax' look for declaration, or definition. If not found return DOM node. 3) if 'strict' get declaration, or raise. ''' skip = self.processContents == 'skip' nspname,pname = _get_element_nsuri_name(elt) what = GED(nspname, pname) if not skip and what is not None: pyobj = what.parse(elt, ps) try: pyobj.typecode = what except AttributeError, ex: # Assume this means builtin type. pyobj = WrapImmutable(pyobj, what) return pyobj # Allow use of "" element declarations w/ local # element declarations prefix, typeName = SplitQName(_find_type(elt)) if not skip and typeName: namespaceURI = _resolve_prefix(elt, prefix or 'xmlns') # First look thru user defined namespaces, if don't find # look for 'primitives'. pyclass = GTD(namespaceURI, typeName) or Any what = pyclass(pname=(nspname,pname)) pyobj = what.parse(elt, ps) try: pyobj.typecode = what except AttributeError, ex: # Assume this means builtin type. pyobj = WrapImmutable(pyobj, what) what.typed = True return pyobj if skip: what = XML(pname=(nspname,pname), wrapped=False) elif self.processContents == 'lax': what = Any(pname=(nspname,pname), unique=True) else: what = Any(pname=(nspname,pname), unique=True) try: pyobj = what.parse(elt, ps) except EvaluateException, ex: self.logger.debug("error parsing: %s" %str(ex)) if len(_children(elt)) != 0: self.logger.debug('parse , return as dict') return Any(aslist=False).parse_into_dict_or_list(elt, ps) self.logger.debug("Give up, parse (%s,%s) as a String", what.nspname, what.pname) what = String(pname=(nspname,pname), typed=False) return WrapImmutable(what.parse(elt, ps), what) if pyobj is None: return # dict is elementName:value pairs if type(pyobj) is dict: return pyobj try: pyobj.typecode = what except AttributeError: pyobj = WrapImmutable(pyobj, what) return pyobj class Union(SimpleType): '''simpleType Union class variables: memberTypes -- list [(namespace,name),] tuples, each representing a type defintion. ''' memberTypes = None logger = _GetLogger('ZSI.TC.Union') def __init__(self, pname=None, minOccurs=1, maxOccurs=1, **kw): SimpleType.__init__(self, pname=pname, minOccurs=minOccurs, maxOccurs=maxOccurs, **kw) self.memberTypeCodes = [] def setMemberTypeCodes(self): if len(self.memberTypeCodes) > 0: return if self.__class__.memberTypes is None: raise EvaluateException, 'uninitialized class variable memberTypes [(namespace,name),]' for nsuri,name in self.__class__.memberTypes: tcclass = GTD(nsuri,name) if tcclass is None: tc = Any.parsemap.get((nsuri,name)) or Any.parsemap.get((None, name)) typecode = tc.__class__(pname=(self.nspname,self.pname)) else: typecode = tcclass(pname=(self.nspname,self.pname)) if typecode is None: raise EvaluateException, \ 'Typecode class for Union memberType (%s,%s) is missing' %(nsuri,name) if isinstance(typecode, Struct): raise EvaluateException, \ 'Illegal: Union memberType (%s,%s) is complexType' %(nsuri,name) self.memberTypeCodes.append(typecode) def parse(self, elt, ps, **kw): '''attempt to parse sequentially. No way to know ahead of time what this instance represents. Must be simple type so it can not have attributes nor children, so this isn't too bad. ''' self.setMemberTypeCodes() (nsuri,typeName) = self.checkname(elt, ps) #if (nsuri,typeName) not in self.memberTypes: # raise EvaluateException( # 'Union Type mismatch got (%s,%s) not in %s' % \ # (nsuri, typeName, self.memberTypes), ps.Backtrace(elt)) for indx in range(len(self.memberTypeCodes)): typecode = self.memberTypeCodes[indx] try: pyobj = typecode.parse(elt, ps) except ParseException, ex: continue except Exception, ex: continue if indx > 0: self.memberTypeCodes.remove(typecode) self.memberTypeCodes.insert(0, typecode) break else: raise return pyobj def get_formatted_content(self, pyobj, **kw): self.setMemberTypeCodes() for indx in range(len(self.memberTypeCodes)): typecode = self.memberTypeCodes[indx] try: content = typecode.get_formatted_content(copy.copy(pyobj)) break except (ParseException, TypeError): pass if indx > 0: self.memberTypeCodes.remove(typecode) self.memberTypeCodes.insert(0, typecode) else: raise return content class List(SimpleType): '''simpleType List Class data: itemType -- sequence (namespaceURI,name) or a TypeCode instance representing the type definition ''' itemType = None logger = _GetLogger('ZSI.TC.List') def __init__(self, pname=None, itemType=None, **kw): '''Currently need to require maxOccurs=1, so list is interpreted as a single unit of data. ''' assert kw.get('maxOccurs',1) == 1, \ 'Currently only supporting SimpleType Lists with maxOccurs=1' SimpleType.__init__(self, pname=pname, **kw) self.itemType = itemType or self.itemType self.itemTypeCode = self.itemType itemTypeCode = None if type(self.itemTypeCode) in _seqtypes: namespaceURI,name = self.itemTypeCode try: itemTypeCode = GTD(*self.itemType)(None) except: if _is_xsd_or_soap_ns(namespaceURI) is False: raise for pyclass in TYPES: if pyclass.type == self.itemTypeCode: itemTypeCode = pyclass(None) break elif pyclass.type[1] == name: itemTypeCode = pyclass(None) if itemTypeCode is None: raise EvaluateException('Failed to locate %s' %str(self.itemTypeCode)) if hasattr(itemTypeCode, 'text_to_data') is False: raise EvaluateException('TypeCode class %s missing text_to_data method' %itemTypeCode) self.itemTypeCode = itemTypeCode def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. items in list are space separated. ''' v = [] items = text.split() for item in items: v.append(self.itemTypeCode.text_to_data(item, elt, ps)) if self.pyclass is not None: return self.pyclass(v) return v def parse(self, elt, ps): '''elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' self.checkname(elt, ps) if len(_children(elt)) == 0: href = _find_href(elt) if not href: if self.nilled(elt, ps) is False: return [] if self.nillable is True: return Nilled raise EvaluateException('Required string missing', ps.Backtrace(elt)) if href[0] != '#': return ps.ResolveHREF(href, self) elt = ps.FindLocalHREF(href, elt) self.checktype(elt, ps) if self.nilled(elt, ps): return Nilled if len(_children(elt)) == 0: return [] v = self.simple_value(elt, ps) return self.text_to_data(v, elt, ps) def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): '''elt -- the current DOMWrapper element sw -- soapWriter object pyobj -- python object to serialize ''' if pyobj is not None and type(pyobj) not in _seqtypes: raise EvaluateException, 'expecting a list or None' objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) el = elt.createAppendElement(ns, n) if self.nillable is True and pyobj is None: self.serialize_as_nil(el) return None tc = self.itemTypeCode s = StringIO(); sep = ' ' for item in pyobj: s.write(tc.get_formatted_content(item)) s.write(sep) el.createAppendTextNode(s.getvalue()) def RegisterType(C, clobber=0, *args, **keywords): instance = apply(C, args, keywords) for t in C.__dict__.get('parselist', []): prev = Any.parsemap.get(t) if prev: if prev.__class__ == C: continue if not clobber: raise TypeError( str(C) + ' duplicating parse registration for ' + str(t)) Any.parsemap[t] = instance for t in C.__dict__.get('seriallist', []): ti = type(t) if ti in [ types.TypeType, types.ClassType]: key = t elif ti in _stringtypes: key = (types.ClassType, t) else: raise TypeError(str(t) + ' is not a class name') prev = Any.serialmap.get(key) if prev: if prev.__class__ == C: continue if not clobber: raise TypeError( str(C) + ' duplicating serial registration for ' + str(t)) Any.serialmap[key] = instance #def _DynamicImport(moduleName, className): # ''' # Utility function for RegisterTypeWithSchemaAndClass # ''' # mod = __import__(moduleName) # components = moduleName.split('.') # for comp in components[1:]: # mod = getattr(mod, comp) # return getattr(mod, className) # #def _RegisterTypeWithSchemaAndClass(importedSchemaTypes, schemaTypeName, classModuleName, className, generatedClassSuffix="_"): # ''' # Used by RegisterGeneratedTypesWithMapping. # Helps register classes so they can be serialized and parsed as "any". # Register a type by providing its schema and class. This allows # Any and AnyType to reconstruct objects made up of your own classes. # Note: The class module should be able to be imported (by being in your # pythonpath). Your classes __init__ functions shoud have default # arguments for all extra parameters. # Example of use: # import SchemaToPyTypeMap # Mapping written by you. Also used with wsdl2py -m # # mapping = {"SomeDescription":("Descriptions", "SomeDescription"), # # schemaTypeName : moduleName , className # # The module on the next line is generated by wsdl2py # from EchoServer_services_types import urn_ZSI_examples as ExampleTypes # # for key,value in SchemaToPyTypeMap.mapping.items(): # ZSI.TC.RegisterTypeWithSchemaAndClass(importedSchemaTypes = ExampleTypes, schemaTypeName=key, classModuleName=value[0], className=value[1]) # # ''' # # Doing this: (schemaTypeName="ExampleTypes", classModuleName="Description", # # className="SomeDescription") # # sd_instance = ExampleTypes.SomeDescription_(pname="SomeDescription") # # Any.serialmap[Descriptions.SomeDescription] = sd_instance # # Any.parsemap[(None,'SomeDescription')] = sd_instance # classDef = _DynamicImport(classModuleName, className) # interfaceDef = getattr(importedSchemaTypes, schemaTypeName + generatedClassSuffix) # # instance = interfaceDef(pname=className) # Any.serialmap[classDef] = instance # Any.parsemap[(None,schemaTypeName)] = instance # #def RegisterGeneratedTypesWithMapping(generatedTypes, mapping, generatedClassSuffix="_"): # ''' # Registers python classes so they can be serialized and parsed as "any". # generatedTypes is a class containing typecode classes generated by zsi. # mapping is a dictionary that maps # {schemaTypeName : moduleName, className} # and is also used with wsdl2py -m # # Example of use: # import SchemaToPyTypeMap # See RegisterTypeWithSchemaAndClass for description # # The module on the next line is generated by wsdl2py and # # contains generated typecodes. # from EchoServer_services_types import urn_ZSI_examples as ExampleTypes # RegisterGeneratedTypesWithMapping(generatedTypes = ExampleTypes, mapping=SchemaToPyTypeMap.mapping) # ''' # for key,value in mapping.items(): # _RegisterTypeWithSchemaAndClass(importedSchemaTypes = generatedTypes, schemaTypeName=key, classModuleName=value[0], className=value[1], generatedClassSuffix=generatedClassSuffix) from TCnumbers import * from TCtimes import * from schema import GTD, GED, WrapImmutable from TCcompound import * from TCapache import * # aliases backwards compatiblity _get_type_definition, _get_global_element_declaration, Wrap = GTD, GED, WrapImmutable f = lambda x: type(x) == types.ClassType and issubclass(x, TypeCode) and getattr(x, 'type', None) is not None TYPES = filter(f, map(lambda y:eval(y),dir())) if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/.cvsignore0000644000175100017510000000002107365336046013170 0ustar zsizsi*.pyc version.py ZSI-2.1-a1/ZSI/ServiceContainer.py0000644000175100017510000004205610656174245015021 0ustar zsizsi#! /usr/bin/env python '''Simple Service Container -- use with wsdl2py generated modules. ''' import urlparse, types, os, sys, cStringIO as StringIO, thread,re from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from ZSI import ParseException, FaultFromException, FaultFromZSIException, Fault from ZSI import _copyright, _seqtypes, _get_element_nsuri_name, resolvers from ZSI import _get_idstr from ZSI.address import Address from ZSI.parse import ParsedSoap from ZSI.writer import SoapWriter from ZSI.dispatch import _ModPythonSendXML, _ModPythonSendFault, _CGISendXML, _CGISendFault from ZSI.dispatch import SOAPRequestHandler as BaseSOAPRequestHandler """ Functions: _Dispatch AsServer GetSOAPContext Classes: SOAPContext NoSuchService PostNotSpecified SOAPActionNotSpecified ServiceSOAPBinding WSAResource SimpleWSResource SOAPRequestHandler ServiceContainer """ class NoSuchService(Exception): pass class UnknownRequestException(Exception): pass class PostNotSpecified(Exception): pass class SOAPActionNotSpecified(Exception): pass class WSActionException(Exception): pass class WSActionNotSpecified(WSActionException): pass class NotAuthorized(Exception): pass class ServiceAlreadyPresent(Exception): pass class SOAPContext: def __init__(self, container, xmldata, ps, connection, httpheaders, soapaction): self.container = container self.xmldata = xmldata self.parsedsoap = ps self.connection = connection self.httpheaders= httpheaders self.soapaction = soapaction _contexts = dict() def GetSOAPContext(): global _contexts return _contexts[thread.get_ident()] def _Dispatch(ps, server, SendResponse, SendFault, post, action, nsdict={}, **kw): '''Send ParsedSoap instance to ServiceContainer, which dispatches to appropriate service via post, and method via action. Response is a self-describing pyobj, which is passed to a SoapWriter. Call SendResponse or SendFault to send the reply back, appropriately. server -- ServiceContainer instance ''' localURL = 'http://%s:%d%s' %(server.server_name,server.server_port,post) address = action service = server.getNode(post) isWSResource = False if isinstance(service, WSAResource): isWSResource = True service.setServiceURL(localURL) address = Address() try: address.parse(ps) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if action and action != address.getAction(): e = WSActionException('SOAP Action("%s") must match WS-Action("%s") if specified.' \ %(action,address.getAction())) return SendFault(FaultFromException(e, 0, None), **kw) action = address.getAction() if isinstance(service, ServiceInterface) is False: e = NoSuchService('no service at POST(%s) in container: %s' %(post,server)) return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if not service.authorize(None, post, action): return SendFault(Fault(Fault.Server, "Not authorized"), code=401) #try: # raise NotAuthorized() #except Exception, e: #return SendFault(FaultFromException(e, 0, None), code=401, **kw) ##return SendFault(FaultFromException(NotAuthorized(), 0, None), code=401, **kw) try: method = service.getOperation(ps, address) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) try: if isWSResource is True: request,result = method(ps, address) else: request,result = method(ps) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) # Verify if Signed service.verify(ps) # If No response just return. if result is None: return SendResponse('', **kw) sw = SoapWriter(nsdict=nsdict) try: sw.serialize(result) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if isWSResource is True: action = service.getResponseAction(ps, action) addressRsp = Address(action=action) try: addressRsp.setResponseFromWSAddress(address, localURL) addressRsp.serialize(sw) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) # Create Signatures service.sign(sw) try: soapdata = str(sw) return SendResponse(soapdata, **kw) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) def AsServer(port=80, services=()): '''port -- services -- list of service instances ''' address = ('', port) sc = ServiceContainer(address, services) sc.serve_forever() class ServiceInterface: '''Defines the interface for use with ServiceContainer Handlers. class variables: soapAction -- dictionary of soapAction keys, and operation name values. These are specified in the WSDL soap bindings. There must be a class method matching the operation name value. If WS-Action is used the keys are WS-Action request values, according to the spec if soapAction and WS-Action is specified they must be equal. wsAction -- dictionary of operation name keys and WS-Action response values. These values are specified by the portType. root -- dictionary of root element keys, and operation name values. ''' soapAction = {} wsAction = {} root = {} def __init__(self, post): self.post = post def authorize(self, auth_info, post, action): return 1 def __str__(self): return '%s(%s) POST(%s)' %(self.__class__.__name__, _get_idstr(self), self.post) def sign(self, sw): return def verify(self, ps): return def getPost(self): return self.post def getOperation(self, ps, action): '''Returns a method of class. action -- soapAction value ''' opName = self.getOperationName(ps, action) return getattr(self, opName) def getOperationName(self, ps, action): '''Returns operation name. action -- soapAction value ''' method = self.root.get(_get_element_nsuri_name(ps.body_root)) or \ self.soapAction.get(action) if method is None: raise UnknownRequestException, \ 'failed to map request to a method: action(%s), root%s' %(action,_get_element_nsuri_name(ps.body_root)) return method class ServiceSOAPBinding(ServiceInterface): '''Binding defines the set of wsdl:binding operations, it takes as input a ParsedSoap instance and parses it into a pyobj. It returns a response pyobj. ''' def __init__(self, post): ServiceInterface.__init__(self, post) def __call___(self, action, ps): return self.getOperation(ps, action)(ps) class WSAResource(ServiceSOAPBinding): '''Simple WSRF service, performs method resolutions based on WS-Action values rather than SOAP Action. class variables: encoding wsAction -- Must override to set output Action values. soapAction -- Must override to set input Action values. ''' encoding = "UTF-8" def __init__(self, post): ''' post -- POST value ''' assert isinstance(self.soapAction, dict), "soapAction must be a dict" assert isinstance(self.wsAction, dict), "wsAction must be a dict" ServiceSOAPBinding.__init__(self, post) def __call___(self, action, ps, address): return self.getOperation(ps, action)(ps, address) def getServiceURL(self): return self._url def setServiceURL(self, url): self._url = url def getOperation(self, ps, address): '''Returns a method of class. address -- ws-address ''' action = address.getAction() opName = self.getOperationName(ps, action) return getattr(self, opName) def getResponseAction(self, ps, action): '''Returns response WS-Action if available action -- request WS-Action value. ''' opName = self.getOperationName(ps, action) if self.wsAction.has_key(opName) is False: raise WSActionNotSpecified, 'wsAction dictionary missing key(%s)' %opName return self.wsAction[opName] def do_POST(self): '''The POST command. This is called by HTTPServer, not twisted. action -- SOAPAction(HTTP header) or wsa:Action(SOAP:Header) ''' global _contexts soapAction = self.headers.getheader('SOAPAction') post = self.path if not post: raise PostNotSpecified, 'HTTP POST not specified in request' if soapAction: soapAction = soapAction.strip('\'"') post = post.strip('\'"') try: ct = self.headers['content-type'] if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, self.rfile) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve, readerclass=DomletteReader) else: length = int(self.headers['content-length']) ps = ParsedSoap(self.rfile.read(length), readerclass=DomletteReader) except ParseException, e: self.send_fault(FaultFromZSIException(e)) except Exception, e: # Faulted while processing; assume it's in the header. self.send_fault(FaultFromException(e, 1, sys.exc_info()[2])) else: # Keep track of calls thread_id = thread.get_ident() _contexts[thread_id] = SOAPContext(self.server, xml, ps, self.connection, self.headers, soapAction) try: _Dispatch(ps, self.server, self.send_xml, self.send_fault, post=post, action=soapAction) except Exception, e: self.send_fault(FaultFromException(e, 0, sys.exc_info()[2])) # Clean up after the call if _contexts.has_key(thread_id): del _contexts[thread_id] class SOAPRequestHandler(BaseSOAPRequestHandler): '''SOAP handler. ''' def do_POST(self): '''The POST command. action -- SOAPAction(HTTP header) or wsa:Action(SOAP:Header) ''' soapAction = self.headers.getheader('SOAPAction') post = self.path if not post: raise PostNotSpecified, 'HTTP POST not specified in request' if soapAction: soapAction = soapAction.strip('\'"') post = post.strip('\'"') try: ct = self.headers['content-type'] if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, self.rfile) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(self.headers['content-length']) xml = self.rfile.read(length) ps = ParsedSoap(xml) except ParseException, e: self.send_fault(FaultFromZSIException(e)) except Exception, e: # Faulted while processing; assume it's in the header. self.send_fault(FaultFromException(e, 1, sys.exc_info()[2])) else: # Keep track of calls thread_id = thread.get_ident() _contexts[thread_id] = SOAPContext(self.server, xml, ps, self.connection, self.headers, soapAction) try: _Dispatch(ps, self.server, self.send_xml, self.send_fault, post=post, action=soapAction) except Exception, e: self.send_fault(FaultFromException(e, 0, sys.exc_info()[2])) # Clean up after the call if _contexts.has_key(thread_id): del _contexts[thread_id] def do_GET(self): '''The GET command. ''' if self.path.lower().endswith("?wsdl"): service_path = self.path[:-5] service = self.server.getNode(service_path) if hasattr(service, "_wsdl"): wsdl = service._wsdl # update the soap:location tag in the wsdl to the actual server # location # - default to 'http' as protocol, or use server-specified protocol proto = 'http' if hasattr(self.server,'proto'): proto = self.server.proto serviceUrl = '%s://%s:%d%s' % (proto, self.server.server_name, self.server.server_port, service_path) soapAddress = '' % serviceUrl wsdlre = re.compile('\]*>',re.IGNORECASE) wsdl = re.sub(wsdlre,soapAddress,wsdl) self.send_xml(wsdl) else: self.send_error(404, "WSDL not available for that service [%s]." % self.path) else: self.send_error(404, "Service not found [%s]." % self.path) class ServiceContainer(HTTPServer): '''HTTPServer that stores service instances according to POST values. An action value is instance specific, and specifies an operation (function) of an instance. ''' class NodeTree: '''Simple dictionary implementation of a node tree ''' def __init__(self): self.__dict = {} def __str__(self): return str(self.__dict) def listNodes(self): print self.__dict.keys() def getNode(self, url): path = urlparse.urlsplit(url)[2] if path.startswith("/"): path = path[1:] if self.__dict.has_key(path): return self.__dict[path] else: raise NoSuchService, 'No service(%s) in ServiceContainer' %path def setNode(self, service, url): path = urlparse.urlsplit(url)[2] if path.startswith("/"): path = path[1:] if not isinstance(service, ServiceSOAPBinding): raise TypeError, 'A Service must implement class ServiceSOAPBinding' if self.__dict.has_key(path): raise ServiceAlreadyPresent, 'Service(%s) already in ServiceContainer' % path else: self.__dict[path] = service def removeNode(self, url): path = urlparse.urlsplit(url)[2] if path.startswith("/"): path = path[1:] if self.__dict.has_key(path): node = self.__dict[path] del self.__dict[path] return node else: raise NoSuchService, 'No service(%s) in ServiceContainer' %path def __init__(self, server_address, services=[], RequestHandlerClass=SOAPRequestHandler): '''server_address -- RequestHandlerClass -- ''' HTTPServer.__init__(self, server_address, RequestHandlerClass) self._nodes = self.NodeTree() map(lambda s: self.setNode(s), services) def __str__(self): return '%s(%s) nodes( %s )' %(self.__class__, _get_idstr(self), str(self._nodes)) def __call__(self, ps, post, action, address=None): '''ps -- ParsedSoap representing the request post -- HTTP POST --> instance action -- Soap Action header --> method address -- Address instance representing WS-Address ''' method = self.getCallBack(ps, post, action) if (isinstance(method.im_self, WSAResource) or isinstance(method.im_self, SimpleWSResource)): return method(ps, address) return method(ps) def setNode(self, service, url=None): if url is None: url = service.getPost() self._nodes.setNode(service, url) def getNode(self, url): return self._nodes.getNode(url) def removeNode(self, url): self._nodes.removeNode(url) class SimpleWSResource(ServiceSOAPBinding): def getNode(self, post): '''post -- POST HTTP value ''' return self._nodes.getNode(post) def setNode(self, service, post): '''service -- service instance post -- POST HTTP value ''' self._nodes.setNode(service, post) def getCallBack(self, ps, post, action): '''post -- POST HTTP value action -- SOAP Action value ''' node = self.getNode(post) if node is None: raise NoSuchFunction if node.authorize(None, post, action): return node.getOperation(ps, action) else: raise NotAuthorized, "Authorization failed for method %s" % action if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/resolvers.py0000644000175100017510000001122307466521042013566 0ustar zsizsi#! /usr/bin/env python # $Header$ '''SOAP messaging parsing. ''' from ZSI import _copyright, _child_elements, EvaluateException, TC import multifile, mimetools, urllib from base64 import decodestring as b64decode import cStringIO as StringIO def Opaque(uri, tc, ps, **keywords): '''Resolve a URI and return its content as a string. ''' source = urllib.urlopen(uri, **keywords) enc = source.info().getencoding() if enc in ['7bit', '8bit', 'binary']: return source.read() data = StringIO.StringIO() mimetools.decode(source, data, enc) return data.getvalue() def XML(uri, tc, ps, **keywords): '''Resolve a URI and return its content as an XML DOM. ''' source = urllib.urlopen(uri, **keywords) enc = source.info().getencoding() if enc in ['7bit', '8bit', 'binary']: data = source else: data = StringIO.StringIO() mimetools.decode(source, data, enc) data.seek(0) dom = ps.readerclass().fromStream(data) return _child_elements(dom)[0] class NetworkResolver: '''A resolver that support string and XML. ''' def __init__(self, prefix=None): self.allowed = prefix or [] def _check_allowed(self, uri): for a in self.allowed: if uri.startswith(a): return raise EvaluateException("Disallowed URI prefix") def Opaque(self, uri, tc, ps, **keywords): self._check_allowed(uri) return Opaque(uri, tc, ps, **keywords) def XML(self, uri, tc, ps, **keywords): self._check_allowed(uri) return XML(uri, tc, ps, **keywords) def Resolve(self, uri, tc, ps, **keywords): if isinstance(tc, TC.XML): return XML(uri, tc, ps, **keywords) return Opaque(uri, tc, ps, **keywords) class MIMEResolver: '''Multi-part MIME resolver -- SOAP With Attachments, mostly. ''' def __init__(self, ct, f, next=None, uribase='thismessage:/', seekable=0, **kw): # Get the boundary. It's too bad I have to write this myself, # but no way am I going to import cgi for 10 lines of code! for param in ct.split(';'): a = param.strip() if a.startswith('boundary='): if a[9] in [ '"', "'" ]: boundary = a[10:-1] else: boundary = a[9:] break else: raise ValueError('boundary parameter not found') self.id_dict, self.loc_dict, self.parts = {}, {}, [] self.next = next self.base = uribase mf = multifile.MultiFile(f, seekable) mf.push(boundary) while mf.next(): head = mimetools.Message(mf) body = StringIO.StringIO() mimetools.decode(mf, body, head.getencoding()) body.seek(0) part = (head, body) self.parts.append(part) key = head.get('content-id') if key: if key[0] == '<' and key[-1] == '>': key = key[1:-1] self.id_dict[key] = part key = head.get('content-location') if key: self.loc_dict[key] = part mf.pop() def GetSOAPPart(self): '''Get the SOAP body part. ''' head, part = self.parts[0] return StringIO.StringIO(part.getvalue()) def get(self, uri): '''Get the content for the bodypart identified by the uri. ''' if uri.startswith('cid:'): # Content-ID, so raise exception if not found. head, part = self.id_dict[uri[4:]] return StringIO.StringIO(part.getvalue()) if self.loc_dict.has_key(uri): head, part = self.loc_dict[uri] return StringIO.StringIO(part.getvalue()) return None def Opaque(self, uri, tc, ps, **keywords): content = self.get(uri) if content: return content.getvalue() if not self.next: raise EvaluateException("Unresolvable URI " + uri) return self.next.Opaque(uri, tc, ps, **keywords) def XML(self, uri, tc, ps, **keywords): content = self.get(uri) if content: dom = ps.readerclass().fromStream(content) return _child_elements(dom)[0] if not self.next: raise EvaluateException("Unresolvable URI " + uri) return self.next.XML(uri, tc, ps, **keywords) def Resolve(self, uri, tc, ps, **keywords): if isinstance(tc, TC.XML): return self.XML(uri, tc, ps, **keywords) return self.Opaque(uri, tc, ps, **keywords) def __getitem__(self, cid): head, body = self.id_dict[cid] newio = StringIO.StringIO(body.getvalue()) return newio if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/client.py0000755000175100017510000005252610641306321013024 0ustar zsizsi#! /usr/bin/env python # $Header$ # # Copyright (c) 2001 Zolera Systems. All rights reserved. from ZSI import _copyright, _seqtypes, ParsedSoap, SoapWriter, TC, ZSI_SCHEMA_URI,\ EvaluateException, FaultFromFaultMessage, _child_elements, _attrs, _find_arraytype,\ _find_type, _get_idstr, _get_postvalue_from_absoluteURI, FaultException, WSActionException,\ UNICODE_ENCODING from ZSI.auth import AUTH from ZSI.TC import AnyElement, AnyType, String, TypeCode, _get_global_element_declaration,\ _get_type_definition from ZSI.TCcompound import Struct import base64, httplib, Cookie, types, time, urlparse from ZSI.address import Address from ZSI.wstools.logging import getLogger as _GetLogger _b64_encode = base64.encodestring class _AuthHeader: """ %s%s """ def __init__(self, name=None, password=None): self.Name = name self.Password = password _AuthHeader.typecode = Struct(_AuthHeader, ofwhat=(String((ZSI_SCHEMA_URI,'Name'), typed=False), String((ZSI_SCHEMA_URI,'Password'), typed=False)), pname=(ZSI_SCHEMA_URI,'BasicAuth'), typed=False) class _Caller: '''Internal class used to give the user a callable object that calls back to the Binding object to make an RPC call. ''' def __init__(self, binding, name, namespace=None): self.binding = binding self.name = name self.namespace = namespace def __call__(self, *args): nsuri = self.namespace if nsuri is None: return self.binding.RPC(None, self.name, args, encodingStyle="http://schemas.xmlsoap.org/soap/encoding/", replytype=TC.Any(self.name+"Response")) return self.binding.RPC(None, (nsuri,self.name), args, encodingStyle="http://schemas.xmlsoap.org/soap/encoding/", replytype=TC.Any((nsuri,self.name+"Response"))) class _NamedParamCaller: '''Similar to _Caller, expect that there are named parameters not positional. ''' def __init__(self, binding, name, namespace=None): self.binding = binding self.name = name self.namespace = namespace def __call__(self, **params): # Pull out arguments that Send() uses kw = {} for key in [ 'auth_header', 'nsdict', 'requesttypecode', 'soapaction' ]: if params.has_key(key): kw[key] = params[key] del params[key] nsuri = self.namespace if nsuri is None: return self.binding.RPC(None, self.name, None, encodingStyle="http://schemas.xmlsoap.org/soap/encoding/", _args=params, replytype=TC.Any(self.name+"Response", aslist=False), **kw) return self.binding.RPC(None, (nsuri,self.name), None, encodingStyle="http://schemas.xmlsoap.org/soap/encoding/", _args=params, replytype=TC.Any((nsuri,self.name+"Response"), aslist=False), **kw) class _Binding: '''Object that represents a binding (connection) to a SOAP server. Once the binding is created, various ways of sending and receiving SOAP messages are available. ''' defaultHttpTransport = httplib.HTTPConnection defaultHttpsTransport = httplib.HTTPSConnection logger = _GetLogger('ZSI.client.Binding') def __init__(self, nsdict=None, transport=None, url=None, tracefile=None, readerclass=None, writerclass=None, soapaction='', wsAddressURI=None, sig_handler=None, transdict=None, **kw): '''Initialize. Keyword arguments include: transport -- default use HTTPConnection. transdict -- dict of values to pass to transport. url -- URL of resource, POST is path soapaction -- value of SOAPAction header auth -- (type, name, password) triplet; default is unauth nsdict -- namespace entries to add tracefile -- file to dump packet traces cert_file, key_file -- SSL data (q.v.) readerclass -- DOM reader class writerclass -- DOM writer class, implements MessageInterface wsAddressURI -- namespaceURI of WS-Address to use. By default it's not used. sig_handler -- XML Signature handler, must sign and verify. endPointReference -- optional Endpoint Reference. ''' self.data = None self.ps = None self.user_headers = [] self.nsdict = nsdict or {} self.transport = transport self.transdict = transdict or {} self.url = url self.trace = tracefile self.readerclass = readerclass self.writerclass = writerclass self.soapaction = soapaction self.wsAddressURI = wsAddressURI self.sig_handler = sig_handler self.address = None self.endPointReference = kw.get('endPointReference', None) self.cookies = Cookie.SimpleCookie() self.http_callbacks = {} if kw.has_key('auth'): self.SetAuth(*kw['auth']) else: self.SetAuth(AUTH.none) def SetAuth(self, style, user=None, password=None): '''Change auth style, return object to user. ''' self.auth_style, self.auth_user, self.auth_pass = \ style, user, password return self def SetURL(self, url): '''Set the URL we post to. ''' self.url = url return self def ResetHeaders(self): '''Empty the list of additional headers. ''' self.user_headers = [] return self def ResetCookies(self): '''Empty the list of cookies. ''' self.cookies = Cookie.SimpleCookie() def AddHeader(self, header, value): '''Add a header to send. ''' self.user_headers.append((header, value)) return self def __addcookies(self): '''Add cookies from self.cookies to request in self.h ''' for cname, morsel in self.cookies.items(): attrs = [] value = morsel.get('version', '') if value != '' and value != '0': attrs.append('$Version=%s' % value) attrs.append('%s=%s' % (cname, morsel.coded_value)) value = morsel.get('path') if value: attrs.append('$Path=%s' % value) value = morsel.get('domain') if value: attrs.append('$Domain=%s' % value) self.h.putheader('Cookie', "; ".join(attrs)) def RPC(self, url, opname, obj, replytype=None, **kw): '''Send a request, return the reply. See Send() and Recieve() docstrings for details. ''' self.Send(url, opname, obj, **kw) return self.Receive(replytype, **kw) def Send(self, url, opname, obj, nsdict={}, soapaction=None, wsaction=None, endPointReference=None, soapheaders=(), **kw): '''Send a message. If url is None, use the value from the constructor (else error). obj is the object (data) to send. Data may be described with a requesttypecode keyword, the default is the class's typecode (if there is one), else Any. Try to serialize as a Struct, if this is not possible serialize an Array. If data is a sequence of built-in python data types, it will be serialized as an Array, unless requesttypecode is specified. arguments: url -- opname -- struct wrapper obj -- python instance key word arguments: nsdict -- soapaction -- wsaction -- WS-Address Action, goes in SOAP Header. endPointReference -- set by calling party, must be an EndPointReference type instance. soapheaders -- list of pyobj, typically w/typecode attribute. serialized in the SOAP:Header. requesttypecode -- ''' url = url or self.url endPointReference = endPointReference or self.endPointReference # Serialize the object. d = {} d.update(self.nsdict) d.update(nsdict) sw = SoapWriter(nsdict=d, header=True, outputclass=self.writerclass, encodingStyle=kw.get('encodingStyle'),) requesttypecode = kw.get('requesttypecode') if kw.has_key('_args'): #NamedParamBinding tc = requesttypecode or TC.Any(pname=opname, aslist=False) sw.serialize(kw['_args'], tc) elif not requesttypecode: tc = getattr(obj, 'typecode', None) or TC.Any(pname=opname, aslist=False) try: if type(obj) in _seqtypes: obj = dict(map(lambda i: (i.typecode.pname,i), obj)) except AttributeError: # can't do anything but serialize this in a SOAP:Array tc = TC.Any(pname=opname, aslist=True) else: tc = TC.Any(pname=opname, aslist=False) sw.serialize(obj, tc) else: sw.serialize(obj, requesttypecode) for i in soapheaders: sw.serialize_header(i) # # Determine the SOAP auth element. SOAP:Header element if self.auth_style & AUTH.zsibasic: sw.serialize_header(_AuthHeader(self.auth_user, self.auth_pass), _AuthHeader.typecode) # # Serialize WS-Address if self.wsAddressURI is not None: if self.soapaction and wsaction.strip('\'"') != self.soapaction: raise WSActionException, 'soapAction(%s) and WS-Action(%s) must match'\ %(self.soapaction,wsaction) self.address = Address(url, self.wsAddressURI) self.address.setRequest(endPointReference, wsaction) self.address.serialize(sw) # # WS-Security Signature Handler if self.sig_handler is not None: self.sig_handler.sign(sw) scheme,netloc,path,nil,nil,nil = urlparse.urlparse(url) transport = self.transport if transport is None and url is not None: if scheme == 'https': transport = self.defaultHttpsTransport elif scheme == 'http': transport = self.defaultHttpTransport else: raise RuntimeError, 'must specify transport or url startswith https/http' # Send the request. if issubclass(transport, httplib.HTTPConnection) is False: raise TypeError, 'transport must be a HTTPConnection' soapdata = str(sw) self.h = transport(netloc, None, **self.transdict) self.h.connect() self.SendSOAPData(soapdata, url, soapaction, **kw) def SendSOAPData(self, soapdata, url, soapaction, headers={}, **kw): # Tracing? if self.trace: print >>self.trace, "_" * 33, time.ctime(time.time()), "REQUEST:" print >>self.trace, soapdata url = url or self.url request_uri = _get_postvalue_from_absoluteURI(url) self.h.putrequest("POST", request_uri) self.h.putheader("Content-Length", "%d" % len(soapdata)) self.h.putheader("Content-Type", 'text/xml; charset="%s"' %UNICODE_ENCODING) self.__addcookies() for header,value in headers.items(): self.h.putheader(header, value) SOAPActionValue = '"%s"' % (soapaction or self.soapaction) self.h.putheader("SOAPAction", SOAPActionValue) if self.auth_style & AUTH.httpbasic: val = _b64_encode(self.auth_user + ':' + self.auth_pass) \ .replace("\012", "") self.h.putheader('Authorization', 'Basic ' + val) elif self.auth_style == AUTH.httpdigest and not headers.has_key('Authorization') \ and not headers.has_key('Expect'): def digest_auth_cb(response): self.SendSOAPDataHTTPDigestAuth(response, soapdata, url, request_uri, soapaction, **kw) self.http_callbacks[401] = None self.http_callbacks[401] = digest_auth_cb for header,value in self.user_headers: self.h.putheader(header, value) self.h.endheaders() self.h.send(soapdata) # Clear prior receive state. self.data, self.ps = None, None def SendSOAPDataHTTPDigestAuth(self, response, soapdata, url, request_uri, soapaction, **kw): '''Resend the initial request w/http digest authorization headers. The SOAP server has requested authorization. Fetch the challenge, generate the authdict for building a response. ''' if self.trace: print >>self.trace, "------ Digest Auth Header" url = url or self.url if response.status != 401: raise RuntimeError, 'Expecting HTTP 401 response.' if self.auth_style != AUTH.httpdigest: raise RuntimeError,\ 'Auth style(%d) does not support requested digest authorization.' %self.auth_style from ZSI.digest_auth import fetch_challenge,\ generate_response,\ build_authorization_arg,\ dict_fetch chaldict = fetch_challenge( response.getheader('www-authenticate') ) if dict_fetch(chaldict,'challenge','').lower() == 'digest' and \ dict_fetch(chaldict,'nonce',None) and \ dict_fetch(chaldict,'realm',None) and \ dict_fetch(chaldict,'qop',None): authdict = generate_response(chaldict, request_uri, self.auth_user, self.auth_pass, method='POST') headers = {\ 'Authorization':build_authorization_arg(authdict), 'Expect':'100-continue', } self.SendSOAPData(soapdata, url, soapaction, headers, **kw) return raise RuntimeError,\ 'Client expecting digest authorization challenge.' def ReceiveRaw(self, **kw): '''Read a server reply, unconverted to any format and return it. ''' if self.data: return self.data trace = self.trace while 1: response = self.h.getresponse() self.reply_code, self.reply_msg, self.reply_headers, self.data = \ response.status, response.reason, response.msg, response.read() if trace: print >>trace, "_" * 33, time.ctime(time.time()), "RESPONSE:" for i in (self.reply_code, self.reply_msg,): print >>trace, str(i) print >>trace, "-------" print >>trace, str(self.reply_headers) print >>trace, self.data saved = None for d in response.msg.getallmatchingheaders('set-cookie'): if d[0] in [ ' ', '\t' ]: saved += d.strip() else: if saved: self.cookies.load(saved) saved = d.strip() if saved: self.cookies.load(saved) if response.status == 401: if not callable(self.http_callbacks.get(response.status,None)): raise RuntimeError, 'HTTP Digest Authorization Failed' self.http_callbacks[response.status](response) continue if response.status != 100: break # The httplib doesn't understand the HTTP continuation header. # Horrible internals hack to patch things up. self.h._HTTPConnection__state = httplib._CS_REQ_SENT self.h._HTTPConnection__response = None return self.data def IsSOAP(self): if self.ps: return 1 self.ReceiveRaw() mimetype = self.reply_headers.type return mimetype == 'text/xml' def ReceiveSOAP(self, readerclass=None, **kw): '''Get back a SOAP message. ''' if self.ps: return self.ps if not self.IsSOAP(): raise TypeError( 'Response is "%s", not "text/xml"' % self.reply_headers.type) if len(self.data) == 0: raise TypeError('Received empty response') self.ps = ParsedSoap(self.data, readerclass=readerclass or self.readerclass, encodingStyle=kw.get('encodingStyle')) if self.sig_handler is not None: self.sig_handler.verify(self.ps) return self.ps def IsAFault(self): '''Get a SOAP message, see if it has a fault. ''' self.ReceiveSOAP() return self.ps.IsAFault() def ReceiveFault(self, **kw): '''Parse incoming message as a fault. Raise TypeError if no fault found. ''' self.ReceiveSOAP(**kw) if not self.ps.IsAFault(): raise TypeError("Expected SOAP Fault not found") return FaultFromFaultMessage(self.ps) def Receive(self, replytype, **kw): '''Parse message, create Python object. KeyWord data: faults -- list of WSDL operation.fault typecodes wsaction -- If using WS-Address, must specify Action value we expect to receive. ''' self.ReceiveSOAP(**kw) if self.ps.IsAFault(): msg = FaultFromFaultMessage(self.ps) raise FaultException(msg) tc = replytype if hasattr(replytype, 'typecode'): tc = replytype.typecode reply = self.ps.Parse(tc) if self.address is not None: self.address.checkResponse(self.ps, kw.get('wsaction')) return reply def __repr__(self): return "<%s instance %s>" % (self.__class__.__name__, _get_idstr(self)) class Binding(_Binding): '''Object that represents a binding (connection) to a SOAP server. Can be used in the "name overloading" style. class attr: gettypecode -- funcion that returns typecode from typesmodule, can be set so can use whatever mapping you desire. ''' gettypecode = staticmethod(lambda mod,e: getattr(mod, str(e.localName)).typecode) logger = _GetLogger('ZSI.client.Binding') def __init__(self, url, namespace=None, typesmodule=None, **kw): """ Parameters: url -- location of service namespace -- optional root element namespace typesmodule -- optional response only. dict(name=typecode), lookup for all children of root element. """ self.typesmodule = typesmodule self.namespace = namespace _Binding.__init__(self, url=url, **kw) def __getattr__(self, name): '''Return a callable object that will invoke the RPC method named by the attribute. ''' if name[:2] == '__' and len(name) > 5 and name[-2:] == '__': if hasattr(self, name): return getattr(self, name) return getattr(self.__class__, name) return _Caller(self, name, self.namespace) def __parse_child(self, node): '''for rpc-style map each message part to a class in typesmodule ''' try: tc = self.gettypecode(self.typesmodule, node) except: self.logger.debug('didnt find typecode for "%s" in typesmodule: %s', node.localName, self.typesmodule) tc = TC.Any(aslist=1) return tc.parse(node, self.ps) self.logger.debug('parse child with typecode : %s', tc) try: return tc.parse(node, self.ps) except Exception: self.logger.debug('parse failed try Any : %s', tc) tc = TC.Any(aslist=1) return tc.parse(node, self.ps) def Receive(self, replytype, **kw): '''Parse message, create Python object. KeyWord data: faults -- list of WSDL operation.fault typecodes wsaction -- If using WS-Address, must specify Action value we expect to receive. ''' self.ReceiveSOAP(**kw) ps = self.ps tp = _find_type(ps.body_root) isarray = ((type(tp) in (tuple,list) and tp[1] == 'Array') or _find_arraytype(ps.body_root)) if self.typesmodule is None or isarray: return _Binding.Receive(self, replytype, **kw) if ps.IsAFault(): msg = FaultFromFaultMessage(ps) raise FaultException(msg) tc = replytype if hasattr(replytype, 'typecode'): tc = replytype.typecode #Ignore response wrapper reply = {} for elt in _child_elements(ps.body_root): name = str(elt.localName) reply[name] = self.__parse_child(elt) if self.address is not None: self.address.checkResponse(ps, kw.get('wsaction')) return reply class NamedParamBinding(Binding): '''Like Binding, except the argument list for invocation is named parameters. ''' logger = _GetLogger('ZSI.client.Binding') def __getattr__(self, name): '''Return a callable object that will invoke the RPC method named by the attribute. ''' if name[:2] == '__' and len(name) > 5 and name[-2:] == '__': if hasattr(self, name): return getattr(self, name) return getattr(self.__class__, name) return _NamedParamCaller(self, name, self.namespace) if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/address.py0000644000175100017510000002160610712164103013162 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! ########################################################################### import time, urlparse, socket from ZSI import _seqtypes, EvaluateException, WSActionException from TC import AnyElement, AnyType, TypeCode from schema import GED, GTD, _has_type_definition from ZSI.TCcompound import ComplexType from ZSI.wstools.Namespaces import WSA_LIST class Address(object): '''WS-Address Implemented is dependent on the default "wsdl2py" convention of generating aname, so the attributes representing element declaration names should be prefixed with an underscore. ''' def __init__(self, addressTo=None, wsAddressURI=None, action=None): self.wsAddressURI = wsAddressURI self.anonymousURI = None self._addressTo = addressTo self._messageID = None self._action = action self._endPointReference = None self._replyTo = None self._relatesTo = None self.setUp() def setUp(self): '''Look for WS-Address ''' toplist = filter(lambda wsa: wsa.ADDRESS==self.wsAddressURI, WSA_LIST) epr = 'EndpointReferenceType' for WSA in toplist+WSA_LIST: if (self.wsAddressURI is not None and self.wsAddressURI != WSA.ADDRESS) or \ _has_type_definition(WSA.ADDRESS, epr) is True: break else: raise EvaluateException,\ 'enabling wsAddressing requires the inclusion of that namespace' self.wsAddressURI = WSA.ADDRESS self.anonymousURI = WSA.ANONYMOUS self._replyTo = WSA.ANONYMOUS def _checkAction(self, action, value): '''WS-Address Action action -- Action value expecting. value -- Action value server returned. ''' if action is None: raise WSActionException, 'Response missing WSAddress Action' if not value: raise WSActionException, 'missing WSAddress Action, expecting %s' %action if value != action: raise WSActionException, 'wrong WSAddress Action(%s), expecting %s'%(value,action) def _checkFrom(self, pyobj): '''WS-Address From, XXX currently not checking the hostname, not forwarding messages. pyobj -- From server returned. ''' if pyobj is None: return value = pyobj._Address if value != self._addressTo: scheme,netloc,path,query,fragment = urlparse.urlsplit(value) hostport = netloc.split(':') schemeF,netlocF,pathF,queryF,fragmentF = urlparse.urlsplit(self._addressTo) if scheme==schemeF and path==pathF and query==queryF and fragment==fragmentF: netloc = netloc.split(':') + ['80'] netlocF = netlocF.split(':') + ['80'] if netloc[1]==netlocF[1] and (socket.gethostbyname(netlocF[0]) in ('127.0.0.1', socket.gethostbyname(netloc[0]))): return raise WSActionException, 'wrong WS-Address From(%s), expecting %s'%(value,self._addressTo) def _checkRelatesTo(self, value): '''WS-Address From value -- From server returned. ''' if value != self._messageID: raise WSActionException, 'wrong WS-Address RelatesTo(%s), expecting %s'%(value,self._messageID) def _checkReplyTo(self, value): '''WS-Address From value -- From server returned in wsa:To ''' if value != self._replyTo: raise WSActionException, 'wrong WS-Address ReplyTo(%s), expecting %s'%(value,self._replyTo) def setAction(self, action): self._action = action def getAction(self): return self._action def getRelatesTo(self): return self._relatesTo def getMessageID(self): return self._messageID def _getWSAddressTypeCodes(self, **kw): '''kw -- namespaceURI keys with sequence of element names. ''' typecodes = [] try: for nsuri,elements in kw.items(): for el in elements: typecode = GED(nsuri, el) if typecode is None: raise WSActionException, 'Missing namespace, import "%s"' %nsuri typecodes.append(typecode) else: pass except EvaluateException, ex: raise EvaluateException, \ 'To use ws-addressing register typecodes for namespace(%s)' %self.wsAddressURI return typecodes def checkResponse(self, ps, action): ''' ps -- ParsedSoap action -- ws-action for response ''' namespaceURI = self.wsAddressURI d = {namespaceURI:("MessageID","Action","To","From","RelatesTo")} typecodes = self._getWSAddressTypeCodes(**d) pyobjs = ps.ParseHeaderElements(typecodes) got_action = pyobjs.get((namespaceURI,"Action")) self._checkAction(action, got_action) From = pyobjs.get((namespaceURI,"From")) self._checkFrom(From) RelatesTo = pyobjs.get((namespaceURI,"RelatesTo")) self._checkRelatesTo(RelatesTo) To = pyobjs.get((namespaceURI,"To")) if To: self._checkReplyTo(To) def setRequest(self, endPointReference, action): '''Call For Request ''' self._action = action self.header_pyobjs = None pyobjs = [] namespaceURI = self.wsAddressURI addressTo = self._addressTo messageID = self._messageID = "uuid:%s" %time.time() # Set Message Information Headers # MessageID typecode = GED(namespaceURI, "MessageID") pyobjs.append(typecode.pyclass(messageID)) # Action typecode = GED(namespaceURI, "Action") pyobjs.append(typecode.pyclass(action)) # To typecode = GED(namespaceURI, "To") pyobjs.append(typecode.pyclass(addressTo)) # From typecode = GED(namespaceURI, "From") mihFrom = typecode.pyclass() mihFrom._Address = self.anonymousURI pyobjs.append(mihFrom) if endPointReference: if hasattr(endPointReference, 'typecode') is False: raise EvaluateException, 'endPointReference must have a typecode attribute' if isinstance(endPointReference.typecode, \ GTD(namespaceURI ,'EndpointReferenceType')) is False: raise EvaluateException, 'endPointReference must be of type %s' \ %GTD(namespaceURI ,'EndpointReferenceType') ReferenceProperties = getattr(endPointReference, '_ReferenceProperties', None) if ReferenceProperties is not None: for v in getattr(ReferenceProperties, '_any', ()): if not hasattr(v,'typecode'): raise EvaluateException, ' element, instance missing typecode attribute' pyobjs.append(v) self.header_pyobjs = tuple(pyobjs) def setResponseFromWSAddress(self, address, localURL): '''Server-side has to set these fields in response. address -- Address instance, representing a WS-Address ''' self.From = localURL self.header_pyobjs = None pyobjs = [] namespaceURI = self.wsAddressURI for nsuri,name,value in (\ (namespaceURI, "Action", self._action), (namespaceURI, "MessageID","uuid:%s" %time.time()), (namespaceURI, "RelatesTo", address.getMessageID()), (namespaceURI, "To", self.anonymousURI),): typecode = GED(nsuri, name) pyobjs.append(typecode.pyclass(value)) typecode = GED(nsuri, "From") pyobj = typecode.pyclass() pyobj._Address = self.From pyobjs.append(pyobj) self.header_pyobjs = tuple(pyobjs) def serialize(self, sw, **kw): ''' sw -- SoapWriter instance, add WS-Address header. ''' for pyobj in self.header_pyobjs: if hasattr(pyobj, 'typecode') is False: raise RuntimeError, 'all header pyobjs must have a typecode attribute' sw.serialize_header(pyobj, **kw) def parse(self, ps, **kw): ''' ps -- ParsedSoap instance ''' namespaceURI = self.wsAddressURI elements = ("MessageID","Action","To","From","RelatesTo") d = {namespaceURI:elements} typecodes = self._getWSAddressTypeCodes(**d) pyobjs = ps.ParseHeaderElements(typecodes) self._messageID = pyobjs[(namespaceURI,elements[0])] self._action = pyobjs[(namespaceURI,elements[1])] self._addressTo = pyobjs[(namespaceURI,elements[2])] self._from = pyobjs[(namespaceURI,elements[3])] self._relatesTo = pyobjs[(namespaceURI,elements[4])] if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/LBNLCopyright0000644000175100017510000000452407730117055013540 0ustar zsizsiCopyright (c) 2003, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such Enhancements or derivative works thereof, in binary and source code form. ZSI-2.1-a1/ZSI/generate/0000755000175100017510000000000010712455110012751 5ustar zsizsiZSI-2.1-a1/ZSI/generate/containers.py0000644000175100017510000033265510712156244015514 0ustar zsizsi############################################################################ # Monte M. Goode, LBNL # See LBNLCopyright for copyright notice! ########################################################################### # contains text container classes for new generation generator # $Id: containers.py 1420 2007-10-31 19:51:00Z boverhof $ import types, warnings from utility import StringWriter, TextProtect, TextProtectAttributeName,\ GetPartsSubNames from utility import NamespaceAliasDict as NAD, NCName_to_ClassName as NC_to_CN import ZSI from ZSI.TC import _is_xsd_or_soap_ns from ZSI.wstools import XMLSchema, WSDLTools from ZSI.wstools.Namespaces import SCHEMA, SOAP, WSDL from ZSI.wstools.logging import getLogger as _GetLogger from ZSI.typeinterpreter import BaseTypeInterpreter from ZSI.generate import WSISpec, WSInteropError, Wsdl2PythonError,\ WsdlGeneratorError, WSDLFormatError ID1 = ' ' ID2 = 2*ID1 ID3 = 3*ID1 ID4 = 4*ID1 ID5 = 5*ID1 ID6 = 6*ID1 KW = {'ID1':ID1, 'ID2':ID2, 'ID3':ID3,'ID4':ID4, 'ID5':ID5, 'ID6':ID6,} DEC = '_Dec' DEF = '_Def' """ type_class_name -- function to return the name formatted as a type class. element_class_name -- function to return the name formatted as an element class. """ type_class_name = lambda n: '%s%s' %(NC_to_CN(n), DEF) element_class_name = lambda n: '%s%s' %(NC_to_CN(n), DEC) def IsRPC(item): """item -- OperationBinding instance. """ if not isinstance(item, WSDLTools.OperationBinding): raise TypeError, 'IsRPC takes 1 argument of type WSDLTools.OperationBinding' soapbinding = item.getBinding().findBinding(WSDLTools.SoapBinding) sob = item.findBinding(WSDLTools.SoapOperationBinding) style = soapbinding.style if sob is not None: style = sob.style or soapbinding.style return style == 'rpc' def IsLiteral(item): """item -- MessageRoleBinding instance. """ if not isinstance(item, WSDLTools.MessageRoleBinding): raise TypeError, 'IsLiteral takes 1 argument of type WSDLTools.MessageRoleBinding' sbb = None if item.type == 'input' or item.type == 'output': sbb = item.findBinding(WSDLTools.SoapBodyBinding) if sbb is None: raise ValueError, 'Missing soap:body binding.' return sbb.use == 'literal' def SetTypeNameFunc(func): global type_class_name type_class_name = func def SetElementNameFunc(func): global element_class_name element_class_name = func def GetClassNameFromSchemaItem(item,do_extended=False): ''' ''' assert isinstance(item, XMLSchema.XMLSchemaComponent), 'must be a schema item.' alias = NAD.getAlias(item.getTargetNamespace()) if item.isDefinition() is True: return '%s.%s' %(alias, NC_to_CN('%s' %type_class_name(item.getAttributeName()))) return None def FromMessageGetSimpleElementDeclaration(message): '''If message consists of one part with an element attribute, and this element is a simpleType return a string representing the python type, else return None. ''' assert isinstance(message, WSDLTools.Message), 'expecting WSDLTools.Message' if len(message.parts) == 1 and message.parts[0].element is not None: part = message.parts[0] nsuri,name = part.element wsdl = message.getWSDL() types = wsdl.types if types.has_key(nsuri) and types[nsuri].elements.has_key(name): e = types[nsuri].elements[name] if isinstance(e, XMLSchema.ElementDeclaration) is True and e.getAttribute('type'): typ = e.getAttribute('type') bt = BaseTypeInterpreter() ptype = bt.get_pythontype(typ[1], typ[0]) return ptype return None class AttributeMixIn: '''for containers that can declare attributes. Class Attributes: attribute_typecode -- typecode attribute name typecode dict built_in_refs -- attribute references that point to built-in types. Skip resolving them into attribute declarations. ''' attribute_typecode = 'self.attribute_typecode_dict' built_in_refs = [(SOAP.ENC, 'arrayType'),] def _setAttributes(self, attributes): '''parameters attributes -- a flat list of all attributes, from this list all items in attribute_typecode_dict will be generated into attrComponents. returns a list of strings representing the attribute_typecode_dict. ''' atd = self.attribute_typecode atd_list = formatted_attribute_list = [] if not attributes: return formatted_attribute_list atd_list.append('# attribute handling code') idx = 0 while(idx < len(attributes)): a = attributes[idx] idx += 1 if a.isWildCard() and a.isDeclaration(): atd_list.append(\ '%s[("%s","anyAttribute")] = ZSI.TC.AnyElement()'\ % (atd, SCHEMA.XSD3) ) elif a.isDeclaration(): tdef = a.getTypeDefinition('type') if tdef is not None: tc = '%s.%s(None)' %(NAD.getAlias(tdef.getTargetNamespace()), self.mangle(type_class_name(tdef.getAttributeName())) ) else: # built-in t = a.getAttribute('type') try: tc = BTI.get_typeclass(t[1], t[0]) except: # hand back a string by default. tc = ZSI.TC.String if tc is not None: tc = '%s()' %tc key = None if a.getAttribute('form') == 'qualified': key = '("%s","%s")' % ( a.getTargetNamespace(), a.getAttribute('name') ) elif a.getAttribute('form') == 'unqualified': key = '"%s"' % a.getAttribute('name') else: raise ContainerError, \ 'attribute form must be un/qualified %s' \ % a.getAttribute('form') atd_list.append(\ '%s[%s] = %s' % (atd, key, tc) ) elif a.isReference() and a.isAttributeGroup(): # flatten 'em out.... for ga in a.getAttributeGroup().getAttributeContent(): attributes += (ga,) elif a.isReference(): try: ga = a.getAttributeDeclaration() except XMLSchema.SchemaError: key = a.getAttribute('ref') self.logger.debug('No schema item for attribute ref (%s, %s)' %key) if key in self.built_in_refs: continue raise tp = None if ga is not None: tp = ga.getTypeDefinition('type') key = '("%s","%s")' %(ga.getTargetNamespace(), ga.getAttribute('name')) if ga is None: # TODO: probably SOAPENC:arrayType key = '("%s","%s")' %( a.getAttribute('ref').getTargetNamespace(), a.getAttribute('ref').getName()) atd_list.append(\ '%s[%s] = ZSI.TC.String()' %(atd, key) ) elif tp is None: # built in simple type try: namespace,typeName = ga.getAttribute('type') except TypeError, ex: # TODO: attribute declaration could be anonymous type # hack in something to work atd_list.append(\ '%s[%s] = ZSI.TC.String()' %(atd, key) ) else: atd_list.append(\ '%s[%s] = %s()' %(atd, key, BTI.get_typeclass(typeName, namespace)) ) else: typeName = tp.getAttribute('name') namespace = tp.getTargetNamespace() alias = NAD.getAlias(namespace) key = '("%s","%s")' \ % (ga.getTargetNamespace(),ga.getAttribute('name')) atd_list.append(\ '%s[%s] = %s.%s(None)' \ % (atd, key, alias, type_class_name(typeName)) ) else: raise TypeError, 'expecting an attribute: %s' %a.getItemTrace() return formatted_attribute_list class ContainerError(Exception): pass class ContainerBase: '''Base class for all Containers. func_aname -- function that takes name, and returns aname. ''' func_aname = staticmethod(TextProtectAttributeName) logger = _GetLogger("ContainerBase") def __init__(self): self.content = StringWriter('\n') self.__setup = False self.ns = None def __str__(self): return self.getvalue() # - string content methods def mangle(self, s): '''class/variable name illegalities ''' return TextProtect(s) def write(self, s): self.content.write(s) def writeArray(self, a): self.content.write('\n'.join(a)) def _setContent(self): '''override in subclasses. formats the content in the desired way. ''' raise NotImplementedError, 'abstract method not implemented' def getvalue(self): if not self.__setup: self._setContent() self.__setup = True return self.content.getvalue() # - namespace utility methods def getNSAlias(self): if self.ns is not None: return NAD.getAlias(self.ns) raise ContainerError, 'no self.ns attr defined in %s' % self.__class__ def getNSModuleName(self): if self.ns: return NAD.getModuleName(self.ns) raise ContainerError, 'no self.ns attr defined in %s' % self.__class__ def getAttributeName(self, name): '''represents the aname ''' if self.func_aname is None: return name assert callable(self.func_aname), \ 'expecting callable method for attribute func_aname, not %s' %type(self.func_aname) f = self.func_aname return f(name) # -- containers for services file components class ServiceContainerBase(ContainerBase): clientClassSuffix = "SOAP" logger = _GetLogger("ServiceContainerBase") class ServiceHeaderContainer(ServiceContainerBase): imports = ['\nimport urlparse, types', 'from ZSI.TCcompound import ComplexType, Struct', 'from ZSI import client', 'from ZSI.schema import GED, GTD', 'import ZSI' ] logger = _GetLogger("ServiceHeaderContainer") def __init__(self, do_extended=False): ServiceContainerBase.__init__(self) self.basic = self.imports[:] self.types = None self.messages = None self.extras = [] self.do_extended = do_extended def setTypesModuleName(self, module): self.types = module def setMessagesModuleName(self, module): self.messages = module def appendImport(self, statement): '''append additional import statement(s). import_stament -- tuple or list or str ''' if type(statement) in (list,tuple): self.extras += statement else: self.extras.append(statement) def _setContent(self): if self.messages: self.write('from %s import *' % self.messages) if self.types: self.write('from %s import *' % self.types) imports = self.basic[:] imports += self.extras self.writeArray(imports) class ServiceLocatorContainer(ServiceContainerBase): logger = _GetLogger("ServiceLocatorContainer") def __init__(self): ServiceContainerBase.__init__(self) self.serviceName = None self.portInfo = [] self.locatorName = None self.portMethods = [] def setUp(self, service): assert isinstance(service, WSDLTools.Service), \ 'expecting WDSLTools.Service instance.' self.serviceName = service.name for p in service.ports: try: ab = p.getAddressBinding() except WSDLTools.WSDLError, ex: self.logger.warning('Skip port(%s), missing address binding' %p.name) continue if isinstance(ab, WSDLTools.SoapAddressBinding) is False: self.logger.warning('Skip port(%s), not a SOAP-1.1 address binding' %p.name) continue #info = (p.getBinding().getPortType().name, p.getBinding().name, ab.location) self.portInfo.append( (NC_to_CN(p.name), NC_to_CN(p.getBinding().name), ab.location) ) def getLocatorName(self): '''return class name of generated locator. ''' return self.locatorName def getPortMethods(self): '''list of get port accessor methods of generated locator class. ''' return self.portMethods def _setContent(self): if not self.serviceName: raise ContainerError, 'no service name defined!' self.serviceName = self.mangle(self.serviceName) self.locatorName = '%sLocator' %self.serviceName locator = ['# Locator', 'class %s:' %self.locatorName, ] self.portMethods = [] kwargs = KW.copy() for port,bind,addr in self.portInfo: # access method each port method = 'get%s' %port kwargs.update(dict(port=port, bind=bind, addr=addr, service=self.serviceName, suffix=self.clientClassSuffix, method=method)) locator += [ '%(ID1)s%(port)s_address = "%(addr)s"' %kwargs, '%(ID1)sdef get%(port)sAddress(self):' %kwargs, '%(ID2)sreturn %(service)sLocator.%(port)s_address' %kwargs, '%(ID1)sdef %(method)s(self, url=None, **kw):' %kwargs, '%(ID2)sreturn %(bind)s%(suffix)s(url or %(service)sLocator.%(port)s_address, **kw)' %kwargs, ] self.portMethods.append(method) self.writeArray(locator) class ServiceOperationContainer(ServiceContainerBase): logger = _GetLogger("ServiceOperationContainer") def __init__(self, useWSA=False, do_extended=False): '''Parameters: useWSA -- boolean, enable ws-addressing do_extended -- boolean ''' ServiceContainerBase.__init__(self) self.useWSA = useWSA self.do_extended = do_extended def hasInput(self): return self.inputName is not None def hasOutput(self): return self.outputName is not None def isRPC(self): return IsRPC(self.binding_operation) def isLiteral(self, input=True): msgrole = self.binding_operation.input if input is False: msgrole = self.binding_operation.output return IsLiteral(msgrole) def isSimpleType(self, input=True): if input is False: return self.outputSimpleType return self.inputSimpleType def getOperation(self): return self.port.operations.get(self.name) def getBOperation(self): return self.port.get(self.name) def getOperationName(self): return self.name def setUp(self, item): ''' Parameters: item -- WSDLTools BindingOperation instance. ''' if not isinstance(item, WSDLTools.OperationBinding): raise TypeError, 'Expecting WSDLTools Operation instance' if not item.input: raise WSDLFormatError('No in ' %( item.getBinding().name, item.name)) self.name = None self.port = None self.soapaction = None self.inputName = None self.outputName = None self.inputSimpleType = None self.outputSimpleType = None self.inputAction = None self.outputAction = None self.port = port = item.getBinding().getPortType() self._wsdl = item.getWSDL() self.name = name = item.name self.binding_operation = bop = item self.soap_input_headers = None self.soap_output_headers = None op = port.operations.get(name) if op is None: raise WSDLFormatError( ' no match for ' %( port.name, item.getBinding().name, item.name)) soap_bop = bop.findBinding(WSDLTools.SoapOperationBinding) if soap_bop is None: raise SOAPBindingError, 'expecting SOAP Bindings' self.soapaction = soap_bop.soapAction sbody = bop.input.findBinding(WSDLTools.SoapBodyBinding) if not sbody: raise SOAPBindingError('Missing ' %( port.binding.name, bop.name)) self.encodingStyle = None if sbody.use == 'encoded': assert sbody.encodingStyle == SOAP.ENC,\ 'Supporting encodingStyle=%s, not %s'%(SOAP.ENC, sbody.encodingStyle) self.encodingStyle = sbody.encodingStyle self.inputName = op.getInputMessage().name self.inputSimpleType = \ FromMessageGetSimpleElementDeclaration(op.getInputMessage()) self.inputAction = op.getInputAction() self.soap_input_headers = bop.input.findBindings(WSDLTools.SoapHeaderBinding) if bop.output is not None: sbody = bop.output.findBinding(WSDLTools.SoapBodyBinding) if not item.output: raise WSDLFormatError, "Operation %s, no match for output binding" %name self.outputName = op.getOutputMessage().name self.outputSimpleType = \ FromMessageGetSimpleElementDeclaration(op.getOutputMessage()) self.outputAction = op.getOutputAction() self.soap_output_headers = bop.output.findBindings(WSDLTools.SoapHeaderBinding) def _setContent(self): '''create string representation of operation. ''' kwstring = 'kw = {}' tCheck = 'if isinstance(request, %s) is False:' % self.inputName bindArgs = '' if self.encodingStyle is not None: bindArgs = 'encodingStyle="%s", ' %self.encodingStyle if self.useWSA: wsactionIn = 'wsaction = "%s"' % self.inputAction wsactionOut = 'wsaction = "%s"' % self.outputAction bindArgs += 'wsaction=wsaction, endPointReference=self.endPointReference, ' responseArgs = ', wsaction=wsaction' else: wsactionIn = '# no input wsaction' wsactionOut = '# no output wsaction' responseArgs = '' bindArgs += '**kw)' if self.do_extended: inputName = self.getOperation().getInputMessage().name wrap_str = "" partsList = self.getOperation().getInputMessage().parts.values() try: subNames = GetPartsSubNames(partsList, self._wsdl) except TypeError, ex: raise Wsdl2PythonError,\ "Extended generation failure: only supports doc/lit, "\ +"and all element attributes () must refer to single global "\ +"element declaration with complexType content. "\ +"\n\n**** TRY WITHOUT EXTENDED ****\n" args = [] for pa in subNames: args += pa for arg in args: wrap_str += "%srequest.%s = %s\n" % (ID2, self.getAttributeName(arg), self.mangle(arg)) #args = [pa.name for pa in self.getOperation().getInputMessage().parts.values()] argsStr = ",".join(args) if len(argsStr) > 1: # add inital comma if args exist argsStr = ", " + argsStr method = [ '%s# op: %s' % (ID1, self.getOperation().getInputMessage()), '%sdef %s(self%s):' % (ID1, self.name, argsStr), '\n%srequest = %s()' % (ID2, self.inputName), '%s' % (wrap_str), '%s%s' % (ID2, kwstring), '%s%s' % (ID2, wsactionIn), '%sself.binding.Send(None, None, request, soapaction="%s", %s'\ %(ID2, self.soapaction, bindArgs), ] elif self.soap_input_headers: method = [ '%s# op: %s' % (ID1, self.name), '%sdef %s(self, request, soapheaders=(), **kw):' % (ID1, self.name), '%s%s' % (ID2, tCheck), '%sraise TypeError, "%%s incorrect request type" %% (%s)' %(ID3, 'request.__class__'), '%s%s' % (ID2, wsactionIn), '%s# TODO: Check soapheaders' % (ID2), '%sself.binding.Send(None, None, request, soapaction="%s", soapheaders=soapheaders, %s'\ %(ID2, self.soapaction, bindArgs), ] else: method = [ '%s# op: %s' % (ID1, self.name), '%sdef %s(self, request, **kw):' % (ID1, self.name), '%s%s' % (ID2, tCheck), '%sraise TypeError, "%%s incorrect request type" %% (%s)' %(ID3, 'request.__class__'), '%s%s' % (ID2, wsactionIn), '%sself.binding.Send(None, None, request, soapaction="%s", %s'\ %(ID2, self.soapaction, bindArgs), ] # # BP 1.0: rpc/literal # WSDL 1.1 Section 3.5 could be interpreted to mean the RPC response # wrapper element must be named identical to the name of the # wsdl:operation. # R2729 # # SOAP-1.1 Note: rpc/encoded # Each parameter accessor has a name corresponding to the name of the # parameter and type corresponding to the type of the parameter. The name of # the return value accessor is not significant. Likewise, the name of the struct is # not significant. However, a convention is to name it after the method name # with the string "Response" appended. # if not self.outputName: method.append('%s#check for soap, assume soap:fault' %(ID2,)) method.append('%sif self.binding.IsSOAP(): self.binding.Receive(None, **kw)' % (ID2,)) self.writeArray(method) return response = ['%s%s' % (ID2, wsactionOut),] if self.isRPC() and not self.isLiteral(): # rpc/encoded Replace wrapper name with None response.append(\ '%stypecode = Struct(pname=None, ofwhat=%s.typecode.ofwhat, pyclass=%s.typecode.pyclass)' %( ID2, self.outputName, self.outputName) ) response.append(\ '%sresponse = self.binding.Receive(typecode%s)' %( ID2, responseArgs) ) else: response.append(\ '%sresponse = self.binding.Receive(%s.typecode%s)' %( ID2, self.outputName, responseArgs) ) # only support lit if self.soap_output_headers: sh = '[' for shb in self.soap_output_headers: #shb.encodingStyle, shb.use, shb.namespace shb.message shb.part try: msg = self._wsdl.messages[shb.message] part = msg.parts[shb.part] if part.element is not None: sh += 'GED%s,' %str(part.element) else: warnings.warn('skipping soap output header in Message "%s"' %str(msg)) except: raise WSDLFormatError( 'failure processing output header typecodes, ' + 'could not find message "%s" or its part "%s"' %( shb.message, shb.part) ) sh += ']' if len(sh) > 2: response.append(\ '%sself.soapheaders = self.binding.ps.ParseHeaderElements(%s)' %(ID2, sh) ) if self.outputSimpleType: response.append('%sreturn %s(response)' %(ID2, self.outputName)) else: if self.do_extended: partsList = self.getOperation().getOutputMessage().parts.values() subNames = GetPartsSubNames(partsList, self._wsdl) args = [] for pa in subNames: args += pa for arg in args: response.append('%s%s = response.%s' % (ID2, self.mangle(arg), self.getAttributeName(arg)) ) margs = ",".join(args) response.append("%sreturn %s" % (ID2, margs) ) else: response.append('%sreturn response' %ID2) method += response self.writeArray(method) class BindingDescription(ServiceContainerBase): '''writes out SOAP Binding class class variables: readerclass -- writerclass -- operationclass -- representation of each operation. ''' readerclass = None writerclass = None operationclass = ServiceOperationContainer logger = _GetLogger("BindingDescription") def __init__(self, useWSA=False, do_extended=False, wsdl=None): '''Parameters: name -- binding name property -- resource properties useWSA -- boolean, enable ws-addressing name -- binding name ''' ServiceContainerBase.__init__(self) self.useWSA = useWSA self.rProp = None #self.bName = None self.operations = None self.do_extended = do_extended self._wsdl = wsdl # None unless do_extended == True def setReaderClass(cls, className): '''specify a reader class name, this must be imported in service module. ''' cls.readerclass = className setReaderClass = classmethod(setReaderClass) def setWriterClass(cls, className): '''specify a writer class name, this must be imported in service module. ''' cls.writerclass = className setWriterClass = classmethod(setWriterClass) def setOperationClass(cls, className): '''specify an operation container class name. ''' cls.operationclass = className setOperationClass = classmethod(setOperationClass) def setUp(self, item): '''This method finds all SOAP Binding Operations, it will skip all bindings that are not SOAP. item -- WSDL.Binding instance ''' assert isinstance(item, WSDLTools.Binding), \ 'expecting WSDLTools Binding instance' portType = item.getPortType() self._kwargs = KW.copy() self._kwargs['bind'] = NC_to_CN(item.name) self.operations = [] self.rProp = portType.getResourceProperties() soap_binding = item.findBinding(WSDLTools.SoapBinding) if soap_binding is None: raise Wsdl2PythonError,\ 'Binding(%s) missing WSDLTools.SoapBinding' %item.name for bop in item.operations: soap_bop = bop.findBinding(WSDLTools.SoapOperationBinding) if soap_bop is None: self.logger.warning(\ 'Skip Binding(%s) operation(%s) no SOAP Binding Operation'\ %(item.name, bop.name), ) continue #soapAction = soap_bop.soapAction if bop.input is not None: soapBodyBind = bop.input.findBinding(WSDLTools.SoapBodyBinding) if soapBodyBind is None: self.logger.warning(\ 'Skip Binding(%s) operation(%s) Bindings(%s) not supported'\ %(item.name, bop.name, bop.extensions) ) continue op = portType.operations.get(bop.name) if op is None: raise Wsdl2PythonError,\ 'no matching portType/Binding operation(%s)' % bop.name c = self.operationclass(useWSA=self.useWSA, do_extended=self.do_extended) c.setUp(bop) self.operations.append(c) def _setContent(self): if self.useWSA is True: args = 'endPointReference=None, **kw' epr = 'self.endPointReference = endPointReference' else: args = '**kw' epr = '# no ws-addressing' if self.rProp: rp = 'kw.setdefault("ResourceProperties", ("%s","%s"))'\ %(self.rProp[0], self.rProp[1]) else: rp = '# no resource properties' kwargs = self._kwargs kwargs.update(dict(suffix=self.clientClassSuffix, args=args, epr=epr, rp=rp, readerclass=self.readerclass, writerclass=self.writerclass,)) methods = [ '# Methods', 'class %(bind)s%(suffix)s:' %kwargs, '%(ID1)sdef __init__(self, url, %(args)s):' %kwargs, '%(ID2)skw.setdefault("readerclass", %(readerclass)s)' %kwargs, '%(ID2)skw.setdefault("writerclass", %(writerclass)s)' %kwargs, '%(ID2)s%(rp)s' % kwargs, '%(ID2)sself.binding = client.Binding(url=url, **kw)' %kwargs, '%(ID2)s%(epr)s' % kwargs, ] for op in self.operations: methods += [ op.getvalue() ] self.writeArray(methods) ServiceOperationsClassContainer = BindingDescription class MessageContainerInterface: logger = _GetLogger("MessageContainerInterface") def setUp(self, port, soc, input): '''sets the attribute _simple which represents a primitive type message represents, or None if not primitive. soc -- WSDLTools.ServiceOperationContainer instance port -- WSDLTools.Port instance input-- boolean, input messasge or output message of operation. ''' raise NotImplementedError, 'Message container must implemented setUp.' class ServiceDocumentLiteralMessageContainer(ServiceContainerBase, MessageContainerInterface): logger = _GetLogger("ServiceDocumentLiteralMessageContainer") def __init__(self, do_extended=False): ServiceContainerBase.__init__(self) self.do_extended=do_extended def setUp(self, port, soc, input): content = self.content # TODO: check soapbody for part name simple = self._simple = soc.isSimpleType(soc.getOperationName()) name = soc.getOperationName() # Document/literal operation = port.getBinding().getPortType().operations.get(name) bop = port.getBinding().operations.get(name) soapBodyBind = None if input is True: soapBodyBind = bop.input.findBinding(WSDLTools.SoapBodyBinding) message = operation.getInputMessage() else: soapBodyBind = bop.output.findBinding(WSDLTools.SoapBodyBinding) message = operation.getOutputMessage() # using underlying data structure to avoid phantom problem. # with message.parts.data.values() if len(message.parts) == 0: raise Wsdl2PythonError, 'must specify part for doc/lit msg' p = None if soapBodyBind.parts is not None: if len(soapBodyBind.parts) > 1: raise Wsdl2PythonError,\ 'not supporting multiple parts in soap body' if len(soapBodyBind.parts) == 0: return p = message.parts.get(soapBodyBind.parts[0]) # XXX: Allow for some slop p = p or message.parts[0] if p.type: raise Wsdl2PythonError, 'no doc/lit suport for ' if not p.element: return self.ns = p.element[0] content.ns = p.element[0] content.pName = p.element[1] content.mName = message.name def _setContent(self): '''create string representation of doc/lit message container. If message element is simple(primitive), use python type as base class. ''' try: simple = self._simple except AttributeError: raise RuntimeError, 'call setUp first' # TODO: Hidden contract. Must set self.ns before getNSAlias... # File "/usr/local/python/lib/python2.4/site-packages/ZSI/generate/containers.py", line 625, in _setContent # kw['message'],kw['prefix'],kw['typecode'] = \ # File "/usr/local/python/lib/python2.4/site-packages/ZSI/generate/containers.py", line 128, in getNSAlias # raise ContainerError, 'no self.ns attr defined in %s' % self.__class__ # ZSI.generate.containers.ContainerError: no self.ns attr defined in ZSI.generate.containers.ServiceDocumentLiteralMessageContainer # # self.ns = self.content.ns kw = KW.copy() kw.update(dict(message=self.content.mName, nsuri=self.content.ns, name=self.content.pName)) # kw['message'],kw['prefix'],kw['typecode'] = \ # self.content.mName, self.getNSAlias(), element_class_name(self.content.pName) # # These messsages are just global element declarations # self.writeArray(['%(message)s = %(prefix)s.%(typecode)s().pyclass' %kw]) self.writeArray(['%(message)s = GED("%(nsuri)s", "%(name)s").pyclass' %kw]) class ServiceRPCEncodedMessageContainer(ServiceContainerBase, MessageContainerInterface): logger = _GetLogger("ServiceRPCEncodedMessageContainer") def setUp(self, port, soc, input): ''' Instance Data: op -- WSDLTools Operation instance bop -- WSDLTools BindingOperation instance input -- boolean input/output ''' name = soc.getOperationName() bop = port.getBinding().operations.get(name) op = port.getBinding().getPortType().operations.get(name) assert op is not None, 'port has no operation %s' %name assert bop is not None, 'port has no binding operation %s' %name self.input = input self.op = op self.bop = bop def _setContent(self): try: self.op except AttributeError: raise RuntimeError, 'call setUp first' pname = self.op.name msgRole = self.op.input msgRoleB = self.bop.input if self.input is False: pname = '%sResponse' %self.op.name msgRole = self.op.output msgRoleB = self.bop.output sbody = msgRoleB.findBinding(WSDLTools.SoapBodyBinding) if not sbody or not sbody.namespace: raise WSInteropError, WSISpec.R2717 assert sbody.use == 'encoded', 'Expecting use=="encoded"' encodingStyle = sbody.encodingStyle assert encodingStyle == SOAP.ENC,\ 'Supporting encodingStyle=%s, not %s' %(SOAP.ENC, encodingStyle) namespace = sbody.namespace tcb = MessageTypecodeContainer(\ tuple(msgRole.getMessage().parts.list), ) ofwhat = '[%s]' %tcb.getTypecodeList() pyclass = msgRole.getMessage().name fdict = KW.copy() fdict['nspname'] = sbody.namespace fdict['pname'] = pname fdict['pyclass'] = None fdict['ofwhat'] = ofwhat fdict['encoded'] = namespace #if self.input is False: # fdict['typecode'] = \ # 'Struct(pname=None, ofwhat=%(ofwhat)s, pyclass=%(pyclass)s, encoded="%(encoded)s")' #else: fdict['typecode'] = \ 'Struct(pname=("%(nspname)s","%(pname)s"), ofwhat=%(ofwhat)s, pyclass=%(pyclass)s, encoded="%(encoded)s")' message = ['class %(pyclass)s:', '%(ID1)sdef __init__(self, **kw):', '%(ID2)s"""Keyword parameters:', ] idx = len(message) for a,p in zip(tcb.getAttributeNames(), tcb.getParameterNames()): message.insert(idx, '%(ID2)s' + p + ' -- part ' + p) message.append('%(ID2)sself.' + a + ' = kw.get("%s")' %p) idx += 1 message.insert(idx, '%(ID2)s"""') # TODO: This isn't a TypecodeContainerBase instance but it # certaintly generates a pyclass and typecode. #if self.metaclass is None: if TypecodeContainerBase.metaclass is None: fdict['pyclass'] = pyclass fdict['typecode'] = fdict['typecode'] %fdict message.append('%(pyclass)s.typecode = %(typecode)s') else: # Need typecode to be available when class is constructed. fdict['typecode'] = fdict['typecode'] %fdict fdict['pyclass'] = pyclass fdict['metaclass'] = TypecodeContainerBase.metaclass message.insert(0, '_%(pyclass)sTypecode = %(typecode)s') message.insert(2, '%(ID1)stypecode = _%(pyclass)sTypecode') message.insert(3, '%(ID1)s__metaclass__ = %(metaclass)s') message.append('%(pyclass)s.typecode.pyclass = %(pyclass)s') self.writeArray(map(lambda l: l %fdict, message)) class ServiceRPCLiteralMessageContainer(ServiceContainerBase, MessageContainerInterface): logger = _GetLogger("ServiceRPCLiteralMessageContainer") def setUp(self, port, soc, input): ''' Instance Data: op -- WSDLTools Operation instance bop -- WSDLTools BindingOperation instance input -- boolean input/output ''' name = soc.getOperationName() bop = port.getBinding().operations.get(name) op = port.getBinding().getPortType().operations.get(name) assert op is not None, 'port has no operation %s' %name assert bop is not None, 'port has no binding operation %s' %name self.op = op self.bop = bop self.input = input def _setContent(self): try: self.op except AttributeError: raise RuntimeError, 'call setUp first' operation = self.op input = self.input pname = operation.name msgRole = operation.input msgRoleB = self.bop.input if input is False: pname = '%sResponse' %operation.name msgRole = operation.output msgRoleB = self.bop.output sbody = msgRoleB.findBinding(WSDLTools.SoapBodyBinding) if not sbody or not sbody.namespace: raise WSInteropError, WSISpec.R2717 namespace = sbody.namespace tcb = MessageTypecodeContainer(\ tuple(msgRole.getMessage().parts.list), ) ofwhat = '[%s]' %tcb.getTypecodeList() pyclass = msgRole.getMessage().name fdict = KW.copy() fdict['nspname'] = sbody.namespace fdict['pname'] = pname fdict['pyclass'] = None fdict['ofwhat'] = ofwhat fdict['encoded'] = namespace fdict['typecode'] = \ 'Struct(pname=("%(nspname)s","%(pname)s"), ofwhat=%(ofwhat)s, pyclass=%(pyclass)s, encoded="%(encoded)s")' message = ['class %(pyclass)s:', '%(ID1)sdef __init__(self, **kw):', '%(ID2)s"""Keyword parameters:', ] idx = len(message) for a,p in zip(tcb.getAttributeNames(), tcb.getParameterNames()): message.insert(idx, '%(ID2)s' + p + ' -- part ' + p) message.append('%(ID2)sself.' + a + ' = kw.get("%s")' %p) idx += 1 message.insert(idx, '%(ID2)s"""') # TODO: This isn't a TypecodeContainerBase instance but it # certaintly generates a pyclass and typecode. #if self.metaclass is None: if TypecodeContainerBase.metaclass is None: fdict['pyclass'] = pyclass fdict['typecode'] = fdict['typecode'] %fdict message.append('%(pyclass)s.typecode = %(typecode)s') else: # Need typecode to be available when class is constructed. fdict['typecode'] = fdict['typecode'] %fdict fdict['pyclass'] = pyclass fdict['metaclass'] = TypecodeContainerBase.metaclass message.insert(0, '_%(pyclass)sTypecode = %(typecode)s') message.insert(2, '%(ID1)stypecode = _%(pyclass)sTypecode') message.insert(3, '%(ID1)s__metaclass__ = %(metaclass)s') message.append('%(pyclass)s.typecode.pyclass = %(pyclass)s') self.writeArray(map(lambda l: l %fdict, message)) TypesContainerBase = ContainerBase class TypesHeaderContainer(TypesContainerBase): '''imports for all generated types modules. ''' imports = [ 'import ZSI', 'import ZSI.TCcompound', 'from ZSI.schema import LocalElementDeclaration, ElementDeclaration, TypeDefinition, GTD, GED', ] logger = _GetLogger("TypesHeaderContainer") def _setContent(self): self.writeArray(TypesHeaderContainer.imports) NamespaceClassContainerBase = TypesContainerBase class NamespaceClassHeaderContainer(NamespaceClassContainerBase): logger = _GetLogger("NamespaceClassHeaderContainer") def _setContent(self): head = [ '#' * 30, '# targetNamespace', '# %s' % self.ns, '#' * 30 + '\n', 'class %s:' % self.getNSAlias(), '%stargetNamespace = "%s"' % (ID1, self.ns) ] self.writeArray(head) class NamespaceClassFooterContainer(NamespaceClassContainerBase): logger = _GetLogger("NamespaceClassFooterContainer") def _setContent(self): foot = [ '# end class %s (tns: %s)' % (self.getNSAlias(), self.ns), ] self.writeArray(foot) BTI = BaseTypeInterpreter() class TypecodeContainerBase(TypesContainerBase): '''Base class for all classes representing anything with element content. class variables: mixed_content_aname -- text content will be placed in this attribute. attributes_aname -- attributes will be placed in this attribute. metaclass -- set this attribute to specify a pyclass __metaclass__ ''' mixed_content_aname = 'text' attributes_aname = 'attrs' metaclass = None lazy = False logger = _GetLogger("TypecodeContainerBase") def __init__(self, do_extended=False, extPyClasses=None): TypesContainerBase.__init__(self) self.name = None # attrs for model groups and others with elements, tclists, etc... self.allOptional = False self.mgContent = None self.contentFlattened = False self.elementAttrs = [] self.tcListElements = [] self.tcListSet = False self.localTypes = [] # used when processing nested anonymous types self.parentClass = None # used when processing attribute content self.mixed = False self.extraFlags = '' self.attrComponents = None # --> EXTENDED # Used if an external pyclass was specified for this type. self.do_extended = do_extended if extPyClasses is None: self.extPyClasses = {} else: self.extPyClasses = extPyClasses # <-- def getvalue(self): out = ContainerBase.getvalue(self) for item in self.localTypes: content = None assert True is item.isElement() is item.isLocal(), 'expecting local elements only' etp = item.content qName = item.getAttribute('type') if not qName: etp = item.content local = True else: etp = item.getTypeDefinition('type') if etp is None: if local is True: content = ElementLocalComplexTypeContainer(do_extended=self.do_extended) else: content = ElementSimpleTypeContainer() elif etp.isLocal() is False: content = ElementGlobalDefContainer() elif etp.isSimple() is True: content = ElementLocalSimpleTypeContainer() elif etp.isComplex(): content = ElementLocalComplexTypeContainer(do_extended=self.do_extended) else: raise Wsdl2PythonError, "Unknown element declaration: %s" %item.getItemTrace() content.setUp(item) out += '\n\n' if self.parentClass: content.parentClass = \ '%s.%s' %(self.parentClass, self.getClassName()) else: content.parentClass = '%s.%s' %(self.getNSAlias(), self.getClassName()) for l in content.getvalue().split('\n'): if l: out += '%s%s\n' % (ID1, l) else: out += '\n' out += '\n\n' return out def getAttributeName(self, name): '''represents the aname ''' if self.func_aname is None: return name assert callable(self.func_aname), \ 'expecting callable method for attribute func_aname, not %s' %type(self.func_aname) f = self.func_aname return f(name) def getMixedTextAName(self): '''returns an aname representing mixed text content. ''' return self.getAttributeName(self.mixed_content_aname) def getClassName(self): if not self.name: raise ContainerError, 'self.name not defined!' if not hasattr(self.__class__, 'type'): raise ContainerError, 'container type not defined!' #suffix = self.__class__.type if self.__class__.type == DEF: classname = type_class_name(self.name) elif self.__class__.type == DEC: classname = element_class_name(self.name) return self.mangle( classname ) # --> EXTENDED def hasExtPyClass(self): if self.name in self.extPyClasses: return True else: return False # <-- def getPyClass(self): '''Name of generated inner class that will be specified as pyclass. ''' # --> EXTENDED if self.hasExtPyClass(): classInfo = self.extPyClasses[self.name] return ".".join(classInfo) # <-- return 'Holder' def getPyClassDefinition(self): '''Return a list containing pyclass definition. ''' kw = KW.copy() # --> EXTENDED if self.hasExtPyClass(): classInfo = self.extPyClasses[self.name] kw['classInfo'] = classInfo[0] return ["%(ID3)simport %(classInfo)s" %kw ] # <-- kw['pyclass'] = self.getPyClass() definition = [] definition.append('%(ID3)sclass %(pyclass)s:' %kw) if self.metaclass is not None: kw['type'] = self.metaclass definition.append('%(ID4)s__metaclass__ = %(type)s' %kw) definition.append('%(ID4)stypecode = self' %kw) #TODO: Remove pyclass holder __init__ --> definition.append('%(ID4)sdef __init__(self):' %kw) definition.append('%(ID5)s# pyclass' %kw) # JRB HACK need to call _setElements via getElements self._setUpElements() # JRB HACK need to indent additional one level for el in self.elementAttrs: kw['element'] = el definition.append('%(ID2)s%(element)s' %kw) definition.append('%(ID5)sreturn' %kw) # <-- # pyclass descriptive name if self.name is not None: kw['name'] = self.name definition.append(\ '%(ID3)s%(pyclass)s.__name__ = "%(name)s_Holder"' %kw ) return definition def nsuriLogic(self): '''set a variable "ns" that represents the targetNamespace in which this item is defined. Used for namespacing local elements. ''' if self.parentClass: return 'ns = %s.%s.schema' %(self.parentClass, self.getClassName()) return 'ns = %s.%s.schema' %(self.getNSAlias(), self.getClassName()) def schemaTag(self): if self.ns is not None: return 'schema = "%s"' % self.ns raise ContainerError, 'failed to set schema targetNamespace(%s)' %(self.__class__) def typeTag(self): if self.name is not None: return 'type = (schema, "%s")' % self.name raise ContainerError, 'failed to set type name(%s)' %(self.__class__) def literalTag(self): if self.name is not None: return 'literal = "%s"' % self.name raise ContainerError, 'failed to set element name(%s)' %(self.__class__) def getExtraFlags(self): if self.mixed: self.extraFlags += 'mixed=True, mixed_aname="%s", ' %self.getMixedTextAName() return self.extraFlags def simpleConstructor(self, superclass=None): if superclass: return '%s.__init__(self, **kw)' % superclass else: return 'def __init__(self, **kw):' def pnameConstructor(self, superclass=None): if superclass: return '%s.__init__(self, pname, **kw)' % superclass else: return 'def __init__(self, pname, **kw):' def _setUpElements(self): """TODO: Remove this method This method ONLY sets up the instance attributes. Dependency instance attribute: mgContent -- expected to be either a complex definition with model group content, a model group, or model group content. TODO: should only support the first two. """ self.logger.debug("_setUpElements: %s" %self._item.getItemTrace()) if hasattr(self, '_done'): #return '\n'.join(self.elementAttrs) return self._done = True flat = [] content = self.mgContent if type(self.mgContent) is not tuple: mg = self.mgContent if not mg.isModelGroup(): mg = mg.content content = mg.content if mg.isAll(): flat = content content = [] elif mg.isModelGroup() and mg.isDefinition(): mg = mg.content content = mg.content idx = 0 content = list(content) while idx < len(content): c = orig = content[idx] if c.isElement(): flat.append(c) idx += 1 continue if c.isReference() and c.isModelGroup(): c = c.getModelGroupReference() if c.isDefinition() and c.isModelGroup(): c = c.content if c.isSequence() or c.isChoice(): begIdx = idx endIdx = begIdx + len(c.content) for i in range(begIdx, endIdx): content.insert(i, c.content[i-begIdx]) content.remove(orig) continue raise ContainerError, 'unexpected schema item: %s' %c.getItemTrace() for c in flat: if c.isDeclaration() and c.isElement(): defaultValue = "None" parent = c defs = [] # stop recursion via global ModelGroupDefinition while defs.count(parent) <= 1: maxOccurs = parent.getAttribute('maxOccurs') if maxOccurs == 'unbounded' or int(maxOccurs) > 1: defaultValue = "[]" break parent = parent._parent() if not parent.isModelGroup(): break if parent.isReference(): parent = parent.getModelGroupReference() if parent.isDefinition(): parent = parent.content defs.append(parent) if None == c.getAttribute('name') and c.isWildCard(): e = '%sself.%s = %s' %(ID3, self.getAttributeName('any'), defaultValue) else: e = '%sself.%s = %s' %(ID3, self.getAttributeName(c.getAttribute('name')), defaultValue) self.elementAttrs.append(e) continue # TODO: This seems wrong if c.isReference(): e = '%sself._%s = None' %(ID3, self.mangle(c.getAttribute('ref')[1])) self.elementAttrs.append(e) continue raise ContainerError, 'unexpected item: %s' % c.getItemTrace() #return '\n'.join(self.elementAttrs) return def _setTypecodeList(self): """generates ofwhat content, minOccurs/maxOccurs facet generation. Dependency instance attribute: mgContent -- expected to be either a complex definition with model group content, a model group, or model group content. TODO: should only support the first two. localTypes -- produce local class definitions later tcListElements -- elements, local/global """ self.logger.debug("_setTypecodeList(%r): %s" % (self.mgContent, self._item.getItemTrace())) flat = [] content = self.mgContent #TODO: too much slop permitted here, impossible # to tell what is going on. if type(content) is not tuple: mg = content if not mg.isModelGroup(): raise Wsdl2PythonErr("Expecting ModelGroup: %s" % mg.getItemTrace()) self.logger.debug("ModelGroup(%r) contents(%r): %s" % (mg, mg.content, mg.getItemTrace())) # if mg.isReference(): raise RuntimeError("Unexpected modelGroup reference: %s" % mg.getItemTrace()) # if mg.isDefinition(): mg = mg.content if mg.isAll(): flat = mg.content content = [] elif mg.isSequence(): content = mg.content elif mg.isChoice(): content = mg.content else: raise RuntimeError("Unknown schema item") idx = 0 content = list(content) self.logger.debug("content: %r" %content) while idx < len(content): c = orig = content[idx] if c.isElement(): flat.append(c) idx += 1 continue if c.isReference() and c.isModelGroup(): c = c.getModelGroupReference() if c.isDefinition() and c.isModelGroup(): c = c.content if c.isSequence() or c.isChoice(): begIdx = idx endIdx = begIdx + len(c.content) for i in range(begIdx, endIdx): content.insert(i, c.content[i-begIdx]) content.remove(orig) continue raise ContainerError, 'unexpected schema item: %s' %c.getItemTrace() # TODO: Need to store "parents" in a dict[id] = list(), # because cannot follow references, but not currently # a big concern. self.logger.debug("flat: %r" %list(flat)) for c in flat: tc = TcListComponentContainer() # TODO: Remove _getOccurs min,max,nil = self._getOccurs(c) min = max = None maxOccurs = 1 parent = c defs = [] # stop recursion via global ModelGroupDefinition while defs.count(parent) <= 1: max = parent.getAttribute('maxOccurs') if max == 'unbounded': maxOccurs = '"%s"' %max break maxOccurs = int(max) * maxOccurs parent = parent._parent() if not parent.isModelGroup(): break if parent.isReference(): parent = parent.getModelGroupReference() if parent.isDefinition(): parent = parent.content defs.append(parent) del defs parent = c while 1: minOccurs = int(parent.getAttribute('minOccurs')) if minOccurs == 0 or parent.isChoice(): minOccurs = 0 break parent = parent._parent() if not parent.isModelGroup(): minOccurs = int(c.getAttribute('minOccurs')) break if parent.isReference(): parent = parent.getModelGroupReference() if parent.isDefinition(): parent = parent.content tc.setOccurs(minOccurs, maxOccurs, nil) processContents = self._getProcessContents(c) tc.setProcessContents(processContents) if c.isDeclaration() and c.isElement(): global_type = c.getAttribute('type') content = getattr(c, 'content', None) if c.isLocal() and c.isQualified() is False: tc.unQualified() if c.isWildCard(): tc.setStyleAnyElement() elif global_type is not None: tc.name = c.getAttribute('name') ns = global_type[0] if ns in SCHEMA.XSD_LIST: tpc = BTI.get_typeclass(global_type[1],global_type[0]) tc.klass = tpc # elif (self.ns,self.name) == global_type: # # elif self._isRecursiveElement(c) # # TODO: Remove this, it only works for 1 level. # tc.setStyleRecursion() else: tc.setGlobalType(*global_type) # tc.klass = '%s.%s' % (NAD.getAlias(ns), # type_class_name(global_type[1])) del ns elif content is not None and content.isLocal() and content.isComplex(): tc.name = c.getAttribute('name') tc.klass = 'self.__class__.%s' % (element_class_name(tc.name)) #TODO: Not an element reference, confusing nomenclature tc.setStyleElementReference() self.localTypes.append(c) elif content is not None and content.isLocal() and content.isSimple(): # Local Simple Type tc.name = c.getAttribute('name') tc.klass = 'self.__class__.%s' % (element_class_name(tc.name)) #TODO: Not an element reference, confusing nomenclature tc.setStyleElementReference() self.localTypes.append(c) else: raise ContainerError, 'unexpected item: %s' % c.getItemTrace() elif c.isReference(): # element references ref = c.getAttribute('ref') # tc.klass = '%s.%s' % (NAD.getAlias(ref[0]), # element_class_name(ref[1]) ) tc.setStyleElementReference() tc.setGlobalType(*ref) else: raise ContainerError, 'unexpected item: %s' % c.getItemTrace() self.tcListElements.append(tc) def getTypecodeList(self): if not self.tcListSet: # self._flattenContent() self._setTypecodeList() self.tcListSet = True list = [] for e in self.tcListElements: list.append(str(e)) return ', '.join(list) # the following _methods() are utility methods used during # TCList generation, et al. def _getOccurs(self, e): nillable = e.getAttribute('nillable') if nillable == 'true': nillable = True else: nillable = False maxOccurs = e.getAttribute('maxOccurs') if maxOccurs == 'unbounded': maxOccurs = '"%s"' %maxOccurs minOccurs = e.getAttribute('minOccurs') if self.allOptional is True: #JRB Hack minOccurs = '0' maxOccurs = '"unbounded"' return minOccurs,maxOccurs,nillable def _getProcessContents(self, e): processContents = e.getAttribute('processContents') return processContents def getBasesLogic(self, indent): try: prefix = NAD.getAlias(self.sKlassNS) except WsdlGeneratorError, ex: # XSD or SOAP raise bases = [] bases.append(\ 'if %s.%s not in %s.%s.__bases__:'\ %(NAD.getAlias(self.sKlassNS), type_class_name(self.sKlass), self.getNSAlias(), self.getClassName()), ) bases.append(\ '%sbases = list(%s.%s.__bases__)'\ %(ID1,self.getNSAlias(),self.getClassName()), ) bases.append(\ '%sbases.insert(0, %s.%s)'\ %(ID1,NAD.getAlias(self.sKlassNS), type_class_name(self.sKlass) ), ) bases.append(\ '%s%s.%s.__bases__ = tuple(bases)'\ %(ID1, self.getNSAlias(), self.getClassName()) ) s = '' for b in bases: s += '%s%s\n' % (indent, b) return s class MessageTypecodeContainer(TypecodeContainerBase): '''Used for RPC style messages, where we have serveral parts serialized within a rpc wrapper name. ''' logger = _GetLogger("MessageTypecodeContainer") def __init__(self, parts=None): TypecodeContainerBase.__init__(self) self.mgContent = parts def _getOccurs(self, e): '''return a 3 item tuple ''' minOccurs = maxOccurs = '1' nillable = True return minOccurs,maxOccurs,nillable def _setTypecodeList(self): self.logger.debug("_setTypecodeList: %s" % str(self.mgContent)) assert type(self.mgContent) is tuple,\ 'expecting tuple for mgContent not: %s' %type(self.mgContent) for p in self.mgContent: # JRB # not sure what needs to be set for tc, this should be # the job of the constructor or a setUp method. min,max,nil = self._getOccurs(p) if p.element: raise WSInteropError, WSISpec.R2203 elif p.type: nsuri,name = p.type tc = RPCMessageTcListComponentContainer(qualified=False) tc.setOccurs(min, max, nil) tc.name = p.name if nsuri in [SOAP.ENC] + SCHEMA.XSD_LIST: tpc = BTI.get_typeclass(name, nsuri) tc.klass = tpc else: tc.klass = '%s.%s' % (NAD.getAlias(nsuri), type_class_name(name) ) else: raise ContainerError, 'part must define an element or type attribute' self.tcListElements.append(tc) def getTypecodeList(self): if not self.tcListSet: self._setTypecodeList() self.tcListSet = True list = [] for e in self.tcListElements: list.append(str(e)) return ', '.join(list) def getAttributeNames(self): '''returns a list of anames representing the parts of the message. ''' return map(lambda e: self.getAttributeName(e.name), self.tcListElements) def getParameterNames(self): '''returns a list of pnames representing the parts of the message. ''' return map(lambda e: e.name, self.tcListElements) def setParts(self, parts): self.mgContent = parts class TcListComponentContainer(ContainerBase): '''Encapsulates a single value in the TClist list. it inherits TypecodeContainerBase only to get the mangle() method, it does not call the baseclass ctor. TODO: Change this inheritance scheme. ''' logger = _GetLogger("TcListComponentContainer") def __init__(self, qualified=True): ''' qualified -- qualify element. All GEDs should be qualified, but local element declarations qualified if form attribute is qualified, else they are unqualified. Only relevant for standard style. ''' #TypecodeContainerBase.__init__(self) ContainerBase.__init__(self) self.qualified = qualified self.name = None self.klass = None self.global_type = None self.min = None self.max = None self.nil = None self.style = None self.setStyleElementDeclaration() def setOccurs(self, min, max, nil): self.min = min self.max = max self.nil = nil def setProcessContents(self, processContents): self.processContents = processContents def setGlobalType(self, namespace, name): self.global_type = (namespace, name) def setStyleElementDeclaration(self): '''set the element style. standard -- GED or local element ''' self.style = 'standard' def setStyleElementReference(self): '''set the element style. ref -- element reference ''' self.style = 'ref' def setStyleAnyElement(self): '''set the element style. anyElement -- element wildcard ''' self.name = 'any' self.style = 'anyElement' # def setStyleRecursion(self): # '''TODO: Remove. good for 1 level # ''' # self.style = 'recursion' def unQualified(self): '''Do not qualify element. ''' self.qualified = False def _getOccurs(self): return 'minOccurs=%s, maxOccurs=%s, nillable=%s' \ % (self.min, self.max, self.nil) def _getProcessContents(self): return 'processContents="%s"' \ % (self.processContents) def _getvalue(self): kw = {'occurs':self._getOccurs(), 'aname':self.getAttributeName(self.name), 'klass':self.klass, 'lazy':TypecodeContainerBase.lazy, 'typed':'typed=False', 'encoded':'encoded=kw.get("encoded")'} gt = self.global_type if gt is not None: kw['nsuri'],kw['type'] = gt if self.style == 'standard': kw['pname'] = '"%s"' %self.name if self.qualified is True: kw['pname'] = '(ns,"%s")' %self.name if gt is None: return '%(klass)s(pname=%(pname)s, aname="%(aname)s", %(occurs)s, %(typed)s, %(encoded)s)' %kw return 'GTD("%(nsuri)s","%(type)s",lazy=%(lazy)s)(pname=%(pname)s, aname="%(aname)s", %(occurs)s, %(typed)s, %(encoded)s)' %kw if self.style == 'ref': if gt is None: return '%(klass)s(%(occurs)s, %(encoded)s)' %kw return 'GED("%(nsuri)s","%(type)s",lazy=%(lazy)s, isref=True)(%(occurs)s, %(encoded)s)' %kw kw['process'] = self._getProcessContents() if self.style == 'anyElement': return 'ZSI.TC.AnyElement(aname="%(aname)s", %(occurs)s, %(process)s)' %kw # if self.style == 'recursion': # return 'ZSI.TC.AnyElement(aname="%(aname)s", %(occurs)s, %(process)s)' %kw raise RuntimeError, 'Must set style for typecode list generation' def __str__(self): return self._getvalue() class RPCMessageTcListComponentContainer(TcListComponentContainer): '''Container for rpc/literal rpc/encoded message typecode. ''' logger = _GetLogger("RPCMessageTcListComponentContainer") def __init__(self, qualified=True, encoded=None): ''' encoded -- encoded namespaceURI, if None treat as rpc/literal. ''' TcListComponentContainer.__init__(self, qualified=qualified) self._encoded = encoded def _getvalue(self): encoded = self._encoded if encoded is not None: encoded = '"%s"' %self._encoded if self.style == 'standard': pname = '"%s"' %self.name if self.qualified is True: pname = '(ns,"%s")' %self.name return '%s(pname=%s, aname="%s", typed=False, encoded=%s, %s)' \ %(self.klass, pname, self.getAttributeName(self.name), encoded, self._getOccurs()) elif self.style == 'ref': return '%s(encoded=%s, %s)' % (self.klass, encoded, self._getOccurs()) elif self.style == 'anyElement': return 'ZSI.TC.AnyElement(aname="%s", %s, %s)' \ %(self.getAttributeName(self.name), self._getOccurs(), self._getProcessContents()) # elif self.style == 'recursion': # return 'ZSI.TC.AnyElement(aname="%s", %s, %s)' \ # % (self.getAttributeName(self.name), self._getOccurs(), self._getProcessContents()) raise RuntimeError('Must set style(%s) for typecode list generation' % self.style) class ElementSimpleTypeContainer(TypecodeContainerBase): type = DEC logger = _GetLogger("ElementSimpleTypeContainer") def _substitutionGroupTag(self): value = self.substitutionGroup if not value: return 'substitutionGroup = None' nsuri,ncname = value return 'substitutionGroup = ("%s","%s")' %(nsuri, ncname) def _setContent(self): aname = self.getAttributeName(self.name) pyclass = self.pyclass # bool cannot be subclassed if pyclass == 'bool': pyclass = 'int' kw = KW.copy() kw.update(dict(aname=aname, ns=self.ns, name=self.name, substitutionGroup=self._substitutionGroupTag(), subclass=self.sKlass,literal=self.literalTag(), schema=self.schemaTag(), init=self.simpleConstructor(), klass=self.getClassName(), element="ElementDeclaration")) if self.local: kw['element'] = 'LocalElementDeclaration' element = map(lambda i: i %kw, [ '%(ID1)sclass %(klass)s(%(subclass)s, %(element)s):', '%(ID2)s%(literal)s', '%(ID2)s%(schema)s', '%(ID2)s%(init)s', '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")', '%(ID3)skw["aname"] = "%(aname)s"', ] ) # TODO: What about getPyClass and getPyClassDefinition? # I want to add pyclass metaclass here but this needs to be # corrected first. # # anyType (?others) has no pyclass. app = element.append if pyclass is not None: app('%sclass IHolder(%s): typecode=self' % (ID3, pyclass),) app('%skw["pyclass"] = IHolder' %(ID3),) app('%sIHolder.__name__ = "%s_immutable_holder"' %(ID3, aname),) app('%s%s' % (ID3, self.simpleConstructor(self.sKlass)),) self.writeArray(element) def setUp(self, tp): self._item = tp self.local = tp.isLocal() try: self.name = tp.getAttribute('name') self.substitutionGroup = tp.getAttribute('substitutionGroup') self.ns = tp.getTargetNamespace() qName = tp.getAttribute('type') except Exception, ex: raise Wsdl2PythonError('Error occured processing element: %s' %( tp.getItemTrace()), *ex.args) if qName is None: raise Wsdl2PythonError('Missing QName for element type attribute: %s' %tp.getItemTrace()) tns,local = qName.getTargetNamespace(),qName.getName() self.sKlass = BTI.get_typeclass(local, tns) if self.sKlass is None: raise Wsdl2PythonError('No built-in typecode for type definition("%s","%s"): %s' %(tns,local,tp.getItemTrace())) try: self.pyclass = BTI.get_pythontype(None, None, typeclass=self.sKlass) except Exception, ex: raise Wsdl2PythonError('Error occured processing element: %s' %( tp.getItemTrace()), *ex.args) class ElementLocalSimpleTypeContainer(TypecodeContainerBase): '''local simpleType container ''' type = DEC logger = _GetLogger("ElementLocalSimpleTypeContainer") def _setContent(self): kw = KW.copy() kw.update(dict(aname=self.getAttributeName(self.name), ns=self.ns, name=self.name, subclass=self.sKlass,literal=self.literalTag(), schema=self.schemaTag(), init=self.simpleConstructor(), klass=self.getClassName(), element="ElementDeclaration", baseinit=self.simpleConstructor(self.sKlass))) if self.local: kw['element'] = 'LocalElementDeclaration' element = map(lambda i: i %kw, [ '%(ID1)sclass %(klass)s(%(subclass)s, %(element)s):', '%(ID2)s%(literal)s', '%(ID2)s%(schema)s', '%(ID2)s%(init)s', '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")', '%(ID3)skw["aname"] = "%(aname)s"', '%(ID3)s%(baseinit)s', ] ) app = element.append pyclass = self.pyclass if pyclass is not None: # bool cannot be subclassed if pyclass == 'bool': pyclass = 'int' kw['pyclass'] = pyclass app('%(ID3)sclass IHolder(%(pyclass)s): typecode=self' %kw) app('%(ID3)sself.pyclass = IHolder' %kw) app('%(ID3)sIHolder.__name__ = "%(aname)s_immutable_holder"' %kw) self.writeArray(element) def _setup_pyclass(self): try: self.pyclass = BTI.get_pythontype(None, None, typeclass=self.sKlass) except Exception, ex: raise Wsdl2PythonError('Error occured processing element: %s' %( self._item.getItemTrace()), *ex.args) def setUp(self, tp): self._item = tp assert tp.isElement() is True and tp.content is not None and \ tp.content.isLocal() is True and tp.content.isSimple() is True ,\ 'expecting local simple type: %s' %tp.getItemTrace() self.local = tp.isLocal() self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() content = tp.content.content if content.isRestriction(): try: base = content.getTypeDefinition() except XMLSchema.SchemaError, ex: base = None qName = content.getAttributeBase() if base is None: self.sKlass = BTI.get_typeclass(qName[1], qName[0]) self._setup_pyclass() return raise Wsdl2PythonError, 'unsupported local simpleType restriction: %s' \ %tp.content.getItemTrace() if content.isList(): try: base = content.getTypeDefinition() except XMLSchema.SchemaError, ex: base = None if base is None: qName = content.getItemType() self.sKlass = BTI.get_typeclass(qName[1], qName[0]) self._setup_pyclass() return raise Wsdl2PythonError, 'unsupported local simpleType List: %s' \ %tp.content.getItemTrace() if content.isUnion(): raise Wsdl2PythonError, 'unsupported local simpleType Union: %s' \ %tp.content.getItemTrace() raise Wsdl2PythonError, 'unexpected schema item: %s' \ %tp.content.getItemTrace() class ElementLocalComplexTypeContainer(TypecodeContainerBase, AttributeMixIn): type = DEC logger = _GetLogger("ElementLocalComplexTypeContainer") def _setContent(self): kw = KW.copy() try: kw.update(dict(klass=self.getClassName(), subclass='ZSI.TCcompound.ComplexType', element='ElementDeclaration', literal=self.literalTag(), schema=self.schemaTag(), init=self.simpleConstructor(), ns=self.ns, name=self.name, aname=self.getAttributeName(self.name), nsurilogic=self.nsuriLogic(), ofwhat=self.getTypecodeList(), atypecode=self.attribute_typecode, pyclass=self.getPyClass(), )) except Exception, ex: args = ['Failure processing an element w/local complexType: %s' %( self._item.getItemTrace())] args += ex.args ex.args = tuple(args) raise if self.local: kw['element'] = 'LocalElementDeclaration' element = [ '%(ID1)sclass %(klass)s(%(subclass)s, %(element)s):', '%(ID2)s%(literal)s', '%(ID2)s%(schema)s', '%(ID2)s%(init)s', '%(ID3)s%(nsurilogic)s', '%(ID3)sTClist = [%(ofwhat)s]', '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")', '%(ID3)skw["aname"] = "%(aname)s"', '%(ID3)s%(atypecode)s = {}', '%(ID3)sZSI.TCcompound.ComplexType.__init__(self,None,TClist,inorder=0,**kw)', ] for l in self.attrComponents: element.append('%(ID3)s'+str(l)) element += self.getPyClassDefinition() element.append('%(ID3)sself.pyclass = %(pyclass)s' %kw) self.writeArray(map(lambda l: l %kw, element)) def setUp(self, tp): ''' {'xsd':['annotation', 'simpleContent', 'complexContent',\ 'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',\ 'anyAttribute', 'any']} ''' # # TODO: Need a Recursive solution, this is incomplete will ignore many # extensions, restrictions, etc. # self._item = tp # JRB HACK SUPPORTING element/no content. assert tp.isElement() is True and \ (tp.content is None or (tp.content.isComplex() is True and tp.content.isLocal() is True)),\ 'expecting element w/local complexType not: %s' %tp.content.getItemTrace() self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() self.local = tp.isLocal() complex = tp.content # JRB HACK SUPPORTING element/no content. if complex is None: self.mgContent = () return #attributeContent = complex.getAttributeContent() #self.mgContent = None if complex.content is None: self.mgContent = () self.attrComponents = self._setAttributes(complex.getAttributeContent()) return is_simple = complex.content.isSimple() if is_simple and complex.content.content.isExtension(): # TODO: Not really supported just passing thru self.mgContent = () self.attrComponents = self._setAttributes(complex.getAttributeContent()) return if is_simple and complex.content.content.isRestriction(): # TODO: Not really supported just passing thru self.mgContent = () self.attrComponents = self._setAttributes(complex.getAttributeContent()) return if is_simple: raise ContainerError, 'not implemented local complexType/simpleContent: %s'\ %tp.getItemTrace() is_complex = complex.content.isComplex() if is_complex and complex.content.content is None: # TODO: Recursion... self.mgContent = () self.attrComponents = self._setAttributes(complex.getAttributeContent()) return if (is_complex and complex.content.content.isExtension() and complex.content.content.content is not None and complex.content.content.content.isModelGroup()): self.mgContent = complex.content.content.content.content self.attrComponents = self._setAttributes( complex.content.content.getAttributeContent() ) return if (is_complex and complex.content.content.isRestriction() and complex.content.content.content is not None and complex.content.content.content.isModelGroup()): self.mgContent = complex.content.content.content.content self.attrComponents = self._setAttributes( complex.content.content.getAttributeContent() ) return if is_complex: self.mgContent = () self.attrComponents = self._setAttributes(complex.getAttributeContent()) return if complex.content.isModelGroup(): self.mgContent = complex.content.content self.attrComponents = self._setAttributes(complex.getAttributeContent()) return # TODO: Scary Fallthru self.mgContent = () self.attrComponents = self._setAttributes(complex.getAttributeContent()) class ElementGlobalDefContainer(TypecodeContainerBase): type = DEC logger = _GetLogger("ElementGlobalDefContainer") def _substitutionGroupTag(self): value = self.substitutionGroup if not value: return 'substitutionGroup = None' nsuri,ncname = value return 'substitutionGroup = ("%s","%s")' %(nsuri, ncname) def _setContent(self): '''GED defines element name, so also define typecode aname ''' kw = KW.copy() try: kw.update(dict(klass=self.getClassName(), element='ElementDeclaration', literal=self.literalTag(), substitutionGroup=self._substitutionGroupTag(), schema=self.schemaTag(), init=self.simpleConstructor(), ns=self.ns, name=self.name, aname=self.getAttributeName(self.name), baseslogic=self.getBasesLogic(ID3), #ofwhat=self.getTypecodeList(), #atypecode=self.attribute_typecode, #pyclass=self.getPyClass(), alias=NAD.getAlias(self.sKlassNS), subclass=type_class_name(self.sKlass), )) except Exception, ex: args = ['Failure processing an element w/local complexType: %s' %( self._item.getItemTrace())] args += ex.args ex.args = tuple(args) raise if self.local: kw['element'] = 'LocalElementDeclaration' element = [ '%(ID1)sclass %(klass)s(%(element)s):', '%(ID2)s%(literal)s', '%(ID2)s%(schema)s', '%(ID2)s%(substitutionGroup)s', '%(ID2)s%(init)s', '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")', '%(ID3)skw["aname"] = "%(aname)s"', '%(baseslogic)s', '%(ID3)s%(alias)s.%(subclass)s.__init__(self, **kw)', '%(ID3)sif self.pyclass is not None: self.pyclass.__name__ = "%(klass)s_Holder"', ] self.writeArray(map(lambda l: l %kw, element)) def setUp(self, element): # Save for debugging self._item = element self.local = element.isLocal() self.name = element.getAttribute('name') self.substitutionGroup = element.getAttribute('substitutionGroup') self.ns = element.getTargetNamespace() tp = element.getTypeDefinition('type') self.sKlass = tp.getAttribute('name') self.sKlassNS = tp.getTargetNamespace() class ComplexTypeComplexContentContainer(TypecodeContainerBase, AttributeMixIn): '''Represents ComplexType with ComplexContent. ''' type = DEF logger = _GetLogger("ComplexTypeComplexContentContainer") def __init__(self, do_extended=False): TypecodeContainerBase.__init__(self, do_extended=do_extended) def setUp(self, tp): '''complexContent/[extension,restriction] restriction extension extType -- used in figuring attrs for extensions ''' self._item = tp assert tp.content.isComplex() is True and \ (tp.content.content.isRestriction() or tp.content.content.isExtension() is True),\ 'expecting complexContent/[extension,restriction]' self.extType = None self.restriction = False self.extension = False self._kw_array = None self._is_array = False self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() # xxx: what is this for? #self.attribute_typecode = 'attributes' derivation = tp.content.content # Defined in Schema instance? try: base = derivation.getTypeDefinition('base') except XMLSchema.SchemaError, ex: base = None # anyType, arrayType, etc... if base is None: base = derivation.getAttributeQName('base') if base is None: raise ContainerError, 'Unsupported derivation: %s'\ %derivation.getItemTrace() if base != (SOAP.ENC,'Array') and base != (SCHEMA.XSD3,'anyType'): raise ContainerError, 'Unsupported base(%s): %s' %( base, derivation.getItemTrace() ) if base == (SOAP.ENC,'Array'): # SOAP-ENC:Array expecting arrayType attribute reference self.logger.debug("Derivation of soapenc:Array") self._is_array = True self._kw_array = {'atype':None, 'id3':ID3, 'ofwhat':None} self.sKlass = BTI.get_typeclass(base[1], base[0]) self.sKlassNS = base[0] for a in derivation.getAttributeContent(): assert a.isAttribute() is True,\ 'only attribute content expected: %s' %a.getItemTrace() if a.isReference() is False: continue if a.getAttribute('ref') != (SOAP.ENC,'arrayType'): continue attr = a.getAttributeQName((WSDL.BASE, 'arrayType')) if attr is None: warnings.warn('soapenc:array derivation declares attribute reference ("%s","%s"), does not define attribute ("%s","%s")' %( SOAP.ENC,'arrayType',WSDL.BASE, 'arrayType')) break self._kw_array['atype'] = attr qname = self._kw_array.get('atype') if a is not None: ncname = qname[1].strip('[]') namespace = qname[0] try: ofwhat = a.getSchemaItem(XMLSchema.TYPES, namespace, ncname) except XMLSchema.SchemaError, ex: ofwhat = None if ofwhat is None: self._kw_array['ofwhat'] = BTI.get_typeclass(ncname, namespace) else: self._kw_array['ofwhat'] = GetClassNameFromSchemaItem(ofwhat, do_extended=self.do_extended) if self._kw_array['ofwhat'] is None: raise ContainerError, 'For Array could not resolve ofwhat typecode(%s,%s): %s'\ %(namespace, ncname, derivation.getItemTrace()) self.logger.debug('Attribute soapenc:arrayType="%s"' % str(self._kw_array['ofwhat'])) break #else: # raise Wsdl2PythonError, \ # 'derivation of soapenc:array must declare attribute reference ("%s","%s")' %( # SOAP.ENC,'arrayType') elif isinstance(base, XMLSchema.XMLSchemaComponent): self.sKlass = base.getAttribute('name') self.sKlassNS = base.getTargetNamespace() else: # TypeDescriptionComponent self.sKlass = base.getName() self.sKlassNS = base.getTargetNamespace() attrs = [] if derivation.isRestriction(): self.restriction = True self.extension = False # derivation.getAttributeContent subset of tp.getAttributeContent attrs += derivation.getAttributeContent() or () else: self.restriction = False self.extension = True attrs += tp.getAttributeContent() or () if isinstance(derivation, XMLSchema.XMLSchemaComponent): attrs += derivation.getAttributeContent() or () # XXX: not sure what this is doing if attrs: self.extType = derivation if derivation.content is not None \ and derivation.content.isModelGroup(): group = derivation.content if group.isReference(): group = group.getModelGroupReference() self.mgContent = group.content elif derivation.content: raise Wsdl2PythonError, \ 'expecting model group, not: %s' %derivation.content.getItemTrace() else: self.mgContent = () self.attrComponents = self._setAttributes(tuple(attrs)) def _setContent(self): '''JRB What is the difference between instance data ns, name, -- type definition? sKlass, sKlassNS? -- element declaration? ''' kw = KW.copy() definition = [] if self._is_array: # SOAP-ENC:Array if _is_xsd_or_soap_ns(self.sKlassNS) is False and self.sKlass == 'Array': raise ContainerError, 'unknown type: (%s,%s)'\ %(self.sKlass, self.sKlassNS) # No need to xsi:type array items since specify with # SOAP-ENC:arrayType attribute. definition += [\ '%sclass %s(ZSI.TC.Array, TypeDefinition):' % (ID1, self.getClassName()), '%s#complexType/complexContent base="SOAP-ENC:Array"' %(ID2), '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), ] append = definition.append if self._kw_array.get('ofwhat') is None: append('%s%s.__init__(self, None, None, pname=pname, childnames=\'item\', undeclared=True, **kw)' %(ID3, self.sKlass)) else: append('%(id3)sofwhat = %(ofwhat)s(None, typed=False)' %self._kw_array) append('%(id3)satype = %(atype)s' %self._kw_array) append('%s%s.__init__(self, atype, ofwhat, pname=pname, childnames=\'item\', **kw)' %(ID3, self.sKlass)) self.writeArray(definition) return definition += [\ '%sclass %s(TypeDefinition):' % (ID1, self.getClassName()), '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), '%s%s' % (ID3, self.nsuriLogic()), '%sTClist = [%s]' % (ID3, self.getTypecodeList()), ] definition.append( '%(ID3)sattributes = %(atc)s = attributes or {}' %{ 'ID3':ID3, 'atc':self.attribute_typecode} ) # # Special case: anyType restriction isAnyType = (self.sKlassNS, self.sKlass) == (SCHEMA.XSD3, 'anyType') if isAnyType: del definition[0] definition.insert(0, '%sclass %s(ZSI.TC.ComplexType, TypeDefinition):' % ( ID1, self.getClassName()) ) definition.insert(1, '%s#complexType/complexContent restrict anyType' %( ID2) ) # derived type support definition.append('%sif extend: TClist += ofwhat'%(ID3)) definition.append('%sif restrict: TClist = ofwhat' %(ID3)) if len(self.attrComponents) > 0: definition.append('%selse:' %(ID3)) for l in self.attrComponents: definition.append('%s%s'%(ID4, l)) if isAnyType: definition.append(\ '%sZSI.TC.ComplexType.__init__(self, None, TClist, pname=pname, **kw)' %( ID3), ) # pyclass class definition definition += self.getPyClassDefinition() kw['pyclass'] = self.getPyClass() definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw) self.writeArray(definition) return definition.append('%s' % self.getBasesLogic(ID3)) prefix = NAD.getAlias(self.sKlassNS) typeClassName = type_class_name(self.sKlass) if self.restriction: definition.append(\ '%s%s.%s.__init__(self, pname, ofwhat=TClist, restrict=True, **kw)' %( ID3, prefix, typeClassName), ) definition.insert(1, '%s#complexType/complexContent restriction' %ID2) self.writeArray(definition) return if self.extension: definition.append(\ '%s%s.%s.__init__(self, pname, ofwhat=TClist, extend=True, attributes=attributes, **kw)'%( ID3, prefix, typeClassName), ) definition.insert(1, '%s#complexType/complexContent extension' %(ID2)) self.writeArray(definition) return raise Wsdl2PythonError,\ 'ComplexContent must be a restriction or extension' def pnameConstructor(self, superclass=None): if superclass: return '%s.__init__(self, pname, ofwhat=(), extend=False, restrict=False, attributes=None, **kw)' % superclass return 'def __init__(self, pname, ofwhat=(), extend=False, restrict=False, attributes=None, **kw):' class ComplexTypeContainer(TypecodeContainerBase, AttributeMixIn): '''Represents a global complexType definition. ''' type = DEF logger = _GetLogger("ComplexTypeContainer") def setUp(self, tp, empty=False): '''Problematic, loose all model group information. , , .. tp -- type definition empty -- no model group, just use as a dummy holder. ''' self._item = tp self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() self.mixed = tp.isMixed() self.mgContent = () self.attrComponents = self._setAttributes(tp.getAttributeContent()) # Save reference to type for debugging self._item = tp if empty: return model = tp.content if model.isReference(): model = model.getModelGroupReference() if model is None: return if model.content is None: return # sequence, all or choice #self.mgContent = model.content self.mgContent = model def _setContent(self): try: definition = [ '%sclass %s(ZSI.TCcompound.ComplexType, TypeDefinition):' % (ID1, self.getClassName()), '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), #'%s' % self.getElements(), '%s%s' % (ID3, self.nsuriLogic()), '%sTClist = [%s]' % (ID3, self.getTypecodeList()), ] except Exception, ex: args = ["Failure processing %s" %self._item.getItemTrace()] args += ex.args ex.args = tuple(args) raise definition.append('%s%s = attributes or {}' %(ID3, self.attribute_typecode)) # IF EXTEND definition.append('%sif extend: TClist += ofwhat'%(ID3)) # IF RESTRICT definition.append('%sif restrict: TClist = ofwhat' %(ID3)) # ELSE if len(self.attrComponents) > 0: definition.append('%selse:' %(ID3)) for l in self.attrComponents: definition.append('%s%s'%(ID4, l)) definition.append(\ '%sZSI.TCcompound.ComplexType.__init__(self, None, TClist, pname=pname, inorder=0, %s**kw)' \ %(ID3, self.getExtraFlags()) ) # pyclass class definition definition += self.getPyClassDefinition() # set pyclass kw = KW.copy() kw['pyclass'] = self.getPyClass() definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw) self.writeArray(definition) def pnameConstructor(self, superclass=None): ''' TODO: Logic is a little tricky. If superclass is ComplexType this is not used. ''' if superclass: return '%s.__init__(self, pname, ofwhat=(), attributes=None, extend=False, restrict=False, **kw)' % superclass return 'def __init__(self, pname, ofwhat=(), attributes=None, extend=False, restrict=False, **kw):' class SimpleTypeContainer(TypecodeContainerBase): type = DEF logger = _GetLogger("SimpleTypeContainer") def __init__(self): ''' Instance Data From TypecodeContainerBase NOT USED... mgContent ''' TypecodeContainerBase.__init__(self) def setUp(self, tp): raise NotImplementedError, 'abstract method not implemented' def _setContent(self, tp): raise NotImplementedError, 'abstract method not implemented' def getPythonType(self): pyclass = eval(str(self.sKlass)) if issubclass(pyclass, ZSI.TC.String): return 'str' if issubclass(pyclass, ZSI.TC.Ilong) or issubclass(pyclass, ZSI.TC.IunsignedLong): return 'long' if issubclass(pyclass, ZSI.TC.Boolean) or issubclass(pyclass, ZSI.TC.Integer): return 'int' if issubclass(pyclass, ZSI.TC.Decimal): return 'float' if issubclass(pyclass, ZSI.TC.Gregorian) or issubclass(pyclass, ZSI.TC.Duration): return 'tuple' return None def getPyClassDefinition(self): definition = [] pt = self.getPythonType() if pt is not None: definition.append('%sclass %s(%s):' %(ID3,self.getPyClass(),pt)) definition.append('%stypecode = self' %ID4) return definition class RestrictionContainer(SimpleTypeContainer): ''' simpleType/restriction ''' logger = _GetLogger("RestrictionContainer") def setUp(self, tp): self._item = tp assert tp.isSimple() is True and tp.isDefinition() is True and \ tp.content.isRestriction() is True,\ 'expecting simpleType restriction, not: %s' %tp.getItemTrace() if tp.content is None: raise Wsdl2PythonError, \ 'empty simpleType defintion: %s' %tp.getItemTrace() self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() self.sKlass = None base = tp.content.getAttribute('base') if base is not None: try: item = tp.content.getTypeDefinition('base') except XMLSchema.SchemaError, ex: item = None if item is None: self.sKlass = BTI.get_typeclass(base.getName(), base.getTargetNamespace()) if self.sKlass is not None: return raise Wsdl2PythonError('no built-in type nor schema instance type for base attribute("%s","%s"): %s' %( base.getTargetNamespace(), base.getName(), tp.getItemTrace())) raise Wsdl2PythonError, \ 'Not Supporting simpleType/Restriction w/User-Defined Base: %s %s' %(tp.getItemTrace(),item.getItemTrace()) sc = tp.content.getSimpleTypeContent() if sc is not None and True is sc.isSimple() is sc.isLocal() is sc.isDefinition(): base = None if sc.content.isRestriction() is True: try: item = tp.content.getTypeDefinition('base') except XMLSchema.SchemaError, ex: pass if item is None: base = sc.content.getAttribute('base') if base is not None: self.sKlass = BTI.get_typeclass(base.getTargetNamespace(), base.getName()) return raise Wsdl2PythonError, \ 'Not Supporting simpleType/Restriction w/User-Defined Base: '\ %item.getItemTrace() raise Wsdl2PythonError, \ 'Not Supporting simpleType/Restriction w/User-Defined Base: '\ %item.getItemTrace() if sc.content.isList() is True: raise Wsdl2PythonError, \ 'iction base in subtypes: %s'\ %sc.getItemTrace() if sc.content.isUnion() is True: raise Wsdl2PythonError, \ 'could not get restriction base in subtypes: %s'\ %sc.getItemTrace() return raise Wsdl2PythonError, 'No Restriction @base/simpleType: %s' %tp.getItemTrace() def _setContent(self): definition = [ '%sclass %s(%s, TypeDefinition):' %(ID1, self.getClassName(), self.sKlass), '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), ] if self.getPythonType() is None: definition.append('%s%s.__init__(self, pname, **kw)' %(ID3, self.sKlass)) else: definition.append('%s%s.__init__(self, pname, pyclass=None, **kw)' \ %(ID3, self.sKlass,)) # pyclass class definition definition += self.getPyClassDefinition() # set pyclass kw = KW.copy() kw['pyclass'] = self.getPyClass() definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw) self.writeArray(definition) class ComplexTypeSimpleContentContainer(SimpleTypeContainer, AttributeMixIn): '''Represents a ComplexType with simpleContent. ''' type = DEF logger = _GetLogger("ComplexTypeSimpleContentContainer") def setUp(self, tp): '''tp -- complexType/simpleContent/[Exention,Restriction] ''' self._item = tp assert tp.isComplex() is True and tp.content.isSimple() is True,\ 'expecting complexType/simpleContent not: %s' %tp.content.getItemTrace() simple = tp.content dv = simple.content assert dv.isExtension() is True or dv.isRestriction() is True,\ 'expecting complexType/simpleContent/[Extension,Restriction] not: %s' \ %tp.content.getItemTrace() self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() # TODO: Why is this being set? self.content.attributeContent = dv.getAttributeContent() base = dv.getAttribute('base') if base is not None: self.sKlass = BTI.get_typeclass( base[1], base[0] ) if not self.sKlass: self.sKlass,self.sKlassNS = base[1], base[0] self.attrComponents = self._setAttributes( self.content.attributeContent ) return raise Wsdl2PythonError,\ 'simple content derivation bad base attribute: ' %tp.getItemTrace() def _setContent(self): # TODO: Add derivation logic to constructors. if type(self.sKlass) in (types.ClassType, type): definition = [ '%sclass %s(%s, TypeDefinition):' \ % (ID1, self.getClassName(), self.sKlass), '%s# ComplexType/SimpleContent derivation of built-in type' %ID2, '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), '%sif getattr(self, "attribute_typecode_dict", None) is None: %s = {}' %( ID3, self.attribute_typecode), ] for l in self.attrComponents: definition.append('%s%s'%(ID3, l)) definition.append('%s%s.__init__(self, pname, **kw)' %(ID3, self.sKlass)) if self.getPythonType() is not None: definition += self.getPyClassDefinition() kw = KW.copy() kw['pyclass'] = self.getPyClass() definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw) self.writeArray(definition) return definition = [ '%sclass %s(TypeDefinition):' % (ID1, self.getClassName()), '%s# ComplexType/SimpleContent derivation of user-defined type' %ID2, '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), '%s%s' % (ID3, self.nsuriLogic()), '%s' % self.getBasesLogic(ID3), '%sif getattr(self, "attribute_typecode_dict", None) is None: %s = {}' %( ID3, self.attribute_typecode), ] for l in self.attrComponents: definition.append('%s%s'%(ID3, l)) definition.append('%s%s.%s.__init__(self, pname, **kw)' %( ID3, NAD.getAlias(self.sKlassNS), type_class_name(self.sKlass))) self.writeArray(definition) def getPyClassDefinition(self): definition = [] pt = self.getPythonType() if pt is not None: definition.append('%sclass %s(%s):' %(ID3,self.getPyClass(),pt)) if self.metaclass is not None: definition.append('%s__metaclass__ = %s' %(ID4, self.metaclass)) definition.append('%stypecode = self' %ID4) return definition class UnionContainer(SimpleTypeContainer): '''SimpleType Union ''' type = DEF logger = _GetLogger("UnionContainer") def __init__(self): SimpleTypeContainer.__init__(self) self.memberTypes = None def setUp(self, tp): self._item = tp if tp.content.isUnion() is False: raise ContainerError, 'content must be a Union: %s' %tp.getItemTrace() self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() self.sKlass = 'ZSI.TC.Union' self.memberTypes = tp.content.getAttribute('memberTypes') def _setContent(self): definition = [ '%sclass %s(%s, TypeDefinition):' \ % (ID1, self.getClassName(), self.sKlass), '%smemberTypes = %s' % (ID2, self.memberTypes), '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), '%s%s' % (ID3, self.pnameConstructor(self.sKlass)), ] # TODO: Union pyclass is None self.writeArray(definition) class ListContainer(SimpleTypeContainer): '''SimpleType List ''' type = DEF logger = _GetLogger("ListContainer") def setUp(self, tp): self._item = tp if tp.content.isList() is False: raise ContainerError, 'content must be a List: %s' %tp.getItemTrace() self.name = tp.getAttribute('name') self.ns = tp.getTargetNamespace() self.sKlass = 'ZSI.TC.List' self.itemType = tp.content.getAttribute('itemType') def _setContent(self): definition = [ '%sclass %s(%s, TypeDefinition):' \ % (ID1, self.getClassName(), self.sKlass), '%sitemType = %s' % (ID2, self.itemType), '%s%s' % (ID2, self.schemaTag()), '%s%s' % (ID2, self.typeTag()), '%s%s' % (ID2, self.pnameConstructor()), '%s%s' % (ID3, self.pnameConstructor(self.sKlass)), ] self.writeArray(definition) ZSI-2.1-a1/ZSI/generate/commands.py0000644000175100017510000004660010656174245015150 0ustar zsizsi############################################################################ # Joshua Boverhof, LBNL # Monte Goode , LBNL # See Copyright for copyright notice! ############################################################################ import exceptions, sys, optparse, os, warnings, traceback from os.path import isfile, join, split #from operator import xor import ZSI from ConfigParser import ConfigParser from ZSI.generate.wsdl2python import WriteServiceModule, ServiceDescription as wsdl2pyServiceDescription from ZSI.wstools import WSDLTools, XMLSchema from ZSI.wstools.logging import setBasicLoggerDEBUG from ZSI.generate import containers, utility from ZSI.generate.utility import NCName_to_ClassName as NC_to_CN, TextProtect from ZSI.generate.wsdl2dispatch import ServiceModuleWriter as ServiceDescription from ZSI.generate.wsdl2dispatch import WSAServiceModuleWriter as ServiceDescriptionWSA warnings.filterwarnings('ignore', '', exceptions.UserWarning) def SetDebugCallback(option, opt, value, parser, *args, **kwargs): setBasicLoggerDEBUG() warnings.resetwarnings() def SetPyclassMetaclass(option, opt, value, parser, *args, **kwargs): """set up pyclass metaclass for complexTypes""" from ZSI.generate.containers import ServiceHeaderContainer,\ TypecodeContainerBase, TypesHeaderContainer TypecodeContainerBase.metaclass = kwargs['metaclass'] TypesHeaderContainer.imports.append(\ 'from %(module)s import %(metaclass)s' %kwargs ) ServiceHeaderContainer.imports.append(\ 'from %(module)s import %(metaclass)s' %kwargs ) def SetUpLazyEvaluation(option, opt, value, parser, *args, **kwargs): from ZSI.generate.containers import TypecodeContainerBase TypecodeContainerBase.lazy = True def wsdl2py(args=None): """Utility for automatically generating client/service interface code from a wsdl definition, and a set of classes representing element declarations and type definitions. By default invoking this script produces three files, each named after the wsdl definition name, in the current working directory. Generated Modules Suffix: _client.py -- client locator, rpc proxy port, messages _types.py -- typecodes representing _server.py -- server-side bindings Parameters: args -- optional can provide arguments, rather than parsing command-line. return: Default behavior is to return None, if args are provided then return names of the generated files. """ op = optparse.OptionParser(usage="USAGE: %wsdl2py [options] WSDL", description=wsdl2py.__doc__) # Basic options op.add_option("-x", "--schema", action="store_true", dest="schema", default=False, help="process just the schema from an xsd file [no services]") op.add_option("-d", "--debug", action="callback", callback=SetDebugCallback, help="debug output") # WS Options op.add_option("-a", "--address", action="store_true", dest="address", default=False, help="ws-addressing support, must include WS-Addressing schema.") # pyclass Metaclass op.add_option("-b", "--complexType", action="callback", callback=SetPyclassMetaclass, callback_kwargs={'module':'ZSI.generate.pyclass', 'metaclass':'pyclass_type'}, help="add convenience functions for complexTypes, including Getters, Setters, factory methods, and properties (via metaclass). *** DONT USE WITH --simple-naming ***") # Lazy Evaluation of Typecodes (done at serialization/parsing when needed). op.add_option("-l", "--lazy", action="callback", callback=SetUpLazyEvaluation, callback_kwargs={}, help="EXPERIMENTAL: recursion error solution, lazy evalution of typecodes") # Use Twisted op.add_option("-w", "--twisted", action="store_true", dest='twisted', default=False, help="generate a twisted.web client/server, dependencies python>=2.4, Twisted>=2.0.0, TwistedWeb>=0.5.0") op.add_option("-o", "--output-dir", action="store", dest="output_dir", default=".", type="string", help="save files in directory") op.add_option("-s", "--simple-naming", action="store_true", dest="simple_naming", default=False, help="map element names directly to python attributes") op.add_option("-p", "--pydoc", action="store_true", dest="pydoc", default=False, help="top-level directory for pydoc documentation.") is_cmdline = args is None if is_cmdline: (options, args) = op.parse_args() else: (options, args) = op.parse_args(args) if len(args) != 1: print>>sys.stderr, 'Expecting a file/url as argument (WSDL).' sys.exit(os.EX_USAGE) location = args[0] if options.schema is True: reader = XMLSchema.SchemaReader(base_url=location) else: reader = WSDLTools.WSDLReader() load = reader.loadFromFile if not isfile(location): load = reader.loadFromURL try: wsdl = load(location) except Exception, e: print >> sys.stderr, "Error loading %s: \n\t%s" % (location, e) traceback.print_exc(sys.stderr) # exit code UNIX specific, Windows? if hasattr(os, 'EX_NOINPUT'): sys.exit(os.EX_NOINPUT) sys.exit("error loading %s" %location) if isinstance(wsdl, XMLSchema.XMLSchema): wsdl.location = location files = _wsdl2py(options, wsdl) else: files = _wsdl2py(options, wsdl) files.append(_wsdl2dispatch(options, wsdl)) if getattr(options, 'pydoc', False): _writepydoc(os.path.join('docs', 'API'), *files) if is_cmdline: return return files #def wsdl2dispatch(args=None): # """Deprecated: wsdl2py now generates everything # A utility for automatically generating service skeleton code from a wsdl # definition. # """ # op = optparse.OptionParser() # op.add_option("-a", "--address", # action="store_true", dest="address", default=False, # help="ws-addressing support, must include WS-Addressing schema.") # op.add_option("-d", "--debug", # action="callback", callback=SetDebugCallback, # help="debug output") # op.add_option("-t", "--types", # action="store", dest="types", default=None, type="string", # help="Write generated files to OUTPUT_DIR") # op.add_option("-o", "--output-dir", # action="store", dest="output_dir", default=".", type="string", # help="file to load types from") # op.add_option("-s", "--simple-naming", # action="store_true", dest="simple_naming", default=False, # help="Simplify generated naming.") # # if args is None: # (options, args) = op.parse_args() # else: # (options, args) = op.parse_args(args) # # if len(args) != 1: # print>>sys.stderr, 'Expecting a file/url as argument (WSDL).' # sys.exit(os.EX_USAGE) # # reader = WSDLTools.WSDLReader() # if isfile(args[0]): # _wsdl2dispatch(options, reader.loadFromFile(args[0])) # return # # _wsdl2dispatch(options, reader.loadFromURL(args[0])) def _wsdl2py(options, wsdl): if options.twisted: from ZSI.generate.containers import ServiceHeaderContainer try: ServiceHeaderContainer.imports.remove('from ZSI import client') except ValueError: pass ServiceHeaderContainer.imports.append('from ZSI.twisted import client') if options.simple_naming: # Use a different client suffix # WriteServiceModule.client_module_suffix = "_client" # Write messages definitions to a separate file. #wsdl2pyServiceDescription.separate_messages = True # Use more simple type and element class names containers.SetTypeNameFunc( lambda n: '%s_' %(NC_to_CN(n)) ) containers.SetElementNameFunc( lambda n: '%s' %(NC_to_CN(n)) ) # Don't add "_" to the attribute name (remove when --aname works well) containers.ContainerBase.func_aname = lambda instnc,n: TextProtect(str(n)) # write out the modules with their names rather than their number. utility.namespace_name = lambda cls, ns: utility.Namespace2ModuleName(ns) files = [] append = files.append if isinstance(wsdl, XMLSchema.XMLSchema): wsm = WriteServiceModule(_XMLSchemaAdapter(wsdl.location, wsdl), addressing=options.address) else: wsm = WriteServiceModule(wsdl, addressing=options.address) client_mod = wsm.getClientModuleName() client_file = join(options.output_dir, '%s.py' %client_mod) append(client_file) fd = open(client_file, 'w+') wsm.writeClient(fd) fd.close() types_mod = wsm.getTypesModuleName() types_file = join(options.output_dir, '%s.py' %types_mod) append(types_file) fd = open(types_file, 'w+' ) wsm.writeTypes(fd) fd.close() return files def _wsdl2dispatch(options, wsdl): """TOOD: Remove ServiceContainer stuff, and replace with WSGI. """ kw = dict() if options.twisted: from ZSI.twisted.WSresource import WSResource kw['base'] = WSResource ss = ServiceDescription(**kw) if options.address is True: raise RuntimeError, 'WS-Address w/twisted currently unsupported, edit the "factory" attribute by hand' else: # TODO: make all this handler arch if options.address is True: ss = ServiceDescriptionWSA() else: ss = ServiceDescription(**kw) ss.fromWSDL(wsdl) file_name = ss.getServiceModuleName()+'.py' fd = open( join(options.output_dir, file_name), 'w+') ss.write(fd) fd.close() return file_name class _XMLSchemaAdapter: """Adapts an obj XMLSchema.XMLSchema to look like a WSDLTools.WSDL, just setting a couple attributes code expects to see. """ def __init__(self, location, schema): """Parameters: location -- base location, file path schema -- XMLSchema instance """ self.name = '_'.join(split(location)[-1].split('.')) self.types = {schema.targetNamespace:schema} import os, pydoc, sys, warnings, inspect import os.path from distutils import log from distutils.command.build_py import build_py from distutils.util import convert_path #from setuptools import find_packages #from setuptools import Command from ZSI.schema import ElementDeclaration, TypeDefinition #from pyGridWare.utility.generate.Modules import NR #from pyGridWare.utility.generate.Modules import CLIENT, TYPES #def find_packages_modules(where='.'): # #pack,mod,mod_file # """Return a list all Python packages found within directory 'where' # """ # out = [] # stack=[(convert_path(where), '')] # while stack: # where,prefix = stack.pop(0) # for name in os.listdir(where): # fn = os.path.join(where,name) # #if (os.path.isdir(fn) and # # os.path.isfile(os.path.join(fn,'__init__.py')) # #): # # out.append(prefix+name); stack.append((fn,prefix+name+'.')) # if (os.path.isdir(fn) and # os.path.isfile(os.path.join(fn,'__init__.py'))): # stack.append((fn,prefix+name+'.')) # continue # # if name == '__init__.py' or not name.endswith('.py'): # continue # # out.append((prefix, name.split('.py')[0])) # # return out def _writedoc(doc, thing, forceload=0): """Write HTML documentation to a file in the current directory. """ try: object, name = pydoc.resolve(thing, forceload) page = pydoc.html.page(pydoc.describe(object), pydoc.html.document(object, name)) fname = os.path.join(doc, name + '.html') file = open(fname, 'w') file.write(page) file.close() except (ImportError, pydoc.ErrorDuringImport), value: traceback.print_exc(sys.stderr) else: return name + '.html' def _writeclientdoc(doc, thing, forceload=0): """Write HTML documentation to a file in the current directory. """ docmodule = pydoc.HTMLDoc.docmodule def strongarm(self, object, name=None, mod=None, *ignored): result = docmodule(self, object, name, mod, *ignored) # Grab all the aliases to pyclasses and create links. nonmembers = [] push = nonmembers.append for k,v in inspect.getmembers(object, inspect.isclass): if inspect.getmodule(v) is not object and getattr(v,'typecode',None) is not None: push('%s: pyclass alias
' %(v.__name__,k)) result += self.bigsection('Aliases', '#ffffff', '#eeaa77', ''.join(nonmembers)) return result pydoc.HTMLDoc.docmodule = strongarm try: object, name = pydoc.resolve(thing, forceload) page = pydoc.html.page(pydoc.describe(object), pydoc.html.document(object, name)) name = os.path.join(doc, name + '.html') file = open(name, 'w') file.write(page) file.close() except (ImportError, pydoc.ErrorDuringImport), value: log.debug(str(value)) pydoc.HTMLDoc.docmodule = docmodule def _writetypesdoc(doc, thing, forceload=0): """Write HTML documentation to a file in the current directory. """ try: object, name = pydoc.resolve(thing, forceload) name = os.path.join(doc, name + '.html') except (ImportError, pydoc.ErrorDuringImport), value: log.debug(str(value)) return # inner classes cdict = {} fdict = {} elements_dict = {} types_dict = {} for kname,klass in inspect.getmembers(thing, inspect.isclass): if thing is not inspect.getmodule(klass): continue cdict[kname] = inspect.getmembers(klass, inspect.isclass) for iname,iklass in cdict[kname]: key = (kname,iname) fdict[key] = _writedoc(doc, iklass) if issubclass(iklass, ElementDeclaration): try: typecode = iklass() except (AttributeError,RuntimeError), ex: elements_dict[iname] = _writebrokedoc(doc, ex, iname) continue elements_dict[iname] = None if typecode.pyclass is not None: elements_dict[iname] = _writedoc(doc, typecode.pyclass) continue if issubclass(iklass, TypeDefinition): try: typecode = iklass(None) except (AttributeError,RuntimeError), ex: types_dict[iname] = _writebrokedoc(doc, ex, iname) continue types_dict[iname] = None if typecode.pyclass is not None: types_dict[iname] = _writedoc(doc, typecode.pyclass) continue def strongarm(self, object, name=None, mod=None, funcs={}, classes={}, *ignored): """Produce HTML documentation for a class object.""" realname = object.__name__ name = name or realname bases = object.__bases__ object, name = pydoc.resolve(object, forceload) contents = [] push = contents.append if name == realname: title = 'class %s' % ( name, realname) else: title = '%s = class %s' % ( name, name, realname) mdict = {} if bases: parents = [] for base in bases: parents.append(self.classlink(base, object.__module__)) title = title + '(%s)' % pydoc.join(parents, ', ') doc = self.markup(pydoc.getdoc(object), self.preformat, funcs, classes, mdict) doc = doc and '%s
 
' % doc for iname,iclass in cdict[name]: fname = fdict[(name,iname)] if elements_dict.has_key(iname): push('class %s: element declaration typecode
'\ %(fname,iname)) pyclass = elements_dict[iname] if pyclass is not None: push('
    instance attributes:') push('
  • pyclass: instances serializable to XML
  • '\ %elements_dict[iname]) push('
') elif types_dict.has_key(iname): push('class %s: type definition typecode
' %(fname,iname)) pyclass = types_dict[iname] if pyclass is not None: push('
    instance attributes:') push('
  • pyclass: instances serializable to XML
  • '\ %types_dict[iname]) push('
') else: push('class %s: TODO not sure what this is
' %(fname,iname)) contents = ''.join(contents) return self.section(title, '#000000', '#ffc8d8', contents, 3, doc) doclass = pydoc.HTMLDoc.docclass pydoc.HTMLDoc.docclass = strongarm try: page = pydoc.html.page(pydoc.describe(object), pydoc.html.document(object, name)) file = open(name, 'w') file.write(page) file.close() except (ImportError, pydoc.ErrorDuringImport), value: log.debug(str(value)) pydoc.HTMLDoc.docclass = doclass def _writebrokedoc(doc, ex, name, forceload=0): try: fname = os.path.join(doc, name + '.html') page = pydoc.html.page(pydoc.describe(ex), pydoc.html.document(str(ex), fname)) file = open(fname, 'w') file.write(page) file.close() except (ImportError, pydoc.ErrorDuringImport), value: log.debug(str(value)) return name + '.html' def _writepydoc(doc, *args): """create pydoc html pages doc -- destination directory for documents *args -- modules run thru pydoc """ ok = True if not os.path.isdir(doc): os.makedirs(doc) if os.path.curdir not in sys.path: sys.path.append(os.path.curdir) for f in args: if f.startswith('./'): f = f[2:] name = os.path.sep.join(f.strip('.py').split(os.path.sep)) try: e = __import__(name) except Exception,ex: raise # _writebrokedoc(doc, ex, name) # continue if name.endswith('_client'): _writeclientdoc(doc, e) continue if name.endswith('_types'): _writetypesdoc(doc, e) continue try: _writedoc(doc, e) except IndexError,ex: _writebrokedoc(doc, ex, name) continue ZSI-2.1-a1/ZSI/generate/wsdl2dispatch.py0000755000175100017510000003673210656174245016132 0ustar zsizsi#!/usr/bin/env python import inspect from cStringIO import StringIO import ZSI, string, sys, getopt, urlparse, types, warnings from ZSI.wstools import WSDLTools from ZSI.ServiceContainer import ServiceSOAPBinding, SimpleWSResource, WSAResource from ZSI.generate import WsdlGeneratorError, Wsdl2PythonError from utility import TextProtect, GetModuleBaseNameFromWSDL, \ NCName_to_ClassName, GetPartsSubNames, TextProtectAttributeName from containers import BindingDescription from wsdl2python import MessageWriter, WriteServiceModule,\ MessageTypecodeContainer, SchemaDescription # Split last token rsplit = lambda x,sep,: (x[:x.rfind(sep)], x[x.rfind(sep)+1:],) if sys.version_info[0:2] == (2, 4, 0, 'final', 0)[0:2]: rsplit = lambda x,sep,: x.rsplit(sep, 1) class SOAPService: def __init__(self, service): self.classdef = StringIO() self.initdef = StringIO() self.location = '' self.methods = [] def newMethod(self): '''name -- operation name ''' self.methods.append(StringIO()) return self.methods[-1] class ServiceModuleWriter: '''Creates a skeleton for a SOAP service instance. ''' indent = ' '*4 server_module_suffix = '_server' func_aname = TextProtectAttributeName func_aname = staticmethod(func_aname) separate_messages = False def __init__(self, base=ServiceSOAPBinding, prefix='soap', service_class=SOAPService): ''' parameters: base -- either a class definition, or a str representing a qualified class name (eg. module.name.classname) prefix -- method prefix. ''' if inspect.isclass(base): self.base_class_name = base.__name__ self.base_module_name = inspect.getmodule(base).__name__ else: self.base_module_name, self.base_class_name = base.rsplit('.', 1) self.wsdl = None self.method_prefix = prefix self._service_class = SOAPService self.header = None self.imports = None self.messages = [] self._services = None self.types_module_path = None self.types_module_name = None self.messages_module_name = None def reset(self): self.header = StringIO() self.imports = StringIO() self.message = [] self._services = {} def getIndent(self, level=1): '''return indent. ''' assert 0 < level < 10, 'bad indent level %d' %level return self.indent*level def getMethodName(self, method): '''return method name. ''' return '%s_%s' %(self.method_prefix, TextProtect(method)) def getClassName(self, name): '''return class name. ''' return NCName_to_ClassName(name) def setTypesModuleName(self, name): self.types_module_name = name # Backwards compatibility setClientModuleName = setTypesModuleName def getTypesModuleName(self): '''return module name. ''' assert self.wsdl is not None, 'initialize, call fromWSDL' if self.types_module_name is not None: return self.types_module_name wsm = WriteServiceModule(self.wsdl) return wsm.getTypesModuleName() def getServiceModuleName(self): '''return module name. ''' name = GetModuleBaseNameFromWSDL(self.wsdl) if not name: raise WsdlGeneratorError, 'could not determine a service name' if self.server_module_suffix is None: return name return '%s%s' %(name, self.server_module_suffix) def getTypesModulePath(self): return self.types_module_path getClientModulePath = getTypesModulePath def setTypesModulePath(self, path): '''setup module path to where client module before calling fromWSDL. ''' self.types_module_path = path setClientModulePath = setTypesModulePath def setUpClassDef(self, service): '''set class definition and class variables. service -- ServiceDescription instance ''' assert isinstance(service, WSDLTools.Service) is True,\ 'expecting WSDLTools.Service instance.' s = self._services[service.name].classdef print >>s, 'class %s(%s):' %(self.getClassName(service.name), self.base_class_name) print >>s, '%ssoapAction = {}' % self.getIndent(level=1) print >>s, '%sroot = {}' % self.getIndent(level=1) def setUpImports(self): '''set import statements ''' i = self.imports print >>i, 'from ZSI.schema import GED, GTD' print >>i, 'from ZSI.TCcompound import ComplexType, Struct' module = self.getTypesModuleName() package = self.getTypesModulePath() if package: module = '%s.%s' %(package, module) print >>i, 'from %s import *' %(module) print >>i, 'from %s import %s' %(self.base_module_name, self.base_class_name) def setUpInitDef(self, service): '''set __init__ function ''' assert isinstance(service, WSDLTools.Service), \ 'expecting WSDLTools.Service instance.' sd = self._services[service.name] d = sd.initdef if sd.location is not None: scheme,netloc,path,params,query,fragment = urlparse.urlparse(sd.location) print >>d, '%sdef __init__(self, post=\'%s\', **kw):' %(self.getIndent(level=1), path) else: print >>d, '%sdef __init__(self, post, **kw):' %self.getIndent(level=1) # Require POST initialization value for test implementation if self.base_module_name == inspect.getmodule(ServiceSOAPBinding).__name__: print >>d, '%s%s.__init__(self, post)' %(self.getIndent(level=2), self.base_class_name) return # No POST initialization value, obtained from HTTP Request in twisted or wsgi print >>d, '%s%s.__init__(self)' %(self.getIndent(level=2), self.base_class_name) def mangle(self, name): return TextProtect(name) def getAttributeName(self, name): return self.func_aname(name) def setUpMethods(self, port): '''set up all methods representing the port operations. Parameters: port -- Port that defines the operations. ''' assert isinstance(port, WSDLTools.Port), \ 'expecting WSDLTools.Port not: ' %type(port) sd = self._services.get(port.getService().name) assert sd is not None, 'failed to initialize.' binding = port.getBinding() portType = port.getPortType() action_in = '' for bop in binding.operations: try: op = portType.operations[bop.name] except KeyError, ex: raise WsdlGeneratorError,\ 'Port(%s) PortType(%s) missing operation(%s) defined in Binding(%s)' \ %(port.name,portType.name,bop.name,binding.name) for ext in bop.extensions: if isinstance(ext, WSDLTools.SoapOperationBinding): action_in = ext.soapAction break else: warnings.warn('Port(%s) operation(%s) defined in Binding(%s) missing soapAction' \ %(port.name,op.name,binding.name) ) msgin = op.getInputMessage() msgin_name = TextProtect(msgin.name) method_name = self.getMethodName(op.name) m = sd.newMethod() print >>m, '%sdef %s(self, ps, **kw):' %(self.getIndent(level=1), method_name) if msgin is not None: print >>m, '%srequest = ps.Parse(%s.typecode)' %(self.getIndent(level=2), msgin_name) else: print >>m, '%s# NO input' %self.getIndent(level=2) msgout = op.getOutputMessage() if msgout is not None: msgout_name = TextProtect(msgout.name) print >>m, '%sreturn request,%s()' %(self.getIndent(level=2), msgout_name) else: print >>m, '%s# NO output' % self.getIndent(level=2) print >>m, '%sreturn request,None' % self.getIndent(level=2) print >>m, '' print >>m, '%ssoapAction[\'%s\'] = \'%s\'' %(self.getIndent(level=1), action_in, method_name) print >>m, '%sroot[(%s.typecode.nspname,%s.typecode.pname)] = \'%s\'' \ %(self.getIndent(level=1), msgin_name, msgin_name, method_name) return def setUpHeader(self): print >>self.header, '#'*50 print >>self.header, '# file: %s.py' %self.getServiceModuleName() print >>self.header, '#' print >>self.header, '# skeleton generated by "%s"' %self.__class__ print >>self.header, '# %s' %' '.join(sys.argv) print >>self.header, '#' print >>self.header, '#'*50 def write(self, fd=sys.stdout): '''write out to file descriptor, should not need to override. ''' print >>fd, self.header.getvalue() print >>fd, self.imports.getvalue() print >>fd, '# Messages ', for m in self.messages: print >>fd, m print >>fd, '' print >>fd, '' print >>fd, '# Service Skeletons' for k,v in self._services.items(): print >>fd, v.classdef.getvalue() print >>fd, v.initdef.getvalue() for s in v.methods: print >>fd, s.getvalue() def fromWSDL(self, wsdl): '''setup the service description from WSDL, should not need to override. ''' assert isinstance(wsdl, WSDLTools.WSDL), 'expecting WSDL instance' if len(wsdl.services) == 0: raise WsdlGeneratorError, 'No service defined' self.reset() self.wsdl = wsdl self.setUpHeader() self.setUpImports() for service in wsdl.services: sd = self._service_class(service.name) self._services[service.name] = sd for port in service.ports: desc = BindingDescription(wsdl=wsdl) try: desc.setUp(port.getBinding()) except Wsdl2PythonError, ex: continue for soc in desc.operations: if not soc.hasInput(): continue self.messages.append(MessageWriter()) self.messages[-1].setUp(soc, port, input=True) if soc.hasOutput(): self.messages.append(MessageWriter()) self.messages[-1].setUp(soc, port, input=False) for e in port.extensions: if isinstance(e, WSDLTools.SoapAddressBinding): sd.location = e.location self.setUpMethods(port) self.setUpClassDef(service) self.setUpInitDef(service) class WSAServiceModuleWriter(ServiceModuleWriter): '''Creates a skeleton for a WS-Address service instance. ''' def __init__(self, base=WSAResource, prefix='wsa', service_class=SOAPService, strict=True): ''' Parameters: strict -- check that soapAction and input ws-action do not collide. ''' ServiceModuleWriter.__init__(self, base, prefix, service_class) self.strict = strict def createMethodBody(msgInName, msgOutName, **kw): '''return a tuple of strings containing the body of a method. msgInName -- None or a str msgOutName -- None or a str ''' body = [] if msgInName is not None: body.append('request = ps.Parse(%s.typecode)' %msgInName) if msgOutName is not None: body.append('return request,%s()' %msgOutName) else: body.append('return request,None') return tuple(body) createMethodBody = staticmethod(createMethodBody) def setUpClassDef(self, service): '''use soapAction dict for WS-Action input, setup wsAction dict for grabbing WS-Action output values. ''' assert isinstance(service, WSDLTools.Service), \ 'expecting WSDLTools.Service instance' s = self._services[service.name].classdef print >>s, 'class %s(%s):' %(self.getClassName(service.name), self.base_class_name) print >>s, '%ssoapAction = {}' % self.getIndent(level=1) print >>s, '%swsAction = {}' % self.getIndent(level=1) print >>s, '%sroot = {}' % self.getIndent(level=1) def setUpMethods(self, port): '''set up all methods representing the port operations. Parameters: port -- Port that defines the operations. ''' assert isinstance(port, WSDLTools.Port), \ 'expecting WSDLTools.Port not: ' %type(port) binding = port.getBinding() portType = port.getPortType() service = port.getService() s = self._services[service.name] for bop in binding.operations: try: op = portType.operations[bop.name] except KeyError, ex: raise WsdlGeneratorError,\ 'Port(%s) PortType(%s) missing operation(%s) defined in Binding(%s)' \ %(port.name, portType.name, op.name, binding.name) soap_action = wsaction_in = wsaction_out = None if op.input is not None: wsaction_in = op.getInputAction() if op.output is not None: wsaction_out = op.getOutputAction() for ext in bop.extensions: if isinstance(ext, WSDLTools.SoapOperationBinding) is False: continue soap_action = ext.soapAction if not soap_action: break if wsaction_in is None: break if wsaction_in == soap_action: break if self.strict is False: warnings.warn(\ 'Port(%s) operation(%s) in Binding(%s) soapAction(%s) != WS-Action(%s)' \ %(port.name, op.name, binding.name, soap_action, wsaction_in), ) break raise WsdlGeneratorError,\ 'Port(%s) operation(%s) in Binding(%s) soapAction(%s) MUST match WS-Action(%s)' \ %(port.name, op.name, binding.name, soap_action, wsaction_in) method_name = self.getMethodName(op.name) m = s.newMethod() print >>m, '%sdef %s(self, ps, address):' %(self.getIndent(level=1), method_name) msgin_name = msgout_name = None msgin,msgout = op.getInputMessage(),op.getOutputMessage() if msgin is not None: msgin_name = TextProtect(msgin.name) if msgout is not None: msgout_name = TextProtect(msgout.name) indent = self.getIndent(level=2) for l in self.createMethodBody(msgin_name, msgout_name): print >>m, indent + l print >>m, '' print >>m, '%ssoapAction[\'%s\'] = \'%s\'' %(self.getIndent(level=1), wsaction_in, method_name) print >>m, '%swsAction[\'%s\'] = \'%s\'' %(self.getIndent(level=1), method_name, wsaction_out) print >>m, '%sroot[(%s.typecode.nspname,%s.typecode.pname)] = \'%s\'' \ %(self.getIndent(level=1), msgin_name, msgin_name, method_name) ZSI-2.1-a1/ZSI/generate/pyclass.py0000644000175100017510000002471310513030247015007 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import pydoc, sys, warnings from ZSI import TC # If function.__name__ is read-only, fail def _x(): return try: _x.func_name = '_y' except: raise RuntimeError,\ 'use python-2.4 or later, cannot set function names in python "%s"'\ %sys.version del _x #def GetNil(typecode=None): # """returns the nilled element, use to set an element # as nilled for immutable instance. # """ # # nil = TC.Nilled() # if typecode is not None: nil.typecode = typecode # return nil # # #def GetNilAsSelf(cls, typecode=None): # """returns the nilled element with typecode specified, # use returned instance to set this element as nilled. # # Key Word Parameters: # typecode -- use to specify a derived type or wildcard as nilled. # """ # if typecode is not None and not isinstance(typecode, TC.TypeCode): # raise TypeError, "Expecting a TypeCode instance" # # nil = TC.Nilled() # nil.typecode = typecode or cls.typecode # return nil class pyclass_type(type): """Stability: Unstable type for pyclasses used with typecodes. expects the typecode to be available in the classdict. creates python properties for accessing and setting the elements specified in the ofwhat list, and factory methods for constructing the elements. Known Limitations: 1)Uses XML Schema element names directly to create method names, using characters in this set will cause Syntax Errors: (NCNAME)-(letter U digit U "_") """ def __new__(cls, classname, bases, classdict): """ """ #import new typecode = classdict.get('typecode') assert typecode is not None, 'MUST HAVE A TYPECODE.' # Assume this means immutable type. ie. str if len(bases) > 0: #classdict['new_Nill'] = classmethod(GetNilAsSelf) pass # Assume this means mutable type. ie. ofwhat. else: assert hasattr(typecode, 'ofwhat'), 'typecode has no ofwhat list??' assert hasattr(typecode, 'attribute_typecode_dict'),\ 'typecode has no attribute_typecode_dict??' #classdict['new_Nill'] = staticmethod(GetNil) if typecode.mixed: get,set = cls.__create_text_functions_from_what(typecode) if classdict.has_key(get.__name__): raise AttributeError,\ 'attribute %s previously defined.' %get.__name__ if classdict.has_key(set.__name__): raise AttributeError,\ 'attribute %s previously defined.' %set.__name__ classdict[get.__name__] = get classdict[set.__name__] = set for what in typecode.ofwhat: get,set,new_func = cls.__create_functions_from_what(what) if classdict.has_key(get.__name__): raise AttributeError,\ 'attribute %s previously defined.' %get.__name__ classdict[get.__name__] = get if classdict.has_key(set.__name__): raise AttributeError,\ 'attribute %s previously defined.' %set.__name__ classdict[set.__name__] = set if new_func is not None: if classdict.has_key(new_func.__name__): raise AttributeError,\ 'attribute %s previously defined.' %new_func.__name__ classdict[new_func.__name__] = new_func assert not classdict.has_key(what.pname),\ 'collision with pname="%s", bail..' %what.pname pname = what.pname if pname is None and isinstance(what, TC.AnyElement): pname = 'any' assert pname is not None, 'Element with no name: %s' %what # TODO: for pname if keyword just uppercase first letter. #if pydoc.Helper.keywords.has_key(pname): pname = pname[0].upper() + pname[1:] assert not pydoc.Helper.keywords.has_key(pname), 'unexpected keyword: %s' %pname classdict[pname] =\ property(get, set, None, 'property for element (%s,%s), minOccurs="%s" maxOccurs="%s" nillable="%s"'\ %(what.nspname,what.pname,what.minOccurs,what.maxOccurs,what.nillable) ) # # mutable type complexContent | modelGroup # or immutable type simpleContent (float, str, etc) # if hasattr(typecode, 'attribute_typecode_dict'): attribute_typecode_dict = typecode.attribute_typecode_dict or {} for key,what in attribute_typecode_dict.items(): get,set = cls.__create_attr_functions_from_what(key, what) if classdict.has_key(get.__name__): raise AttributeError,\ 'attribute %s previously defined.' %get.__name__ if classdict.has_key(set.__name__): raise AttributeError,\ 'attribute %s previously defined.' %set.__name__ classdict[get.__name__] = get classdict[set.__name__] = set return type.__new__(cls,classname,bases,classdict) def __create_functions_from_what(what): if not callable(what): def get(self): return getattr(self, what.aname) if what.maxOccurs > 1: def set(self, value): if not (value is None or hasattr(value, '__iter__')): raise TypeError, 'expecting an iterable instance' setattr(self, what.aname, value) else: def set(self, value): setattr(self, what.aname, value) else: def get(self): return getattr(self, what().aname) if what.maxOccurs > 1: def set(self, value): if not (value is None or hasattr(value, '__iter__')): raise TypeError, 'expecting an iterable instance' setattr(self, what().aname, value) else: def set(self, value): setattr(self, what().aname, value) # # new factory function # if pyclass is None, skip # if not callable(what) and getattr(what, 'pyclass', None) is None: new_func = None elif (isinstance(what, TC.ComplexType) or isinstance(what, TC.Array)): def new_func(self): '''returns a mutable type ''' return what.pyclass() elif not callable(what): def new_func(self, value): '''value -- initialize value returns an immutable type ''' return what.pyclass(value) elif (issubclass(what.klass, TC.ComplexType) or issubclass(what.klass, TC.Array)): def new_func(self): '''returns a mutable type or None (if no pyclass). ''' p = what().pyclass if p is None: return return p() else: def new_func(self, value=None): '''if simpleType provide initialization value, else if complexType value should be left as None. Parameters: value -- initialize value or None returns a mutable instance (value is None) or an immutable instance or None (if no pyclass) ''' p = what().pyclass if p is None: return if value is None: return p() return p(value) #TODO: sub all illegal characters in set # (NCNAME)-(letter U digit U "_") if new_func is not None: new_func.__name__ = 'new_%s' %what.pname get.func_name = 'get_element_%s' %what.pname set.func_name = 'set_element_%s' %what.pname return get,set,new_func __create_functions_from_what = staticmethod(__create_functions_from_what) def __create_attr_functions_from_what(key, what): def get(self): '''returns attribute value for attribute %s, else None. ''' %str(key) return getattr(self, what.attrs_aname, {}).get(key, None) def set(self, value): '''set value for attribute %s. value -- initialize value, immutable type ''' %str(key) if not hasattr(self, what.attrs_aname): setattr(self, what.attrs_aname, {}) getattr(self, what.attrs_aname)[key] = value #TODO: sub all illegal characters in set # (NCNAME)-(letter U digit U "_") if type(key) in (tuple, list): get.__name__ = 'get_attribute_%s' %key[1] set.__name__ = 'set_attribute_%s' %key[1] else: get.__name__ = 'get_attribute_%s' %key set.__name__ = 'set_attribute_%s' %key return get,set __create_attr_functions_from_what = \ staticmethod(__create_attr_functions_from_what) def __create_text_functions_from_what(what): def get(self): '''returns text content, else None. ''' return getattr(self, what.mixed_aname, None) get.im_func = 'get_text' def set(self, value): '''set text content. value -- initialize value, immutable type ''' setattr(self, what.mixed_aname, value) get.im_func = 'set_text' return get,set __create_text_functions_from_what = \ staticmethod(__create_text_functions_from_what) ZSI-2.1-a1/ZSI/generate/wsdl2python.py0000644000175100017510000004707610643543564015654 0ustar zsizsi############################################################################ # Monte M. Goode, LBNL # See LBNLCopyright for copyright notice! ########################################################################### # main generator engine for new generation generator # $Id: wsdl2python.py 1402 2007-07-06 22:51:32Z boverhof $ import os, sys, warnings from ZSI import _get_idstr from ZSI.wstools.logging import getLogger as _GetLogger from ZSI.wstools import WSDLTools from ZSI.wstools.WSDLTools import SoapAddressBinding,\ SoapBodyBinding, SoapBinding,MimeContentBinding,\ HttpUrlEncodedBinding from ZSI.wstools.XMLSchema import SchemaReader, ElementDeclaration, SchemaError from ZSI.typeinterpreter import BaseTypeInterpreter from ZSI.generate import WsdlGeneratorError, Wsdl2PythonError from containers import * from ZSI.generate import utility from ZSI.generate.utility import NamespaceAliasDict as NAD from ZSI.generate.utility import GetModuleBaseNameFromWSDL """ classes: WriteServiceModule -- composes/writes out client stubs and types module. ServiceDescription -- represents a single WSDL service. MessageWriter -- represents a single WSDL Message and associated bindings of the port/binding. SchemaDescription -- generates classes for defs and decs in the schema instance. TypeWriter -- represents a type definition. ElementWriter -- represents a element declaration. """ class WriteServiceModule: """top level driver class invoked by wsd2py class variables: client_module_suffix -- suffix of client module. types_module_suffix -- suffix of types module. """ client_module_suffix = '_client' messages_module_suffix = '_messages' types_module_suffix = '_types' logger = _GetLogger("WriteServiceModule") def __init__(self, wsdl, addressing=False, notification=False, do_extended=False, extPyClasses=None, configParser = None): self._wsdl = wsdl self._addressing = addressing self._notification = notification self._configParser = configParser self.usedNamespaces = None self.services = [] self.client_module_path = None self.types_module_name = None self.types_module_path = None self.messages_module_path = None # used in extended generation self.do_extended = do_extended self.extPyClasses = extPyClasses def getClientModuleName(self): """client module name. """ name = GetModuleBaseNameFromWSDL(self._wsdl) if not name: raise WsdlGeneratorError, 'could not determine a service name' if self.client_module_suffix is None: return name return '%s%s' %(name, self.client_module_suffix) # def getMessagesModuleName(self): # name = GetModuleBaseNameFromWSDL(self._wsdl) # if not name: # raise WsdlGeneratorError, 'could not determine a service name' # # if self.messages_module_suffix is None: # return name # # if len(self.messages_module_suffix) == 0: # return self.getClientModuleName() # # return '%s%s' %(name, self.messages_module_suffix) def setTypesModuleName(self, name): self.types_module_name = name def getTypesModuleName(self): """types module name. """ if self.types_module_name is not None: return self.types_module_name name = GetModuleBaseNameFromWSDL(self._wsdl) if not name: raise WsdlGeneratorError, 'could not determine a service name' if self.types_module_suffix is None: return name return '%s%s' %(name, self.types_module_suffix) def setClientModulePath(self, path): """setup module path to where client module before calling fromWsdl. module path to types module eg. MyApp.client """ self.client_module_path = path def getTypesModulePath(self): """module path to types module eg. MyApp.types """ return self.types_module_path # def getMessagesModulePath(self): # '''module path to messages module # same as types path # ''' # return self.messages_module_path def setTypesModulePath(self, path): """setup module path to where service module before calling fromWsdl. module path to types module eg. MyApp.types """ self.types_module_path = path # def setMessagesModulePath(self, path): # """setup module path to where message module before calling fromWsdl. # module path to types module eg. MyApp.types # """ # self.messages_module_path = path def gatherNamespaces(self): '''This method must execute once.. Grab all schemas representing each targetNamespace. ''' if self.usedNamespaces is not None: return self.logger.debug('gatherNamespaces') self.usedNamespaces = {} # Add all schemas defined in wsdl # to used namespace and to the Alias dict for schema in self._wsdl.types.values(): tns = schema.getTargetNamespace() self.logger.debug('Register schema(%s) -- TNS(%s)'\ %(_get_idstr(schema), tns),) if self.usedNamespaces.has_key(tns) is False: self.usedNamespaces[tns] = [] self.usedNamespaces[tns].append(schema) NAD.add(tns) # Add all xsd:import schema instances # to used namespace and to the Alias dict for k,v in SchemaReader.namespaceToSchema.items(): self.logger.debug('Register schema(%s) -- TNS(%s)'\ %(_get_idstr(v), k),) if self.usedNamespaces.has_key(k) is False: self.usedNamespaces[k] = [] self.usedNamespaces[k].append(v) NAD.add(k) def writeClient(self, fd, sdClass=None, **kw): """write out client module to file descriptor. Parameters and Keywords arguments: fd -- file descriptor sdClass -- service description class name imports -- list of imports readerclass -- class name of ParsedSoap reader writerclass -- class name of SoapWriter writer """ sdClass = sdClass or ServiceDescription assert issubclass(sdClass, ServiceDescription), \ 'parameter sdClass must subclass ServiceDescription' # header = '%s \n# %s.py \n# generated by %s\n%s\n'\ # %('#'*50, self.getClientModuleName(), self.__module__, '#'*50) print >>fd, '#'*50 print >>fd, '# file: %s.py' %self.getClientModuleName() print >>fd, '# ' print >>fd, '# client stubs generated by "%s"' %self.__class__ print >>fd, '# %s' %' '.join(sys.argv) print >>fd, '# ' print >>fd, '#'*50 self.services = [] for service in self._wsdl.services: sd = sdClass(self._addressing, do_extended=self.do_extended, wsdl=self._wsdl) if len(self._wsdl.types) > 0: sd.setTypesModuleName(self.getTypesModuleName(), self.getTypesModulePath()) # sd.setMessagesModuleName(self.getMessagesModuleName(), # self.getMessagesModulePath()) self.gatherNamespaces() sd.fromWsdl(service, **kw) sd.write(fd) self.services.append(sd) def writeTypes(self, fd): """write out types module to file descriptor. """ print >>fd, '#'*50 print >>fd, '# file: %s.py' %self.getTypesModuleName() print >>fd, '#' print >>fd, '# schema types generated by "%s"' %self.__class__ print >>fd, '# %s' %' '.join(sys.argv) print >>fd, '#' print >>fd, '#'*50 print >>fd, TypesHeaderContainer() self.gatherNamespaces() for l in self.usedNamespaces.values(): sd = SchemaDescription(do_extended=self.do_extended, extPyClasses=self.extPyClasses) for schema in l: sd.fromSchema(schema) sd.write(fd) class ServiceDescription: """client interface - locator, port, etc classes""" separate_messages = False logger = _GetLogger("ServiceDescription") def __init__(self, addressing=False, do_extended=False, wsdl=None): self.typesModuleName = None self.messagesModuleName = None self.wsAddressing = addressing self.imports = ServiceHeaderContainer() self.messagesImports = ServiceHeaderContainer() self.locator = ServiceLocatorContainer() self.bindings = [] self.messages = [] self.do_extended=do_extended self._wsdl = wsdl # None unless do_extended == True def setTypesModuleName(self, name, modulePath=None): """The types module to be imported. Parameters name -- name of types module modulePath -- optional path where module is located. """ self.typesModuleName = '%s' %name if modulePath is not None: self.typesModuleName = '%s.%s' %(modulePath,name) # def setMessagesModuleName(self, name, modulePath=None): # '''The types module to be imported. # Parameters # name -- name of types module # modulePath -- optional path where module is located. # ''' # self.messagesModuleName = '%s' %name # if modulePath is not None: # self.messagesModuleName = '%s.%s' %(modulePath,name) def fromWsdl(self, service, **kw): self.imports.setTypesModuleName(self.typesModuleName) # if self.separate_messages: # self.messagesImports.setMessagesModuleName(self.messagesModuleName) self.imports.appendImport(kw.get('imports', [])) self.locator.setUp(service) try: bindings = map(lambda p: p.binding, service.ports) except: warnings.warn('not all ports have binding declared,') bindings = () for port in service.ports: if port.binding not in bindings: continue while port.binding in bindings: bindings.remove(port.binding) desc = BindingDescription(useWSA=self.wsAddressing, do_extended=self.do_extended, wsdl=self._wsdl) try: desc.setUp(port.getBinding()) except Wsdl2PythonError, ex: self.logger.warning('Skipping port(%s)' %port.name) if len(ex.args): self.logger.warning(ex.args[0]) continue desc.setReaderClass(kw.get('readerclass')) desc.setWriterClass(kw.get('writerclass')) for soc in desc.operations: if soc.hasInput() is True: mw = MessageWriter(do_extended=self.do_extended) mw.setUp(soc, port, input=True) self.messages.append(mw) if soc.hasOutput() is True: mw = MessageWriter(do_extended=self.do_extended) mw.setUp(soc, port, input=False) self.messages.append(mw) self.bindings.append(desc) def write(self, fd, msg_fd=None): """write out module to file descriptor. fd -- file descriptor to write out service description. msg_fd -- optional file descriptor for messages module. """ # if msg_fd != None: # print >>fd, self.messagesImports # print >>msg_fd, self.imports # else: print >>fd, self.imports print >>fd, self.locator for m in self.bindings: print >>fd, m # if msg_fd != None: # for m in self.messages: # print >>msg_fd, m # else: for m in self.messages: print >>fd, m class MessageWriter: logger = _GetLogger("MessageWriter") def __init__(self, do_extended=False): """Representation of a WSDL Message and associated WSDL Binding. operation -- boperation -- input -- rpc -- literal -- simple -- """ self.content = None self.do_extended = do_extended def __str__(self): if not self.content: raise Wsdl2PythonError, 'Must call setUp.' return self.content.getvalue() def setUp(self, soc, port, input=False): assert isinstance(soc, ServiceOperationContainer),\ 'expecting a ServiceOperationContainer instance' assert isinstance(port, WSDLTools.Port),\ 'expecting a WSDL.Port instance' rpc,literal = soc.isRPC(), soc.isLiteral(input) kw,klass = {}, None if rpc and literal: klass = ServiceRPCLiteralMessageContainer elif not rpc and literal: kw['do_extended'] = self.do_extended klass = ServiceDocumentLiteralMessageContainer elif rpc and not literal: klass = ServiceRPCEncodedMessageContainer else: raise WsdlGeneratorError, 'doc/enc not supported.' self.content = klass(**kw) self.content.setUp(port, soc, input) class SchemaDescription: """generates classes for defs and decs in the schema instance. """ logger = _GetLogger("SchemaDescription") def __init__(self, do_extended=False, extPyClasses=None): self.classHead = NamespaceClassHeaderContainer() self.classFoot = NamespaceClassFooterContainer() self.items = [] self.__types = [] self.__elements = [] self.targetNamespace = None self.do_extended=do_extended self.extPyClasses = extPyClasses def fromSchema(self, schema): ''' Can be called multiple times, but will not redefine a previously defined type definition or element declaration. ''' ns = schema.getTargetNamespace() assert self.targetNamespace is None or self.targetNamespace == ns,\ 'SchemaDescription instance represents %s, not %s'\ %(self.targetNamespace, ns) if self.targetNamespace is None: self.targetNamespace = ns self.classHead.ns = self.classFoot.ns = ns for item in [t for t in schema.types if t.getAttributeName() not in self.__types]: self.__types.append(item.getAttributeName()) self.items.append(TypeWriter(do_extended=self.do_extended, extPyClasses=self.extPyClasses)) self.items[-1].fromSchemaItem(item) for item in [e for e in schema.elements if e.getAttributeName() not in self.__elements]: self.__elements.append(item.getAttributeName()) self.items.append(ElementWriter(do_extended=self.do_extended)) self.items[-1].fromSchemaItem(item) def getTypes(self): return self.__types def getElements(self): return self.__elements def write(self, fd): """write out to file descriptor. """ print >>fd, self.classHead for t in self.items: print >>fd, t print >>fd, self.classFoot class SchemaItemWriter: """contains/generates a single declaration""" logger = _GetLogger("SchemaItemWriter") def __init__(self, do_extended=False, extPyClasses=None): self.content = None self.do_extended=do_extended self.extPyClasses=extPyClasses def __str__(self): '''this appears to set up whatever is in self.content.localElements, local elements simpleType|complexType. ''' assert self.content is not None, 'Must call fromSchemaItem to setup.' return str(self.content) def fromSchemaItem(self, item): raise NotImplementedError, '' class ElementWriter(SchemaItemWriter): """contains/generates a single declaration""" logger = _GetLogger("ElementWriter") def fromSchemaItem(self, item): """set up global elements. """ if item.isElement() is False or item.isLocal() is True: raise TypeError, 'expecting global element declaration: %s' %item.getItemTrace() local = False qName = item.getAttribute('type') if not qName: etp = item.content local = True else: etp = item.getTypeDefinition('type') if etp is None: if local is True: self.content = ElementLocalComplexTypeContainer(do_extended=self.do_extended) else: self.content = ElementSimpleTypeContainer() elif etp.isLocal() is False: self.content = ElementGlobalDefContainer() elif etp.isSimple() is True: self.content = ElementLocalSimpleTypeContainer() elif etp.isComplex(): self.content = ElementLocalComplexTypeContainer(do_extended=self.do_extended) else: raise Wsdl2PythonError, "Unknown element declaration: %s" %item.getItemTrace() self.logger.debug('ElementWriter setUp container "%r", Schema Item "%s"' %( self.content, item.getItemTrace())) self.content.setUp(item) class TypeWriter(SchemaItemWriter): """contains/generates a single definition""" logger = _GetLogger("TypeWriter") def fromSchemaItem(self, item): if item.isDefinition() is False or item.isLocal() is True: raise TypeError, \ 'expecting global type definition not: %s' %item.getItemTrace() self.content = None if item.isSimple(): if item.content.isRestriction(): self.content = RestrictionContainer() elif item.content.isUnion(): self.content = UnionContainer() elif item.content.isList(): self.content = ListContainer() else: raise Wsdl2PythonError,\ 'unknown simple type definition: %s' %item.getItemTrace() self.content.setUp(item) return if item.isComplex(): kw = {} if item.content is None or item.content.isModelGroup(): self.content = \ ComplexTypeContainer(\ do_extended=self.do_extended, extPyClasses=self.extPyClasses ) kw['empty'] = item.content is None elif item.content.isSimple(): self.content = ComplexTypeSimpleContentContainer() elif item.content.isComplex(): self.content = \ ComplexTypeComplexContentContainer(\ do_extended=self.do_extended ) else: raise Wsdl2PythonError,\ 'unknown complex type definition: %s' %item.getItemTrace() self.logger.debug('TypeWriter setUp container "%r", Schema Item "%s"' %( self.content, item.getItemTrace())) try: self.content.setUp(item, **kw) except Exception, ex: args = ['Failure in setUp: %s' %item.getItemTrace()] args += ex.args ex.args = tuple(args) raise return raise TypeError,\ 'expecting SimpleType or ComplexType: %s' %item.getItemTrace() ZSI-2.1-a1/ZSI/generate/utility.py0000644000175100017510000001310010435642307015031 0ustar zsizsi############################################################################ # Monte M. Goode, LBNL # See LBNLCopyright for copyright notice! ########################################################################### # utility classes used by new generator - mostly 'sugar' classes # that are actually imported by the generated code. also includes # utilities used by wsdl2python itself. # $Id: utility.py 1226 2006-05-26 18:11:19Z boverhof $ import re from ZSI import EvaluateException from ZSI.TCcompound import Struct from ZSI.generate import WsdlGeneratorError, Wsdl2PythonError from ZSI.wstools.Utility import SplitQName from ZSI.wstools.Namespaces import SCHEMA NCName_to_ModuleName = lambda name: re.sub('\.', '_', TextProtect(name)) NCName_to_ClassName = lambda name: re.sub('\.', '_', TextProtect(name)) TextProtect = lambda s: re.sub('[-./:# ]', '_', s) TextProtectAttributeName = lambda name: TextProtect('_%s' %name) Namespace2ModuleName = lambda ns: TextProtect(ns.lstrip('http://')).rstrip('_') def GetModuleBaseNameFromWSDL(wsdl): """By default try to construct a reasonable base name for all generated modules. Otherwise return None. """ base_name = wsdl.name or wsdl.services[0].name base_name = SplitQName(base_name)[1] if base_name is None: return None return NCName_to_ModuleName(base_name) namespace_name = lambda cls, ns: 'ns%s' % len(cls.alias_list) class NamespaceAliasDict: """a lookup table to store relevant namespaces and their aliases""" alias_dict = {} alias_list = [] def add(cls, ns): if cls.alias_dict.has_key(ns): return cls.alias_dict[ns] = (Namespace2ModuleName(ns), '%s' % namespace_name(cls,ns)) cls.alias_list.append(ns) add = classmethod(add) def getModuleName(cls, ns): if cls.alias_dict.has_key(ns): return cls.alias_dict[ns][0] msg = 'failed to find import for schema "%s"'%ns +\ 'possibly missing @schemaLocation attribute.' if ns in SCHEMA.XSD_LIST: msg = 'missing built-in typecode for schema "%s"' %ns raise WsdlGeneratorError, msg getModuleName = classmethod(getModuleName) def getAlias(cls, ns): if cls.alias_dict.has_key(ns): return cls.alias_dict[ns][1] msg = 'failed to find import for schema "%s"'%ns +\ 'possibly missing @schemaLocation attribute.' if ns in SCHEMA.XSD_LIST: msg = 'missing built-in typecode for schema "%s"' %ns raise WsdlGeneratorError, msg getAlias = classmethod(getAlias) def getNSList(cls): return tuple(cls.alias_list) getNSList = classmethod(getNSList) class StringWriter: """generator util""" def __init__(self, val=None): self.data = [] if val: self.data.append(val) def set(self, val): if self.data: # in some cases the empty list reassignment fails, so.... self.data = None self.data = [] self.data.append(val) def write(self, val): self.data.append(val) def getvalue(self): if self.data: return ''.join(self.data) else: return '' def __iadd__(self, val): self.data.append(val) return self def __str__(self): return self.getvalue() # ---- generated code utils class MessageContainer: """generator util - used by address.py""" pass # Extract sub names from message parts so they can be used when mapping # a message's contents to a function's arguments. # Args is a list of Message Parts. i.e.: op.getInputMessage().parts.values() def GetPartsSubNames(args, wsdl): do_extended = True from wsdl2python import WriteServiceModule, SchemaDescription wsm = WriteServiceModule(wsdl, do_extended=do_extended) wsm.gatherNamespaces() toReturn = [] for arg in args: argSubnames = [] for l in wsm.usedNamespaces.values(): for schema in l: sd = SchemaDescription(do_extended=do_extended) sd.fromSchema(schema) argNamespace = arg.element[0] if (sd.targetNamespace == argNamespace): for i in sd.items: # arg.name is the part name, but we want it's type argElementType = arg.element[1] if str(argElementType) == str(i.content.name): argSubnames = [] # I'm not sure when the name attribute was dropped # but at some point, or in some circumstance it's not # there, but instead a ref attribute is there which is # tuple of (namespace, name). This hack fixes things, # but I'm not sure why this happens or has happened. # IRJ - 2005-05-25 if i.content.mgContent != None: for c in i.content.mgContent: nValue = "None" if c.isWildCard(): nValue="any" elif c.attributes.has_key("name"): nValue = c.attributes["name"] elif c.attributes.has_key("ref"): nValue = c.attributes["ref"][1] argSubnames.append(nValue) toReturn.append(argSubnames) return toReturn ZSI-2.1-a1/ZSI/generate/__init__.py0000644000175100017510000000213110513030247015056 0ustar zsizsi# $Id: __init__.py 1261 2006-10-10 23:45:43Z boverhof $ __all__ = ['wsdl2python', 'utility', 'containers', 'commands'] class WSDLFormatError(Exception): '''Detected errors in the WSDL document. ''' class WsdlGeneratorError(Exception): pass class Wsdl2PythonError(Exception): pass class WSInteropError(Exception): '''Conformance to WS-I Basic-Profile 1.0 specification ''' class WSISpec: R2203 = 'An rpc-literal binding in a DESCRIPTION MUST refer, in its soapbind:body element(s), only to wsdl:part element(s) that have been defined using the type attribute.' R2710 = 'The operations in a wsdl:binding in a DESCRIPTION MUST result in wire signatures that are different from one another.' R2717 = 'An rpc-literal binding in a DESCRIPTION MUST have the namespace attribute specified, the value of which MUST be an absolute URI, on contained soapbind:body elements.' R2729 = 'A MESSAGE described with an rpc-literal binding that is a response message MUST have a wrapper element whose name is the corresponding wsdl:operation name suffixed with the string "Response"' ZSI-2.1-a1/ZSI/twisted/0000755000175100017510000000000010712455110012642 5ustar zsizsiZSI-2.1-a1/ZSI/twisted/wsgi.py0000644000175100017510000002316310712434035014175 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: $ ########################################################################### import os, sys, types, inspect from StringIO import StringIO # twisted & related imports from zope.interface import classProvides, implements, Interface # ZSI imports from ZSI import _get_element_nsuri_name, EvaluateException, ParseException,\ fault, ParsedSoap, SoapWriter from ZSI.twisted.reverse import DataHandler, ReverseHandlerChain,\ HandlerChainInterface """ EXAMPLES: See zsi/samples/WSGI """ def soapmethod(requesttypecode, responsetypecode, soapaction='', operation=None, **kw): """@soapmethod decorator function for soap methods """ def _closure(func_cb): func_cb.root = (requesttypecode.nspname,requesttypecode.pname) func_cb.action = soapaction func_cb.requesttypecode = requesttypecode func_cb.responsetypecode = responsetypecode func_cb.soapmethod = True func_cb.operation = None return func_cb return _closure class SOAPCallbackHandler: """ ps --> pyobj, pyobj --> sw class variables: writerClass -- ElementProxy implementation to use for SoapWriter instances. """ classProvides(HandlerChainInterface) writerClass = None @classmethod def processRequest(cls, ps, **kw): """invokes callback that should return a (request,response) tuple. representing the SOAP request and response respectively. ps -- ParsedSoap instance representing HTTP Body. request -- twisted.web.server.Request """ resource = kw['resource'] request = kw['request'] root = _get_element_nsuri_name(ps.body_root) for key,method in inspect.getmembers(resource, inspect.ismethod): if (getattr(method, 'soapmethod', False) and method.root == root): break else: raise RuntimeError, 'Missing soap callback method for root "%s"' %root try: req = ps.Parse(method.requesttypecode) except Exception, ex: raise try: rsp = method.responsetypecode.pyclass() except Exception, ex: raise try: req,rsp = method(req, rsp) except Exception, ex: raise return rsp @classmethod def processResponse(cls, output, **kw): sw = SoapWriter(outputclass=cls.writerClass) sw.serialize(output) return sw class SOAPHandlerChainFactory: protocol = ReverseHandlerChain @classmethod def newInstance(cls): return cls.protocol(DataHandler, SOAPCallbackHandler) class WSGIApplication(dict): encoding = "UTF-8" def __call__(self, env, start_response): """do dispatching, else process """ script = env['SCRIPT_NAME'] # consumed ipath = os.path.split(env['PATH_INFO'])[1:] for i in range(1, len(ipath)+1): path = os.path.join(*ipath[:i]) print "PATH: ", path application = self.get(path) if application is not None: env['SCRIPT_NAME'] = script + path env['PATH_INFO'] = '' print "SCRIPT: ", env['SCRIPT_NAME'] return application(env, start_response) return self._request_cb(env, start_response) def _request_cb(self, env, start_response): """callback method, override """ start_response("404 ERROR", [('Content-Type','text/plain')]) return ['Move along people, there is nothing to see to hear'] def putChild(self, path, resource): """ """ path = path.split('/') lp = len(path) if lp == 0: raise RuntimeError, 'bad path "%s"' %path if lp == 1: self[path[0]] = resource for i in range(len(path)): if not path[i]: continue break next = self.get(path[i], None) if next is None: next = self[path[i]] = WSGIApplication() next.putChild('/'.join(path[-1:]), resource) class SOAPApplication(WSGIApplication): """ """ factory = SOAPHandlerChainFactory def __init__(self, **kw): dict.__init__(self, **kw) self.delegate = None def _request_cb(self, env, start_response): """process request, """ if env['REQUEST_METHOD'] == 'GET': return self._handle_GET(env, start_response) if env['REQUEST_METHOD'] == 'POST': return self._handle_POST(env, start_response) start_response("500 ERROR", [('Content-Type','text/plain')]) s = StringIO() h = env.items(); h.sort() for k,v in h: print >>s, k,'=',`v` return [s.getvalue()] def _handle_GET(self, env, start_response): if env['QUERY_STRING'].lower() == 'wsdl': start_response("200 OK", [('Content-Type','text/plain')]) r = self.delegate or self return _resourceToWSDL(r) start_response("404 ERROR", [('Content-Type','text/plain')]) return ['NO RESOURCE FOR GET'] def _handle_POST(self, env, start_response): """Dispatch Method called by twisted render, creates a request/response handler chain. request -- twisted.web.server.Request """ input = env['wsgi.input'] data = input.read( int(env['CONTENT_LENGTH']) ) mimeType = "text/xml" if self.encoding is not None: mimeType = 'text/xml; charset="%s"' % self.encoding request = None resource = self.delegate or self chain = self.factory.newInstance() try: pyobj = chain.processRequest(data, request=request, resource=resource) except Exception, ex: start_response("500 ERROR", [('Content-Type',mimeType)]) return [fault.FaultFromException(ex, False, sys.exc_info()[2]).AsSOAP()] try: soap = chain.processResponse(pyobj, request=request, resource=resource) except Exception, ex: start_response("500 ERROR", [('Content-Type',mimeType)]) return [fault.FaultFromException(ex, False, sys.exc_info()[2]).AsSOAP()] start_response("200 OK", [('Content-Type',mimeType)]) return [soap] def test(app, port=8080, host="localhost"): """ """ from twisted.internet import reactor from twisted.python import log from twisted.web2.channel import HTTPFactory from twisted.web2.server import Site from twisted.web2.wsgi import WSGIResource log.startLogging(sys.stdout) reactor.listenTCP(port, HTTPFactory( Site(WSGIResource(app)) ), interface=host, ) reactor.run() def _issoapmethod(f): return type(f) is types.MethodType and getattr(f, 'soapmethod', False) def _resourceToWSDL(resource): from xml.etree import ElementTree from xml.etree.ElementTree import Element, QName from ZSI.wstools.Namespaces import WSDL r = resource methods = filter(_issoapmethod, map(lambda i: getattr(r, i), dir(r))) tns = '' #tree = ElementTree() defs = Element("{%s}definitions" %WSDL.BASE) defs.attrib['name'] = 'SampleDefs' defs.attrib['targetNamespace'] = tns #tree.append(defs) porttype = Element("{%s}portType" %WSDL) porttype.attrib['name'] = QName("{%s}SamplePortType" %tns) binding = Element("{%s}binding" %WSDL) defs.append(binding) binding.attrib['name'] = QName("{%s}SampleBinding" %tns) binding.attrib['type'] = porttype.get('name') for m in methods: m.action service = Element("{%s}service" %WSDL.BASE) defs.append(service) service.attrib['name'] = 'SampleService' port = Element("{%s}port" %WSDL.BASE) service.append(port) port.attrib['name'] = "SamplePort" port.attrib['binding'] = binding.get('name') soapaddress = Element("{%s}address" %WSDL.BIND_SOAP) soapaddress.attrib['location'] = 'http://localhost/bla' port.append(soapaddress) return [ElementTree.tostring(defs)] """ """ ZSI-2.1-a1/ZSI/twisted/WSresource.py0000644000175100017510000002655710712434035015337 0ustar zsizsi########################################################################### # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: WSresource.py 1423 2007-11-01 20:33:33Z boverhof $ ########################################################################### import sys, warnings # twisted & related imports from zope.interface import classProvides, implements, Interface from twisted.python import log, failure from twisted.web.error import NoResource from twisted.web.server import NOT_DONE_YET import twisted.web.http import twisted.web.resource # ZSI imports from ZSI import _get_element_nsuri_name, EvaluateException, ParseException from ZSI.parse import ParsedSoap from ZSI.writer import SoapWriter from ZSI import fault # WS-Address related imports from ZSI.address import Address from ZSI.ServiceContainer import WSActionException from interfaces import CheckInputArgs, HandlerChainInterface, CallbackChainInterface,\ DataHandler class LoggingHandlerChain: @CheckInputArgs(CallbackChainInterface, HandlerChainInterface) def __init__(self, cb, *handlers): self.handlercb = cb self.handlers = handlers self.debug = len(log.theLogPublisher.observers) > 0 def processRequest(self, arg, **kw): debug = self.debug if debug: log.msg('--->PROCESS REQUEST: %s' %arg, debug=1) for h in self.handlers: if debug: log.msg('\t%s handler: %s' %(arg, h), debug=1) arg = h.processRequest(arg, **kw) return self.handlercb.processRequest(arg, **kw) def processResponse(self, arg, **kw): debug = self.debug if debug: log.msg('===>PROCESS RESPONSE: %s' %str(arg), debug=1) if arg is None: return for h in self.handlers: if debug: log.msg('\t%s handler: %s' %(arg, h), debug=1) arg = h.processResponse(arg, **kw) s = str(arg) if debug: log.msg(s, debug=1) return s # # Stability: Unstable # class DefaultCallbackHandler: classProvides(CallbackChainInterface) @classmethod def processRequest(cls, ps, **kw): """invokes callback that should return a (request,response) tuple. representing the SOAP request and response respectively. ps -- ParsedSoap instance representing HTTP Body. request -- twisted.web.server.Request """ resource = kw['resource'] request = kw['request'] method = getattr(resource, 'soap_%s' % _get_element_nsuri_name(ps.body_root)[-1]) try: req_pyobj,rsp_pyobj = method(ps, request=request) except TypeError, ex: log.err( 'ERROR: service %s is broken, method MUST return request, response'\ % cls.__name__ ) raise except Exception, ex: log.err('failure when calling bound method') raise return rsp_pyobj class WSAddressHandler: """General WS-Address handler. This implementation depends on a 'wsAction' dictionary in the service stub which contains keys to WS-Action values. Implementation saves state on request response flow, so using this handle is not reliable if execution is deferred between proceesRequest and processResponse. TODO: sink this up with wsdl2dispatch TODO: reduce coupling with WSAddressCallbackHandler. """ implements(HandlerChainInterface) def processRequest(self, ps, **kw): # TODO: Clean this up resource = kw['resource'] d = getattr(resource, 'root', None) key = _get_element_nsuri_name(ps.body_root) if d is None or d.has_key(key) is False: raise RuntimeError,\ 'Error looking for key(%s) in root dictionary(%s)' %(key, str(d)) self.op_name = d[key] self.address = address = Address() address.parse(ps) action = address.getAction() if not action: raise WSActionException('No WS-Action specified in Request') request = kw['request'] http_headers = request.getAllHeaders() soap_action = http_headers.get('soapaction') if soap_action and soap_action.strip('\'"') != action: raise WSActionException(\ 'SOAP Action("%s") must match WS-Action("%s") if specified.'\ %(soap_action,action) ) # Save WS-Address in ParsedSoap instance. ps.address = address return ps def processResponse(self, sw, **kw): if sw is None: self.address = None return request, resource = kw['request'], kw['resource'] if isinstance(request, twisted.web.http.Request) is False: raise TypeError, '%s instance expected' %http.Request d = getattr(resource, 'wsAction', None) key = self.op_name if d is None or d.has_key(key) is False: raise WSActionNotSpecified,\ 'Error looking for key(%s) in wsAction dictionary(%s)' %(key, str(d)) addressRsp = Address(action=d[key]) if request.transport.TLS == 0: addressRsp.setResponseFromWSAddress(\ self.address, 'http://%s:%d%s' %( request.host.host, request.host.port, request.path) ) else: addressRsp.setResponseFromWSAddress(\ self.address, 'https://%s:%d%s' %( request.host.host, request.host.port, request.path) ) addressRsp.serialize(sw, typed=False) self.address = None return sw class WSAddressCallbackHandler: classProvides(CallbackChainInterface) @classmethod def processRequest(cls, ps, **kw): """invokes callback that should return a (request,response) tuple. representing the SOAP request and response respectively. ps -- ParsedSoap instance representing HTTP Body. request -- twisted.web.server.Request """ resource = kw['resource'] request = kw['request'] method = getattr(resource, 'wsa_%s' % _get_element_nsuri_name(ps.body_root)[-1]) # TODO: grab ps.address, clean this up. try: req_pyobj,rsp_pyobj = method(ps, ps.address, request=request) except TypeError, ex: log.err( 'ERROR: service %s is broken, method MUST return request, response'\ %self.__class__.__name__ ) raise except Exception, ex: log.err('failure when calling bound method') raise return rsp_pyobj class DeferHandlerChain: """Each handler is """ @CheckInputArgs(CallbackChainInterface, HandlerChainInterface) def __init__(self, cb, *handlers): self.handlercb = cb self.handlers = handlers self.debug = len(log.theLogPublisher.observers) > 0 def processRequest(self, arg, **kw): from twisted.internet import reactor from twisted.internet.defer import Deferred debug = self.debug if debug: log.msg('--->DEFER PROCESS REQUEST: %s' %arg, debug=1) d = Deferred() for h in self.handlers: if debug: log.msg('\t%s handler: %s' %(arg, h), debug=1) log.msg('\thandler callback: %s' %h.processRequest) d.addCallback(h.processRequest, **kw) d.addCallback(self.handlercb.processRequest, **kw) reactor.callLater(.0001, d.callback, arg) if debug: log.msg('===>DEFER PROCESS RESPONSE: %s' %str(arg), debug=1) for h in self.handlers: if debug: log.msg('\t%s handler: %s' %(arg, h), debug=1) d.addCallback(h.processResponse, **kw) d.addCallback(str) return d def processResponse(self, arg, **kw): return arg class DefaultHandlerChainFactory: protocol = LoggingHandlerChain @classmethod def newInstance(cls): return cls.protocol(DefaultCallbackHandler, DataHandler) class WSAddressHandlerChainFactory: protocol = DefaultHandlerChain @classmethod def newInstance(cls): return cls.protocol(WSAddressCallbackHandler, DataHandler, WSAddressHandler()) class WSResource(twisted.web.resource.Resource, object): """ class variables: encoding -- factory -- hander chain, which has a factory method "newInstance" that returns a """ encoding = "UTF-8" factory = DefaultHandlerChainFactory def __init__(self): """ """ twisted.web.resource.Resource.__init__(self) def _writeResponse(self, response, request, status=200): """ request -- request message response --- response message status -- HTTP Status """ request.setResponseCode(status) if self.encoding is not None: mimeType = 'text/xml; charset="%s"' % self.encoding else: mimeType = "text/xml" request.setHeader("Content-Type", mimeType) request.setHeader("Content-Length", str(len(response))) request.write(response) request.finish() def _writeFault(self, fail, request): """ fail -- failure request -- request message ex -- Exception """ response = fault.FaultFromException(fail.value, False, fail.tb).AsSOAP() self._writeResponse(response, request, status=500) def render_POST(self, request): """Dispatch Method called by twisted render, creates a request/response handler chain. request -- twisted.web.server.Request """ from twisted.internet.defer import maybeDeferred chain = self.factory.newInstance() data = request.content.read() d = maybeDeferred(chain.processRequest, data, request=request, resource=self) d.addCallback(chain.processResponse, request=request, resource=self) d.addCallback(self._writeResponse, request) d.addErrback(self._writeFault, request) return NOT_DONE_YET class DefaultHandlerChain: @CheckInputArgs(CallbackChainInterface, HandlerChainInterface) def __init__(self, cb, *handlers): self.handlercb = cb self.handlers = handlers self.debug = len(log.theLogPublisher.observers) > 0 def processRequest(self, arg, **kw): debug = self.debug if debug: log.msg('--->PROCESS REQUEST: %s' %arg, debug=1) for h in self.handlers: if debug: log.msg('\t%s handler: %s' %(arg, h), debug=1) arg = h.processRequest(arg, **kw) return self.handlercb.processRequest(arg, **kw) def processResponse(self, arg, **kw): debug = self.debug if debug: log.msg('===>PROCESS RESPONSE: %s' %str(arg), debug=1) if arg is None: return for h in self.handlers: if debug: log.msg('\t%s handler: %s' %(arg, h), debug=1) arg = h.processResponse(arg, **kw) s = str(arg) if debug: log.msg(s, debug=1) return s ZSI-2.1-a1/ZSI/twisted/client.py0000644000175100017510000002436410424053132014501 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import time # twisted & related imports from zope.interface import classProvides, implements, Interface from twisted.web import client from twisted.internet import defer from twisted.internet import reactor from twisted.python import log from twisted.python.failure import Failure from ZSI.parse import ParsedSoap from ZSI.writer import SoapWriter from ZSI.fault import FaultFromFaultMessage from ZSI.wstools.Namespaces import WSA from WSresource import HandlerChainInterface, CheckInputArgs # # Stability: Unstable # class HTTPPageGetter(client.HTTPPageGetter): def handleStatus_500(self): """potentially a SOAP:Fault. """ log.err('HTTP Error 500') def handleStatus_404(self): """client error, not found """ log.err('HTTP Error 404') client.HTTPClientFactory.protocol = HTTPPageGetter def getPage(url, contextFactory=None, *args, **kwargs): """Download a web page as a string. Download a page. Return a deferred, which will callback with a page (as a string) or errback with a description of the error. See HTTPClientFactory to see what extra args can be passed. """ scheme, host, port, path = client._parse(url) factory = client.HTTPClientFactory(url, *args, **kwargs) if scheme == 'https': if contextFactory is None: raise RuntimeError, 'must provide a contextFactory' conn = reactor.connectSSL(host, port, factory, contextFactory) else: conn = reactor.connectTCP(host, port, factory) return factory class ClientDataHandler: """ class variables: readerClass -- factory class to create reader for ParsedSoap instances. writerClass -- ElementProxy implementation to use for SoapWriter instances. """ classProvides(HandlerChainInterface) readerClass = None writerClass = None @classmethod def processResponse(cls, soapdata, **kw): """called by deferred, returns pyobj representing reply. Parameters and Key Words: soapdata -- SOAP Data replytype -- reply type of response """ if len(soapdata) == 0: raise TypeError('Received empty response') # log.msg("_" * 33, time.ctime(time.time()), # "RESPONSE: \n%s" %soapdata, debug=True) ps = ParsedSoap(soapdata, readerclass=cls.readerClass) if ps.IsAFault() is True: log.msg('Received SOAP:Fault', debug=True) raise FaultFromFaultMessage(ps) return ps @classmethod def processRequest(cls, obj, nsdict={}, header=True, **kw): tc = None if kw.has_key('requesttypecode'): tc = kw['requesttypecode'] elif kw.has_key('requestclass'): tc = kw['requestclass'].typecode else: tc = getattr(obj.__class__, 'typecode', None) sw = SoapWriter(nsdict=nsdict, header=header, outputclass=cls.writerClass) sw.serialize(obj, tc) return sw class WSAddressHandler: """Minimal WS-Address handler. Most of the logic is in the ZSI.address.Address class. class variables: uri -- default WSA Addressing URI """ implements(HandlerChainInterface) uri = WSA.ADDRESS def processResponse(self, ps, wsaction=None, soapaction=None, **kw): addr = self.address addr.parse(ps) action = addr.getAction() if not action: raise WSActionException('No WS-Action specified in Request') if not soapaction: return ps soapaction = soapaction.strip('\'"') if soapaction and soapaction != wsaction: raise WSActionException(\ 'SOAP Action("%s") must match WS-Action("%s") if specified.'%( soapaction, wsaction) ) return ps def processRequest(self, sw, wsaction=None, url=None, endPointReference=None, **kw): from ZSI.address import Address if sw is None: self.address = None return if not sw.header: raise RuntimeError, 'expecting SOAP:Header' self.address = addr = Address(url, wsAddressURI=self.uri) addr.setRequest(endPointReference, wsaction) addr.serialize(sw, typed=False) return sw class DefaultClientHandlerChain: @CheckInputArgs(HandlerChainInterface) def __init__(self, *handlers): self.handlers = handlers self.debug = len(log.theLogPublisher.observers) > 0 self.flow = None @staticmethod def parseResponse(ps, replytype): return ps.Parse(replytype) def processResponse(self, arg, replytype, **kw): """ Parameters: arg -- deferred replytype -- typecode """ if self.debug: log.msg('--->PROCESS REQUEST\n%s' %arg, debug=1) for h in self.handlers: arg.addCallback(h.processResponse, **kw) arg.addCallback(self.parseResponse, replytype) def processRequest(self, arg, **kw): """ Parameters: arg -- XML Soap data string """ if self.debug: log.msg('===>PROCESS RESPONSE: %s' %str(arg), debug=1) if arg is None: return for h in self.handlers: arg = h.processRequest(arg, **kw) s = str(arg) if self.debug: log.msg(s, debug=1) return s class DefaultClientHandlerChainFactory: protocol = DefaultClientHandlerChain @classmethod def newInstance(cls): return cls.protocol(ClientDataHandler) class WSAddressClientHandlerChainFactory: protocol = DefaultClientHandlerChain @classmethod def newInstance(cls): return cls.protocol(ClientDataHandler, WSAddressHandler()) class Binding: """Object that represents a binding (connection) to a SOAP server. """ agent='ZSI.twisted client' factory = DefaultClientHandlerChainFactory defer = False def __init__(self, url=None, nsdict=None, contextFactory=None, tracefile=None, **kw): """Initialize. Keyword arguments include: url -- URL of resource, POST is path nsdict -- namespace entries to add contextFactory -- security contexts tracefile -- file to dump packet traces """ self.url = url self.nsdict = nsdict or {} self.contextFactory = contextFactory self.http_headers = {'content-type': 'text/xml',} self.trace = tracefile def addHTTPHeader(self, key, value): self.http_headers[key] = value def getHTTPHeaders(self): return self.http_headers def Send(self, url, opname, pyobj, nsdict={}, soapaction=None, chain=None, **kw): """Returns a ProcessingChain which needs to be passed to Receive if Send is being called consecutively. """ url = url or self.url cookies = None if chain is not None: cookies = chain.flow.cookies d = {} d.update(self.nsdict) d.update(nsdict) if soapaction is not None: self.addHTTPHeader('SOAPAction', soapaction) chain = self.factory.newInstance() soapdata = chain.processRequest(pyobj, nsdict=nsdict, soapaction=soapaction, **kw) if self.trace: print >>self.trace, "_" * 33, time.ctime(time.time()), "REQUEST:" print >>self.trace, soapdata f = getPage(str(url), contextFactory=self.contextFactory, postdata=soapdata, agent=self.agent, method='POST', headers=self.getHTTPHeaders(), cookies=cookies) if isinstance(f, Failure): return f chain.flow = f self.chain = chain return chain def Receive(self, replytype, chain=None, **kw): """This method allows code to act in a synchronous manner, it waits to return until the deferred fires but it doesn't prevent other queued calls from being executed. Send must be called first, which sets up the chain/factory. WARNING: If defer is set to True, must either call Receive immediately after Send (ie. no intervening Sends) or pass chain in as a paramter. Parameters: replytype -- TypeCode KeyWord Parameters: chain -- processing chain, optional """ chain = chain or self.chain d = chain.flow.deferred if self.trace: def trace(soapdata): print >>self.trace, "_" * 33, time.ctime(time.time()), "RESPONSE:" print >>self.trace, soapdata return soapdata d.addCallback(trace) chain.processResponse(d, replytype, **kw) if self.defer: return d failure = [] append = failure.append def errback(result): """Used with Response method to suppress 'Unhandled error in Deferred' messages by adding an errback. """ append(result) return None d.addErrback(errback) # spin reactor while not d.called: reactor.runUntilCurrent() t2 = reactor.timeout() t = reactor.running and t2 reactor.doIteration(t) pyobj = d.result if len(failure): failure[0].raiseException() return pyobj def trace(): if trace: print >>trace, "_" * 33, time.ctime(time.time()), "RESPONSE:" for i in (self.reply_code, self.reply_msg,): print >>trace, str(i) print >>trace, "-------" print >>trace, str(self.reply_headers) print >>trace, self.data ZSI-2.1-a1/ZSI/twisted/interfaces.py0000644000175100017510000000643710712434035015354 0ustar zsizsi########################################################################### # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: $ ########################################################################### import sys, warnings # twisted & related imports from zope.interface import classProvides, implements, Interface # ZSI imports from ZSI import EvaluateException, ParseException, ParsedSoap, SoapWriter # # Stability: Unstable # def CheckInputArgs(*interfaces): """Must provide at least one interface, the last one may be repeated. """ l = len(interfaces) def wrapper(func): def check_args(self, *args, **kw): for i in range(len(args)): if (l > i and interfaces[i].providedBy(args[i])) or interfaces[-1].providedBy(args[i]): continue if l > i: raise TypeError, 'arg %s does not implement %s' %(args[i], interfaces[i]) raise TypeError, 'arg %s does not implement %s' %(args[i], interfaces[-1]) func(self, *args, **kw) return check_args return wrapper class HandlerChainInterface(Interface): def processRequest(self, input, **kw): """returns a representation of the request, the last link in the chain must return a response pyobj with a typecode attribute. Parameters: input -- Keyword Parameters: request -- HTTPRequest instance resource -- Resource instance """ def processResponse(self, output, **kw): """returns a string representing the soap response. Parameters output -- Keyword Parameters: request -- HTTPRequest instance resource -- Resource instance """ class CallbackChainInterface(Interface): def processRequest(self, input, **kw): """returns a response pyobj with a typecode attribute. Parameters: input -- Keyword Parameters: request -- HTTPRequest instance resource -- Resource instance """ class DataHandler: """ class variables: readerClass -- factory class to create reader for ParsedSoap instances. writerClass -- ElementProxy implementation to use for SoapWriter instances. """ classProvides(HandlerChainInterface) readerClass = None writerClass = None @classmethod def processRequest(cls, input, **kw): return ParsedSoap(input, readerclass=cls.readerClass) @classmethod def processResponse(cls, output, **kw): sw = SoapWriter(outputclass=cls.writerClass) sw.serialize(output) return sw class DefaultHandlerChain: @CheckInputArgs(CallbackChainInterface, HandlerChainInterface) def __init__(self, cb, *handlers): self.handlercb = cb self.handlers = handlers def processRequest(self, arg, **kw): for h in self.handlers: arg = h.processRequest(arg, **kw) return self.handlercb.processRequest(arg, **kw) def processResponse(self, arg, **kw): if arg is None: return for h in self.handlers: arg = h.processResponse(arg, **kw) s = str(arg) return s ZSI-2.1-a1/ZSI/twisted/reverse.py0000644000175100017510000000516410712434035014700 0ustar zsizsi########################################################################### # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: $ ########################################################################### from ZSI import _get_element_nsuri_name, SoapWriter, ParsedSoap from interfaces import HandlerChainInterface from zope.interface import classProvides, implements, Interface class DataHandler: """ str --> ps, sw --> str class variables: readerClass -- factory class to create reader for ParsedSoap instances. """ classProvides(HandlerChainInterface) readerClass = None @classmethod def processRequest(cls, input, **kw): return ParsedSoap(input, readerclass=cls.readerClass) @classmethod def processResponse(cls, sw, **kw): return str(sw) class CallbackHandler: """ ps --> pyobj, pyobj --> sw class variables: writerClass -- ElementProxy implementation to use for SoapWriter instances. """ classProvides(HandlerChainInterface) writerClass = None @classmethod def processRequest(cls, ps, **kw): """invokes callback that should return a (request,response) tuple. representing the SOAP request and response respectively. ps -- ParsedSoap instance representing HTTP Body. request -- twisted.web.server.Request """ resource = kw['resource'] request = kw['request'] method = getattr(resource, 'soap_%s' % _get_element_nsuri_name(ps.body_root)[-1]) try: req,rsp = method(ps, request=request) except Exception, ex: raise return rsp @classmethod def processResponse(cls, output, **kw): sw = SoapWriter(outputclass=cls.writerClass) sw.serialize(output) return sw class ReverseHandlerChain: def __init__(self, *handlers): self.in_handlers = handlers handlers = list(handlers); handlers.reverse() self.out_handlers = tuple(handlers) def processRequest(self, arg, **kw): for h in self.in_handlers: arg = h.processRequest(arg, **kw) return arg def processResponse(self, arg, **kw): if arg is None: return for h in self.out_handlers: arg = h.processResponse(arg, **kw) return arg class ReverseHandlerChainFactory: protocol = ReverseHandlerChain @classmethod def newInstance(cls): return cls.protocol(DataHandler, CallbackHandler) ZSI-2.1-a1/ZSI/twisted/__init__.py0000644000175100017510000000054210712434035014757 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: __init__.py 1423 2007-11-01 20:33:33Z boverhof $ ########################################################################### __all__=['interfaces', 'client', 'WSresource', 'WSsecurity'] import interfaces ZSI-2.1-a1/ZSI/twisted/WSsecurity.py0000644000175100017510000003256210377450752015363 0ustar zsizsi########################################################################### # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! # $Id: WSsecurity.py 1134 2006-02-24 00:23:06Z boverhof $ ########################################################################### import sys, time, warnings import sha, base64 # twisted & related imports from zope.interface import classProvides, implements, Interface from twisted.python import log, failure from twisted.web.error import NoResource from twisted.web.server import NOT_DONE_YET from twisted.internet import reactor import twisted.web.http import twisted.web.resource # ZSI imports from ZSI import _get_element_nsuri_name, EvaluateException, ParseException from ZSI.parse import ParsedSoap from ZSI.writer import SoapWriter from ZSI.TC import _get_global_element_declaration as GED from ZSI import fault from ZSI.wstools.Namespaces import OASIS, DSIG from WSresource import DefaultHandlerChain, HandlerChainInterface,\ WSAddressCallbackHandler, DataHandler, WSAddressHandler # # Global Element Declarations # UsernameTokenDec = GED(OASIS.WSSE, "UsernameToken") SecurityDec = GED(OASIS.WSSE, "Security") SignatureDec = GED(DSIG.BASE, "Signature") PasswordDec = GED(OASIS.WSSE, "Password") NonceDec = GED(OASIS.WSSE, "Nonce") CreatedDec = GED(OASIS.UTILITY, "Created") if None in [UsernameTokenDec,SecurityDec,SignatureDec,PasswordDec,NonceDec,CreatedDec]: raise ImportError, 'required global element(s) unavailable: %s ' %({ (OASIS.WSSE, "UsernameToken"):UsernameTokenDec, (OASIS.WSSE, "Security"):SecurityDec, (DSIG.BASE, "Signature"):SignatureDec, (OASIS.WSSE, "Password"):PasswordDec, (OASIS.WSSE, "Nonce"):NonceDec, (OASIS.UTILITY, "Created"):CreatedDec, }) # # Stability: Unstable, Untested, Not Finished. # class WSSecurityHandler: """Web Services Security: SOAP Message Security 1.0 Class Variables: debug -- If True provide more detailed SOAP:Fault information to clients. """ classProvides(HandlerChainInterface) debug = True @classmethod def processRequest(cls, ps, **kw): if type(ps) is not ParsedSoap: raise TypeError,'Expecting ParsedSoap instance' security = ps.ParseHeaderElements([cls.securityDec]) # Assume all security headers are supposed to be processed here. for pyobj in security or []: for any in pyobj.Any or []: if any.typecode is UsernameTokenDec: try: ps = cls.UsernameTokenProfileHandler.processRequest(ps, any) except Exception, ex: if cls.debug: raise raise RuntimeError, 'Unauthorized Username/passphrase combination' continue if any.typecode is SignatureDec: try: ps = cls.SignatureHandler.processRequest(ps, any) except Exception, ex: if cls.debug: raise raise RuntimeError, 'Invalid Security Header' continue raise RuntimeError, 'WS-Security, Unsupported token %s' %str(any) return ps @classmethod def processResponse(cls, output, **kw): return output class UsernameTokenProfileHandler: """Web Services Security UsernameToken Profile 1.0 Class Variables: targetNamespace -- """ classProvides(HandlerChainInterface) # Class Variables targetNamespace = OASIS.WSSE sweepInterval = 60*5 nonces = None # Set to None to disable PasswordText = targetNamespace + "#PasswordText" PasswordDigest = targetNamespace + "#PasswordDigest" # Override passwordCallback passwordCallback = lambda cls,username: None @classmethod def sweep(cls, index): """remove nonces every sweepInterval. Parameters: index -- remove all nonces up to this index. """ if cls.nonces is None: cls.nonces = [] seconds = cls.sweepInterval cls.nonces = cls.nonces[index:] reactor.callLater(seconds, cls.sweep, len(cls.nonces)) @classmethod def processRequest(cls, ps, token, **kw): """ Parameters: ps -- ParsedSoap instance token -- UsernameToken pyclass instance """ if token.typecode is not UsernameTokenDec: raise TypeError, 'expecting GED (%s,%s) representation.' %( UsernameTokenDec.nspname, UsernameTokenDec.pname) username = token.Username # expecting only one password # may have a nonce and a created password = nonce = timestamp = None for any in token.Any or []: if any.typecode is PasswordDec: password = any continue if any.typecode is NonceTypeDec: nonce = any continue if any.typecode is CreatedTypeDec: timestamp = any continue raise TypeError, 'UsernameTokenProfileHander unexpected %s' %str(any) if password is None: raise RuntimeError, 'Unauthorized, no password' # TODO: not yet supporting complexType simpleContent in pyclass_type attrs = getattr(password, password.typecode.attrs_aname, {}) pwtype = attrs.get('Type', cls.PasswordText) # Clear Text Passwords if cls.PasswordText is not None and pwtype == cls.PasswordText: if password == cls.passwordCallback(username): return ps raise RuntimeError, 'Unauthorized, clear text password failed' if cls.nonces is None: cls.sweep(0) if nonce is not None: if nonce in cls.nonces: raise RuntimeError, 'Invalid Nonce' # created was 10 seconds ago or sooner if created is not None and created < time.gmtime(time.time()-10): raise RuntimeError, 'UsernameToken created is expired' cls.nonces.append(nonce) # PasswordDigest, recommended that implemenations # require a Nonce and Created if cls.PasswordDigest is not None and pwtype == cls.PasswordDigest: digest = sha.sha() for i in (nonce, created, cls.passwordCallback(username)): if i is None: continue digest.update(i) if password == base64.encodestring(digest.digest()).strip(): return ps raise RuntimeError, 'Unauthorized, digest failed' raise RuntimeError, 'Unauthorized, contents of UsernameToken unknown' @classmethod def processResponse(cls, output, **kw): return output @staticmethod def hmac_sha1(xml): return class SignatureHandler: """Web Services Security UsernameToken Profile 1.0 """ digestMethods = { DSIG.BASE+"#sha1":sha.sha, } signingMethods = { DSIG.BASE+"#hmac-sha1":hmac_sha1, } canonicalizationMethods = { DSIG.C14N_EXCL:lambda node: Canonicalize(node, unsuppressedPrefixes=[]), DSIG.C14N:lambda node: Canonicalize(node), } @classmethod def processRequest(cls, ps, signature, **kw): """ Parameters: ps -- ParsedSoap instance signature -- Signature pyclass instance """ if token.typecode is not SignatureDec: raise TypeError, 'expecting GED (%s,%s) representation.' %( SignatureDec.nspname, SignatureDec.pname) si = signature.SignedInfo si.CanonicalizationMethod calgo = si.CanonicalizationMethod.get_attribute_Algorithm() for any in si.CanonicalizationMethod.Any: pass # Check Digest si.Reference context = XPath.Context.Context(ps.dom, processContents={'wsu':OASIS.UTILITY}) exp = XPath.Compile('//*[@wsu:Id="%s"]' %si.Reference.get_attribute_URI()) nodes = exp.evaluate(context) if len(nodes) != 1: raise RuntimeError, 'A SignedInfo Reference must refer to one node %s.' %( si.Reference.get_attribute_URI()) try: xml = cls.canonicalizeMethods[calgo](nodes[0]) except IndexError: raise RuntimeError, 'Unsupported canonicalization algorithm' try: digest = cls.digestMethods[salgo] except IndexError: raise RuntimeError, 'unknown digestMethods Algorithm' digestValue = base64.encodestring(digest(xml).digest()).strip() if si.Reference.DigestValue != digestValue: raise RuntimeError, 'digest does not match' if si.Reference.Transforms: pass signature.KeyInfo signature.KeyInfo.KeyName signature.KeyInfo.KeyValue signature.KeyInfo.RetrievalMethod signature.KeyInfo.X509Data signature.KeyInfo.PGPData signature.KeyInfo.SPKIData signature.KeyInfo.MgmtData signature.KeyInfo.Any signature.Object # TODO: Check Signature signature.SignatureValue si.SignatureMethod salgo = si.SignatureMethod.get_attribute_Algorithm() if si.SignatureMethod.HMACOutputLength: pass for any in si.SignatureMethod.Any: pass # exp = XPath.Compile('//child::*[attribute::URI = "%s"]/..' %( si.Reference.get_attribute_URI())) nodes = exp.evaluate(context) if len(nodes) != 1: raise RuntimeError, 'A SignedInfo Reference must refer to one node %s.' %( si.Reference.get_attribute_URI()) try: xml = cls.canonicalizeMethods[calgo](nodes[0]) except IndexError: raise RuntimeError, 'Unsupported canonicalization algorithm' # TODO: Check SignatureValue @classmethod def processResponse(cls, output, **kw): return output class X509TokenProfileHandler: """Web Services Security UsernameToken Profile 1.0 """ targetNamespace = DSIG.BASE # Token Types singleCertificate = targetNamespace + "#X509v3" certificatePath = targetNamespace + "#X509PKIPathv1" setCerticatesCRLs = targetNamespace + "#PKCS7" @classmethod def processRequest(cls, ps, signature, **kw): return ps """ """ class WSSecurityHandlerChainFactory: protocol = DefaultHandlerChain @classmethod def newInstance(cls): return cls.protocol(WSAddressCallbackHandler, DataHandler, WSSecurityHandler, WSAddressHandler()) ZSI-2.1-a1/ZSI/TCtimes.py0000644000175100017510000002526110556451671013125 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Typecodes for dates and times. ''' from ZSI import _copyright, _floattypes, _inttypes, _get_idstr, EvaluateException from ZSI.TC import TypeCode, SimpleType from ZSI.wstools.Namespaces import SCHEMA import operator, re, time as _time from time import mktime as _mktime, localtime as _localtime, gmtime as _gmtime from datetime import tzinfo as _tzinfo, timedelta as _timedelta,\ datetime as _datetime from math import modf as _modf _niltime = [ 0, 0, 0, # year month day 0, 0, 0, # hour minute second 0, 0, 0 # weekday, julian day, dst flag ] #### Code added to check current timezone offset _zero = _timedelta(0) _dstoffset = _stdoffset = _timedelta(seconds=-_time.timezone) if _time.daylight: _dstoffset = _timedelta(seconds=-_time.altzone) _dstdiff = _dstoffset - _stdoffset class _localtimezone(_tzinfo): """ """ def dst(self, dt): """datetime -> DST offset in minutes east of UTC.""" tt = _localtime(_mktime((dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1))) if tt.tm_isdst > 0: return _dstdiff return _zero #def fromutc(...) #datetime in UTC -> datetime in local time. def tzname(self, dt): """datetime -> string name of time zone.""" tt = _localtime(_mktime((dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1))) return _time.tzname[tt.tm_isdst > 0] def utcoffset(self, dt): """datetime -> minutes east of UTC (negative for west of UTC).""" tt = _localtime(_mktime((dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1))) if tt.tm_isdst > 0: return _dstoffset return _stdoffset class _fixedoffset(_tzinfo): """Fixed offset in minutes east from UTC. A class building tzinfo objects for fixed-offset time zones. Note that _fixedoffset(0, "UTC") is a different way to build a UTC tzinfo object. """ #def __init__(self, offset, name): def __init__(self, offset): self.__offset = _timedelta(minutes=offset) #self.__name = name def dst(self, dt): """datetime -> DST offset in minutes east of UTC.""" return _zero def tzname(self, dt): """datetime -> string name of time zone.""" #return self.__name return "server" def utcoffset(self, dt): """datetime -> minutes east of UTC (negative for west of UTC).""" return self.__offset def _dict_to_tuple(d): '''Convert a dictionary to a time tuple. Depends on key values in the regexp pattern! ''' # TODO: Adding a ms field to struct_time tuples is problematic # since they don't have this field. Should use datetime # which has a microseconds field, else no ms.. When mapping struct_time # to gDateTime the last 3 fields are irrelevant, here using dummy values to make # everything happy. # retval = _niltime[:] for k,i in ( ('Y', 0), ('M', 1), ('D', 2), ('h', 3), ('m', 4), ): v = d.get(k) if v: retval[i] = int(v) v = d.get('s') if v: msec,sec = _modf(float(v)) retval[6],retval[5] = int(round(msec*1000)), int(sec) v = d.get('tz') if v and v != 'Z': h,m = map(int, v.split(':')) # check for time zone offset, if within the same timezone, # ignore offset specific calculations offset=_localtimezone().utcoffset(_datetime.now()) local_offset_hour = offset.seconds/3600 local_offset_min = (offset.seconds%3600)%60 if local_offset_hour > 12: local_offset_hour -= 24 if local_offset_hour != h or local_offset_min != m: if h<0: #TODO: why is this set to server #foff = _fixedoffset(-((abs(h)*60+m)),"server") foff = _fixedoffset(-((abs(h)*60+m))) else: #TODO: why is this set to server #foff = _fixedoffset((abs(h)*60+m),"server") foff = _fixedoffset((abs(h)*60+m)) dt = _datetime(retval[0],retval[1],retval[2],retval[3],retval[4], retval[5],0,foff) # update dict with calculated timezone localdt=dt.astimezone(_localtimezone()) retval[0] = localdt.year retval[1] = localdt.month retval[2] = localdt.day retval[3] = localdt.hour retval[4] = localdt.minute retval[5] = localdt.second if d.get('neg', 0): retval[0:5] = map(operator.__neg__, retval[0:5]) return tuple(retval) class Duration(SimpleType): '''Time duration. ''' parselist = [ (None,'duration') ] lex_pattern = re.compile('^' r'(?P-?)P' \ r'((?P\d+)Y)?' r'((?P\d+)M)?' r'((?P\d+)D)?' \ r'(?PT?)' r'((?P\d+)H)?' r'((?P\d+)M)?' \ r'((?P\d*(\.\d+)?)S)?' '$') type = (SCHEMA.XSD3, 'duration') def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' if text is None: return None m = Duration.lex_pattern.match(text) if m is None: raise EvaluateException('Illegal duration', ps.Backtrace(elt)) d = m.groupdict() if d['T'] and (d['h'] is None and d['m'] is None and d['s'] is None): raise EvaluateException('Duration has T without time') try: retval = _dict_to_tuple(d) except ValueError, e: raise EvaluateException(str(e)) if self.pyclass is not None: return self.pyclass(retval) return retval def get_formatted_content(self, pyobj): if type(pyobj) in _floattypes or type(pyobj) in _inttypes: pyobj = _gmtime(pyobj) d = {} pyobj = tuple(pyobj) if 1 in map(lambda x: x < 0, pyobj[0:6]): pyobj = map(abs, pyobj) neg = '-' else: neg = '' val = '%sP%dY%dM%dDT%dH%dM%dS' % \ ( neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5]) return val class Gregorian(SimpleType): '''Gregorian times. ''' lex_pattern = tag = format = None def text_to_data(self, text, elt, ps): '''convert text into typecode specific data. ''' if text is None: return None m = self.lex_pattern.match(text) if not m: raise EvaluateException('Bad Gregorian: %s' %text, ps.Backtrace(elt)) try: retval = _dict_to_tuple(m.groupdict()) except ValueError, e: #raise EvaluateException(str(e)) raise if self.pyclass is not None: return self.pyclass(retval) return retval def get_formatted_content(self, pyobj): if type(pyobj) in _floattypes or type(pyobj) in _inttypes: pyobj = _gmtime(pyobj) d = {} pyobj = tuple(pyobj) if 1 in map(lambda x: x < 0, pyobj[0:6]): pyobj = map(abs, pyobj) d['neg'] = '-' else: d['neg'] = '' ms = pyobj[6] if not ms or not hasattr(self, 'format_ms'): d = { 'Y': pyobj[0], 'M': pyobj[1], 'D': pyobj[2], 'h': pyobj[3], 'm': pyobj[4], 's': pyobj[5], } return self.format % d if ms > 999: raise ValueError, 'milliseconds must be a integer between 0 and 999' d = { 'Y': pyobj[0], 'M': pyobj[1], 'D': pyobj[2], 'h': pyobj[3], 'm': pyobj[4], 's': pyobj[5], 'ms':ms, } return self.format_ms % d class gDateTime(Gregorian): '''A date and time. ''' parselist = [ (None,'dateTime') ] lex_pattern = re.compile('^' r'(?P-?)' \ '(?P\d{4,})-' r'(?P\d\d)-' r'(?P\d\d)' 'T' \ r'(?P\d\d):' r'(?P\d\d):' r'(?P\d*(\.\d+)?)' \ r'(?P(Z|([-+]\d\d:\d\d))?)' '$') tag, format = 'dateTime', '%(Y)04d-%(M)02d-%(D)02dT%(h)02d:%(m)02d:%(s)02dZ' format_ms = format[:-1] + '.%(ms)03dZ' type = (SCHEMA.XSD3, 'dateTime') class gDate(Gregorian): '''A date. ''' parselist = [ (None,'date') ] lex_pattern = re.compile('^' r'(?P-?)' \ '(?P\d{4,})-' r'(?P\d\d)-' r'(?P\d\d)' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'date', '%(Y)04d-%(M)02d-%(D)02dZ' type = (SCHEMA.XSD3, 'date') class gYearMonth(Gregorian): '''A date. ''' parselist = [ (None,'gYearMonth') ] lex_pattern = re.compile('^' r'(?P-?)' \ '(?P\d{4,})-' r'(?P\d\d)' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'gYearMonth', '%(Y)04d-%(M)02dZ' type = (SCHEMA.XSD3, 'gYearMonth') class gYear(Gregorian): '''A date. ''' parselist = [ (None,'gYear') ] lex_pattern = re.compile('^' r'(?P-?)' \ '(?P\d{4,})' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'gYear', '%(Y)04dZ' type = (SCHEMA.XSD3, 'gYear') class gMonthDay(Gregorian): '''A gMonthDay. ''' parselist = [ (None,'gMonthDay') ] lex_pattern = re.compile('^' r'(?P-?)' \ r'--(?P\d\d)-' r'(?P\d\d)' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'gMonthDay', '---%(M)02d-%(D)02dZ' type = (SCHEMA.XSD3, 'gMonthDay') class gDay(Gregorian): '''A gDay. ''' parselist = [ (None,'gDay') ] lex_pattern = re.compile('^' r'(?P-?)' \ r'---(?P\d\d)' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'gDay', '---%(D)02dZ' type = (SCHEMA.XSD3, 'gDay') class gMonth(Gregorian): '''A gMonth. ''' parselist = [ (None,'gMonth') ] lex_pattern = re.compile('^' r'(?P-?)' \ r'---(?P\d\d)' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'gMonth', '---%(M)02dZ' type = (SCHEMA.XSD3, 'gMonth') class gTime(Gregorian): '''A time. ''' parselist = [ (None,'time') ] lex_pattern = re.compile('^' r'(?P-?)' \ r'(?P\d\d):' r'(?P\d\d):' r'(?P\d*(\.\d+)?)' \ r'(?PZ|([-+]\d\d:\d\d))?' '$') tag, format = 'time', '%(h)02d:%(m)02d:%(s)02dZ' format_ms = format[:-1] + '.%(ms)03dZ' type = (SCHEMA.XSD3, 'time') if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/schema.py0000644000175100017510000003553510602266764013021 0ustar zsizsi#! /usr/bin/env python # $Header$ '''XML Schema support ''' from ZSI import _copyright, _seqtypes, _find_type, _get_element_nsuri_name, EvaluateException from ZSI.wstools.Namespaces import SCHEMA, SOAP from ZSI.wstools.Utility import SplitQName def _get_type_definition(namespaceURI, name, **kw): return SchemaInstanceType.getTypeDefinition(namespaceURI, name, **kw) def _get_global_element_declaration(namespaceURI, name, **kw): return SchemaInstanceType.getElementDeclaration(namespaceURI, name, **kw) def _get_substitute_element(head, elt, ps): '''if elt matches a member of the head substitutionGroup, return the GED typecode. head -- ElementDeclaration typecode, elt -- the DOM element being parsed ps -- ParsedSoap Instance ''' if not isinstance(head, ElementDeclaration): return None return ElementDeclaration.getSubstitutionElement(head, elt, ps) def _has_type_definition(namespaceURI, name): return SchemaInstanceType.getTypeDefinition(namespaceURI, name) is not None def _is_substitute_element(head, sub): '''if head and sub are both GEDs, and sub declares head as its substitutionGroup then return True. head -- Typecode instance sub -- Typecode instance ''' if not isinstance(head, ElementDeclaration) or not isinstance(sub, ElementDeclaration): return False try: group = sub.substitutionGroup except (AttributeError, TypeError): return False ged = GED(*group) # TODO: better way of representing element references. Wrap them with # facets, and dereference when needed and delegate to.. print (head.nspname == ged.nspname and head.pname == ged.pname) if head is ged or not (head.nspname == ged.nspname and head.pname == ged.pname): return False return True # # functions for retrieving schema items from # the global schema instance. # GED = _get_global_element_declaration GTD = _get_type_definition def WrapImmutable(pyobj, what): '''Wrap immutable instance so a typecode can be set, making it self-describing ie. serializable. ''' return _GetPyobjWrapper.WrapImmutable(pyobj, what) def RegisterBuiltin(arg): '''Add a builtin to be registered, and register it with the Any typecode. ''' _GetPyobjWrapper.RegisterBuiltin(arg) _GetPyobjWrapper.RegisterAnyElement() def RegisterAnyElement(): '''register all Wrapper classes with the Any typecode. This allows instances returned by Any to be self-describing. ie. serializable. AnyElement falls back on Any to parse anything it doesn't understand. ''' return _GetPyobjWrapper.RegisterAnyElement() class SchemaInstanceType(type): '''Register all types/elements, when hit already defined class dont create a new one just give back reference. Thus import order determines which class is loaded. class variables: types -- dict of typecode classes definitions representing global type definitions. elements -- dict of typecode classes representing global element declarations. element_typecode_cache -- dict of typecode instances representing global element declarations. ''' types = {} elements = {} element_typecode_cache = {} #substitution_registry = {} def __new__(cls,classname,bases,classdict): '''If classdict has literal and schema register it as a element declaration, else if has type and schema register it as a type definition. ''' if classname in ['ElementDeclaration', 'TypeDefinition', 'LocalElementDeclaration',]: return type.__new__(cls,classname,bases,classdict) if ElementDeclaration in bases: if classdict.has_key('schema') is False or classdict.has_key('literal') is False: raise AttributeError, 'ElementDeclaration must define schema and literal attributes' key = (classdict['schema'],classdict['literal']) if SchemaInstanceType.elements.has_key(key): return SchemaInstanceType.elements[key] # create global element declaration ged = SchemaInstanceType.elements[key] = type.__new__(cls,classname,bases,classdict) # TODO: Maybe I want access to all registrants?? # #if classdict.has_key('substitutionGroup'): # sub = classdict.has_key('substitutionGroup') # if not SchemaInstanceType.substitution_registry.has_key(sub): # SchemaInstanceType.substitution_registry[sub] = [ged] # else: # SchemaInstanceType.substitution_registry[sub].append(ged) return ged if TypeDefinition in bases: if classdict.has_key('type') is None: raise AttributeError, 'TypeDefinition must define type attribute' key = classdict['type'] if SchemaInstanceType.types.has_key(key) is False: SchemaInstanceType.types[key] = type.__new__(cls,classname,bases,classdict) return SchemaInstanceType.types[key] if LocalElementDeclaration in bases: return type.__new__(cls,classname,bases,classdict) raise TypeError, 'SchemaInstanceType must be an ElementDeclaration or TypeDefinition ' def getTypeDefinition(cls, namespaceURI, name, lazy=False): '''Grab a type definition, returns a typecode class definition because the facets (name, minOccurs, maxOccurs) must be provided. Parameters: namespaceURI -- name -- ''' klass = cls.types.get((namespaceURI, name), None) if lazy and klass is not None: return _Mirage(klass) return klass getTypeDefinition = classmethod(getTypeDefinition) def getElementDeclaration(cls, namespaceURI, name, isref=False, lazy=False): '''Grab an element declaration, returns a typecode instance representation or a typecode class definition. An element reference has its own facets, and is local so it will not be cached. Parameters: namespaceURI -- name -- isref -- if element reference, return class definition. ''' key = (namespaceURI, name) if isref: klass = cls.elements.get(key,None) if klass is not None and lazy is True: return _Mirage(klass) return klass typecode = cls.element_typecode_cache.get(key, None) if typecode is None: tcls = cls.elements.get(key,None) if tcls is not None: typecode = cls.element_typecode_cache[key] = tcls() typecode.typed = False return typecode getElementDeclaration = classmethod(getElementDeclaration) class ElementDeclaration: '''Typecodes subclass to represent a Global Element Declaration by setting class variables schema and literal. schema = namespaceURI literal = NCName substitutionGroup -- GED reference of form, (namespaceURI,NCName) ''' __metaclass__ = SchemaInstanceType def checkSubstitute(self, typecode): '''If this is True, allow typecode to be substituted for "self" typecode. ''' if not isinstance(typecode, ElementDeclaration): return False try: nsuri,ncname = typecode.substitutionGroup except (AttributeError, TypeError): return False if (nsuri,ncname) != (self.schema,self.literal): # allow slop with the empty namespace if not nsuri and not self.schema and ncname == self.literal: return True return False sub = GED(self.schema, self.literal) if sub is None or sub is not typecode: return False return True def getSubstitutionElement(self, elt, ps): '''if elt matches a member of the head substitutionGroup, return the GED typecode representation of the member. head -- ElementDeclaration typecode, elt -- the DOM element being parsed ps -- ParsedSoap instance ''' nsuri,ncname = _get_element_nsuri_name(elt) typecode = GED(nsuri,ncname) if typecode is None: return try: nsuri,ncname = typecode.substitutionGroup except (AttributeError, TypeError): return if (ncname == self.pname) and (nsuri == self.nspname or (not nsuri and not self.nspname)): return typecode return class LocalElementDeclaration: '''Typecodes subclass to represent a Local Element Declaration. ''' __metaclass__ = SchemaInstanceType class TypeDefinition: '''Typecodes subclass to represent a Global Type Definition by setting class variable type. type = (namespaceURI, NCName) ''' __metaclass__ = SchemaInstanceType def getSubstituteType(self, elt, ps): '''if xsi:type does not match the instance type attr, check to see if it is a derived type substitution. DONT Return the element's type. Parameters: elt -- the DOM element being parsed ps -- the ParsedSoap object. ''' pyclass = SchemaInstanceType.getTypeDefinition(*self.type) if pyclass is None: raise EvaluateException( 'No Type registed for xsi:type=(%s, %s)' % (self.type[0], self.type[1]), ps.Backtrace(elt)) typeName = _find_type(elt) prefix,typeName = SplitQName(typeName) uri = ps.GetElementNSdict(elt).get(prefix) subclass = SchemaInstanceType.getTypeDefinition(uri, typeName) if subclass is None: raise EvaluateException( 'No registered xsi:type=(%s, %s), substitute for xsi:type=(%s, %s)' % (uri, typeName, self.type[0], self.type[1]), ps.Backtrace(elt)) if not issubclass(subclass, pyclass) and subclass(None) and not issubclass(subclass, pyclass): raise TypeError( 'Substitute Type (%s, %s) is not derived from %s' % (self.type[0], self.type[1], pyclass), ps.Backtrace(elt)) return subclass((self.nspname, self.pname)) class _Mirage: '''Used with SchemaInstanceType for lazy evaluation, eval during serialize or parse as needed. Mirage is callable, TypeCodes are not. When called it returns the typecode. Tightly coupled with generated code. NOTE: **Must Use ClassType** for intended MRO of __call__ since setting it in an instance attribute rather than a class attribute (will not work for object). ''' def __init__(self, klass): self.klass = klass self.__reveal = False self.__cache = None if issubclass(klass, ElementDeclaration): self.__call__ = self._hide_element def __str__(self): msg = "" if issubclass(self.klass, ElementDeclaration): msg = "" return msg %(id(self), self.klass) def _hide_type(self, pname, aname, minOccurs=0, maxOccurs=1, nillable=False, **kw): self.__call__ = self._reveal_type self.__reveal = True # store all attributes, make some visable for pyclass_type self.__kw = kw self.minOccurs,self.maxOccurs,self.nillable = minOccurs,maxOccurs,nillable self.nspname,self.pname,self.aname = None,pname,aname if type(self.pname) in (tuple,list): self.nspname,self.pname = pname return self def _hide_element(self, minOccurs=0, maxOccurs=1, nillable=False, **kw): self.__call__ = self._reveal_element self.__reveal = True # store all attributes, make some visable for pyclass_type self.__kw = kw self.nspname = self.klass.schema self.pname = self.klass.literal #TODO: Fix hack #self.aname = '_%s' %self.pname self.minOccurs,self.maxOccurs,self.nillable = minOccurs,maxOccurs,nillable return self def _reveal_type(self): if self.__cache is None: self.__cache = self.klass(pname=self.pname, aname=self.aname, minOccurs=self.minOccurs, maxOccurs=self.maxOccurs, nillable=self.nillable, **self.__kw) return self.__cache def _reveal_element(self): if self.__cache is None: self.__cache = self.klass(minOccurs=self.minOccurs, maxOccurs=self.maxOccurs, nillable=self.nillable, **self.__kw) return self.__cache __call__ = _hide_type class _GetPyobjWrapper: '''Get a python object that wraps data and typecode. Used by parse routine, so that typecode information discovered during parsing is retained in the pyobj representation and thus can be serialized. ''' types_dict = dict() def RegisterBuiltin(cls, arg): '''register a builtin, create a new wrapper. ''' if arg in cls.types_dict: raise RuntimeError, '%s already registered' %arg class _Wrapper(arg): 'Wrapper for builtin %s\n%s' %(arg, cls.__doc__) _Wrapper.__name__ = '_%sWrapper' %arg.__name__ cls.types_dict[arg] = _Wrapper RegisterBuiltin = classmethod(RegisterBuiltin) def RegisterAnyElement(cls): '''If find registered TypeCode instance, add Wrapper class to TypeCode class serialmap and Re-RegisterType. Provides Any serialzation of any instances of the Wrapper. ''' for k,v in cls.types_dict.items(): what = Any.serialmap.get(k) if what is None: continue if v in what.__class__.seriallist: continue what.__class__.seriallist.append(v) RegisterType(what.__class__, clobber=1, **what.__dict__) RegisterAnyElement = classmethod(RegisterAnyElement) def WrapImmutable(cls, pyobj, what): '''return a wrapper for pyobj, with typecode attribute set. Parameters: pyobj -- instance of builtin type (immutable) what -- typecode describing the data ''' d = cls.types_dict if type(pyobj) is bool: pyclass = d[int] elif d.has_key(type(pyobj)) is True: pyclass = d[type(pyobj)] else: raise TypeError,\ 'Expecting a built-in type in %s (got %s).' %( d.keys(),type(pyobj)) newobj = pyclass(pyobj) newobj.typecode = what return newobj WrapImmutable = classmethod(WrapImmutable) from TC import Any, RegisterType if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/auth.py0000644000175100017510000000344710314170035012500 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Simple CGI dispatching. ''' from ZSI import * from ZSI import _copyright import base64, os _b64_decode = base64.decodestring # Typecode to parse a ZSI BasicAuth header. _auth_tc = TC.Struct(None, [ TC.String('Name'), TC.String('Password') ], extras=1) class AUTH: '''Constants for authentication mechanisms. ''' none = 0 httpbasic = 1 zsibasic = 2 httpdigest = 4 class ClientBinding: '''Information about the client that is connected to us. ''' def __init__(self, ps): self.ps, self.auth = \ ps, None self.environ = os.environ.copy() self.environ['CONTENT_LENGTH'] = str(0) def GetAuth(self): '''Return a tuple containing client authentication data. ''' if self.auth: return self.auth for elt in self.ps.GetMyHeaderElements(): if elt.localName == 'BasicAuth' \ and elt.namespaceURI == ZSI_SCHEMA_URI: d = _auth_tc.parse(elt, self.ps) self.auth = (AUTH.zsibasic, d['Name'], d['Password']) return self.auth ba = self.environ.get('HTTP_AUTHENTICATION') if ba: ba = ba.split(' ') if len(ba) == 2 and ba[0].lower() == 'basic': ba = _b64_decode(ba[1]) self.auth = (AUTH.httpbasic,) + tuple(ba.split(':')) return self.auth self.auth = (AUTH.none,) return self.auth def GetNS(self): '''Return namespace for the top main request element. ''' return self.ps.body_root.namespaceURI or '' def GetRequest(self): '''Return the ParsedSoap request. ''' return self.ps if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/dispatch.py0000644000175100017510000002454610641306321013343 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Simple CGI dispatching. ''' import types, os, sys from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from ZSI import * from ZSI import _child_elements, _copyright, _seqtypes, _find_arraytype, _find_type, resolvers from ZSI.auth import _auth_tc, AUTH, ClientBinding # Client binding information is stored in a global. We provide an accessor # in case later on it's not. _client_binding = None def GetClientBinding(): '''Return the client binding object. ''' return _client_binding gettypecode = lambda mod,e: getattr(mod, str(e.localName)).typecode def _Dispatch(ps, modules, SendResponse, SendFault, nsdict={}, typesmodule=None, gettypecode=gettypecode, rpc=False, docstyle=False, **kw): '''Find a handler for the SOAP request in ps; search modules. Call SendResponse or SendFault to send the reply back, appropriately. Behaviors: default -- Call "handler" method with pyobj representation of body root, and return a self-describing request (w/typecode). Parsing done via a typecode from typesmodule, or Any. docstyle -- Call "handler" method with ParsedSoap instance and parse result with an XML typecode (DOM). Behavior, wrap result in a body_root "Response" appended message. rpc -- Specify RPC wrapper of result. Behavior, ignore body root (RPC Wrapper) of request, parse all "parts" of message via individual typecodes. Expect the handler to return the parts of the message, whether it is a dict, single instance, or a list try to serialize it as a Struct but if this is not possible put it in an Array. Parsing done via a typecode from typesmodule, or Any. ''' global _client_binding try: what = str(ps.body_root.localName) # See what modules have the element name. if modules is None: modules = ( sys.modules['__main__'], ) handlers = [ getattr(m, what) for m in modules if hasattr(m, what) ] if len(handlers) == 0: raise TypeError("Unknown method " + what) # Of those modules, see who's callable. handlers = [ h for h in handlers if callable(h) ] if len(handlers) == 0: raise TypeError("Unimplemented method " + what) if len(handlers) > 1: raise TypeError("Multiple implementations found: " + `handlers`) handler = handlers[0] _client_binding = ClientBinding(ps) if docstyle: result = handler(ps.body_root) tc = TC.XML(aslist=1, pname=what+'Response') elif not rpc: try: tc = gettypecode(typesmodule, ps.body_root) except Exception: tc = TC.Any() try: arg = tc.parse(ps.body_root, ps) except EvaluateException, ex: SendFault(FaultFromZSIException(ex), **kw) return try: result = handler(arg) except Exception,ex: SendFault(FaultFromZSIException(ex), **kw) return try: tc = result.typecode except AttributeError,ex: SendFault(FaultFromZSIException(ex), **kw) return elif typesmodule is not None: kwargs = {} for e in _child_elements(ps.body_root): try: tc = gettypecode(typesmodule, e) except Exception: tc = TC.Any() try: kwargs[str(e.localName)] = tc.parse(e, ps) except EvaluateException, ex: SendFault(FaultFromZSIException(ex), **kw) return result = handler(**kwargs) aslist = False # make sure data is wrapped, try to make this a Struct if type(result) in _seqtypes: for o in result: aslist = hasattr(result, 'typecode') if aslist: break elif type(result) is not dict: aslist = not hasattr(result, 'typecode') result = (result,) tc = TC.Any(pname=what+'Response', aslist=aslist) else: # if this is an Array, call handler with list # if this is an Struct, call handler with dict tp = _find_type(ps.body_root) isarray = ((type(tp) in (tuple,list) and tp[1] == 'Array') or _find_arraytype(ps.body_root)) data = _child_elements(ps.body_root) tc = TC.Any() if isarray and len(data) == 0: result = handler() elif isarray: try: arg = [ tc.parse(e, ps) for e in data ] except EvaluateException, e: #SendFault(FaultFromZSIException(e), **kw) SendFault(RuntimeError("THIS IS AN ARRAY: %s" %isarray)) return result = handler(*arg) else: try: kwarg = dict([ (str(e.localName),tc.parse(e, ps)) for e in data ]) except EvaluateException, e: SendFault(FaultFromZSIException(e), **kw) return result = handler(**kwarg) # reponse typecode #tc = getattr(result, 'typecode', TC.Any(pname=what+'Response')) tc = TC.Any(pname=what+'Response') sw = SoapWriter(nsdict=nsdict) sw.serialize(result, tc) return SendResponse(str(sw), **kw) except Fault, e: return SendFault(e, **kw) except Exception, e: # Something went wrong, send a fault. return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) def _ModPythonSendXML(text, code=200, **kw): req = kw['request'] req.content_type = 'text/xml' req.content_length = len(text) req.send_http_header() req.write(text) def _ModPythonSendFault(f, **kw): _ModPythonSendXML(f.AsSOAP(), 500, **kw) def _JonPySendFault(f, **kw): _JonPySendXML(f.AsSOAP(), 500, **kw) def _JonPySendXML(text, code=200, **kw): req = kw['request'] req.set_header("Content-Type", 'text/xml; charset="%s"' %UNICODE_ENCODING) req.set_header("Content-Length", str(len(text))) req.write(text) def _CGISendXML(text, code=200, **kw): print 'Status: %d' % code print 'Content-Type: text/xml; charset="%s"' %UNICODE_ENCODING print 'Content-Length: %d' % len(text) print '' print text def _CGISendFault(f, **kw): _CGISendXML(f.AsSOAP(), 500, **kw) class SOAPRequestHandler(BaseHTTPRequestHandler): '''SOAP handler. ''' server_version = 'ZSI/1.1 ' + BaseHTTPRequestHandler.server_version def send_xml(self, text, code=200): '''Send some XML. ''' self.send_response(code) if text: self.send_header('Content-type', 'text/xml; charset="%s"' %UNICODE_ENCODING) self.send_header('Content-Length', str(len(text))) self.end_headers() if text: self.wfile.write(text) self.wfile.flush() def send_fault(self, f, code=500): '''Send a fault. ''' self.send_xml(f.AsSOAP(), code) def do_POST(self): '''The POST command. ''' try: ct = self.headers['content-type'] if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, self.rfile) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(self.headers['content-length']) ps = ParsedSoap(self.rfile.read(length)) except ParseException, e: self.send_fault(FaultFromZSIException(e)) return except Exception, e: # Faulted while processing; assume it's in the header. self.send_fault(FaultFromException(e, 1, sys.exc_info()[2])) return _Dispatch(ps, self.server.modules, self.send_xml, self.send_fault, docstyle=self.server.docstyle, nsdict=self.server.nsdict, typesmodule=self.server.typesmodule, rpc=self.server.rpc) def AsServer(port=80, modules=None, docstyle=False, nsdict={}, typesmodule=None, rpc=False, addr=''): address = (addr, port) httpd = HTTPServer(address, SOAPRequestHandler) httpd.modules = modules httpd.docstyle = docstyle httpd.nsdict = nsdict httpd.typesmodule = typesmodule httpd.rpc = rpc httpd.serve_forever() def AsCGI(nsdict={}, typesmodule=None, rpc=False, modules=None): '''Dispatch within a CGI script. ''' if os.environ.get('REQUEST_METHOD') != 'POST': _CGISendFault(Fault(Fault.Client, 'Must use POST')) return ct = os.environ['CONTENT_TYPE'] try: if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, sys.stdin) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(os.environ['CONTENT_LENGTH']) ps = ParsedSoap(sys.stdin.read(length)) except ParseException, e: _CGISendFault(FaultFromZSIException(e)) return _Dispatch(ps, modules, _CGISendXML, _CGISendFault, nsdict=nsdict, typesmodule=typesmodule, rpc=rpc) def AsHandler(request=None, modules=None, **kw): '''Dispatch from within ModPython.''' ps = ParsedSoap(request) kw['request'] = request _Dispatch(ps, modules, _ModPythonSendXML, _ModPythonSendFault, **kw) def AsJonPy(request=None, modules=None, **kw): '''Dispatch within a jonpy CGI/FastCGI script. ''' kw['request'] = request if request.environ.get('REQUEST_METHOD') != 'POST': _JonPySendFault(Fault(Fault.Client, 'Must use POST'), **kw) return ct = request.environ['CONTENT_TYPE'] try: if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, request.stdin) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(request.environ['CONTENT_LENGTH']) ps = ParsedSoap(request.stdin.read(length)) except ParseException, e: _JonPySendFault(FaultFromZSIException(e), **kw) return _Dispatch(ps, modules, _JonPySendXML, _JonPySendFault, **kw) if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/TCapache.py0000644000175100017510000000417110365246140013211 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Apache typecodes. ''' from ZSI import _copyright, _child_elements, _get_idstr from ZSI.TC import TypeCode, Struct as _Struct, Any as _Any class Apache: NS = "http://xml.apache.org/xml-soap" class _Map(TypeCode): '''Apache's "Map" type. ''' parselist = [ (Apache.NS, 'Map') ] def __init__(self, pname=None, aslist=0, **kw): TypeCode.__init__(self, pname, **kw) self.aslist = aslist self.tc = _Struct(None, [ _Any('key'), _Any('value') ], inline=1) def parse(self, elt, ps): self.checkname(elt, ps) if self.nilled(elt, ps): return None p = self.tc.parse if self.aslist: v = [] for c in _child_elements(elt): d = p(c, ps) v.append((d['key'], d['value'])) else: v = {} for c in _child_elements(elt): d = p(c, ps) v[d['key']] = d['value'] return v def serialize(self, elt, sw, pyobj, name=None, **kw): objid = _get_idstr(pyobj) n = name or self.pname or ('E' + objid) # nillable el = elt.createAppendElement(self.nspname, n) if self.nillable is True and pyobj is None: self.serialize_as_nil(el) return None # other attributes self.set_attributes(el, pyobj) # soap href attribute unique = self.unique or kw.get('unique', False) if unique is False and sw.Known(orig or pyobj): self.set_attribute_href(el, objid) return None # xsi:type attribute if kw.get('typed', self.typed) is True: self.set_attribute_xsi_type(el, **kw) # soap id attribute if self.unique is False: self.set_attribute_id(el, objid) if self.aslist: for k,v in pyobj: self.tc.serialize(el, sw, {'key': k, 'value': v}, name='item') else: for k,v in pyobj.items(): self.tc.serialize(el, sw, {'key': k, 'value': v}, name='item') Apache.Map = _Map if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/__init__.py0000644000175100017510000003627010641306321013300 0ustar zsizsi#! /usr/bin/env python # $Header$ '''ZSI: Zolera Soap Infrastructure. Copyright 2001, Zolera Systems, Inc. All Rights Reserved. ''' _copyright = """ZSI: Zolera Soap Infrastructure. Copyright 2001, Zolera Systems, Inc. All Rights Reserved. Copyright 2002-2003, Rich Salz. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. Portions are also: Copyright (c) 2003, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such Enhancements or derivative works thereof, in binary and source code form. For wstools also: Zope Public License (ZPL) Version 2.0 ----------------------------------------------- This software is Copyright (c) Zope Corporation (tm) and Contributors. All rights reserved. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name Zope Corporation (tm) must not be used to endorse or promote products derived from this software without prior written permission from Zope Corporation. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of Zope Corporation. Use of them is covered in a separate agreement (see http://www.zope.com/Marks). 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of contributions made by Zope Corporation and many individuals on behalf of Zope Corporation. Specific attributions are listed in the accompanying credits file. """ ## ## Stuff imported from elsewhere. from xml.dom import Node as _Node import types as _types ## ## Public constants. from ZSI.wstools.Namespaces import ZSI_SCHEMA_URI UNICODE_ENCODING = 'utf-8' ## ## Not public constants. _inttypes = [ _types.IntType, _types.LongType ] _floattypes = [ _types.FloatType ] _seqtypes = [ _types.TupleType, _types.ListType ] _stringtypes = [ _types.StringType, _types.UnicodeType ] ## ## Low-level DOM oriented utilities; useful for typecode implementors. _attrs = lambda E: (E.attributes and E.attributes.values()) or [] _children = lambda E: E.childNodes or [] _child_elements = lambda E: [ n for n in (E.childNodes or []) if n.nodeType == _Node.ELEMENT_NODE ] ## ## Stuff imported from elsewhere. from ZSI.wstools.Namespaces import SOAP as _SOAP, SCHEMA as _SCHEMA, XMLNS as _XMLNS ## ## Low-level DOM oriented utilities; useful for typecode implementors. _find_arraytype = lambda E: E.getAttributeNS(_SOAP.ENC, "arrayType") _find_encstyle = lambda E: E.getAttributeNS(_SOAP.ENV, "encodingStyle") try: from xml.dom import EMPTY_NAMESPACE _empty_nsuri_list = [ EMPTY_NAMESPACE ] #if '' not in _empty_nsuri_list: __empty_nsuri_list.append('') #if None not in _empty_nsuri_list: __empty_nsuri_list.append(None) except: _empty_nsuri_list = [ None, '' ] def _find_attr(E, attr): for nsuri in _empty_nsuri_list: try: v = E.getAttributeNS(nsuri, attr) if v: return v except: pass return None def _find_attrNS(E, namespaceURI, localName): '''namespaceURI localName ''' try: v = E.getAttributeNS(namespaceURI, localName) if v: return v except: pass return None def _find_attrNodeNS(E, namespaceURI, localName): '''Must grab the attribute Node to distinquish between an unspecified attribute(None) and one set to empty string(""). namespaceURI localName ''' attr = E.getAttributeNodeNS(namespaceURI, localName) if attr is None: return None try: return attr.value except: pass return E.getAttributeNS(namespaceURI, localName) _find_href = lambda E: _find_attr(E, "href") _find_xsi_attr = lambda E, attr: \ E.getAttributeNS(_SCHEMA.XSI3, attr) \ or E.getAttributeNS(_SCHEMA.XSI1, attr) \ or E.getAttributeNS(_SCHEMA.XSI2, attr) _find_type = lambda E: _find_xsi_attr(E, "type") _find_xmlns_prefix = lambda E, attr: E.getAttributeNS(_XMLNS.BASE, attr) _find_default_namespace = lambda E: E.getAttributeNS(_XMLNS.BASE, None) #_textprotect = lambda s: s.replace('&', '&').replace('<', '<') _get_element_nsuri_name = lambda E: (E.namespaceURI, E.localName) _is_element = lambda E: E.nodeType == _Node.ELEMENT_NODE def _resolve_prefix(celt, prefix): '''resolve prefix to a namespaceURI. If None or empty str, return default namespace or None. Parameters: celt -- element node prefix -- xmlns:prefix, or empty str or None ''' namespace = None while _is_element(celt): if prefix: namespaceURI = _find_xmlns_prefix(celt, prefix) else: namespaceURI = _find_default_namespace(celt) if namespaceURI: break celt = celt.parentNode else: if prefix: raise EvaluateException, 'cant resolve xmlns:%s' %prefix return namespaceURI def _valid_encoding(elt): '''Does this node have a valid encoding? ''' enc = _find_encstyle(elt) if not enc or enc == _SOAP.ENC: return 1 for e in enc.split(): if e.startswith(_SOAP.ENC): # XXX Is this correct? Once we find a Sec5 compatible # XXX encoding, should we check that all the rest are from # XXX that same base? Perhaps. But since the if test above # XXX will surely get 99% of the cases, leave it for now. return 1 return 0 def _backtrace(elt, dom): '''Return a "backtrace" from the given element to the DOM root, in XPath syntax. ''' s = '' while elt != dom: name, parent = elt.nodeName, elt.parentNode if parent is None: break matches = [ c for c in _child_elements(parent) if c.nodeName == name ] if len(matches) == 1: s = '/' + name + s else: i = matches.index(elt) + 1 s = ('/%s[%d]' % (name, i)) + s elt = parent return s def _get_idstr(pyobj): '''Python 2.3.x generates a FutureWarning for negative IDs, so we use a different prefix character to ensure uniqueness, and call abs() to avoid the warning.''' x = id(pyobj) if x < 0: return 'x%x' % abs(x) return 'o%x' % x def _get_postvalue_from_absoluteURI(url): """Bug [ 1513000 ] POST Request-URI not limited to "abs_path" Request-URI = "*" | absoluteURI | abs_path | authority Not a complete solution, but it seems to work with all known implementations. ValueError thrown if bad uri. """ cache = _get_postvalue_from_absoluteURI.cache path = cache.get(url, '') if not path: scheme,authpath = url.split('://') s = authpath.split('/', 1) if len(s) == 2: path = '/%s' %s[1] if len(cache) > _get_postvalue_from_absoluteURI.MAXLEN:cache.clear() cache[url] = path return path _get_postvalue_from_absoluteURI.cache = {} _get_postvalue_from_absoluteURI.MAXLEN = 20 ## ## Exception classes. class ZSIException(Exception): '''Base class for all ZSI exceptions. ''' pass class ParseException(ZSIException): '''Exception raised during parsing. ''' def __init__(self, str, inheader, elt=None, dom=None): Exception.__init__(self) self.str, self.inheader, self.trace = str, inheader, None if elt and dom: self.trace = _backtrace(elt, dom) def __str__(self): if self.trace: return self.str + '\n[Element trace: ' + self.trace + ']' return self.str def __repr__(self): return "<%s.ParseException %s>" % (__name__, _get_idstr(self)) class EvaluateException(ZSIException): '''Exception raised during data evaluation (serialization). ''' def __init__(self, str, trace=None): Exception.__init__(self) self.str, self.trace = str, trace def __str__(self): if self.trace: return self.str + '\n[Element trace: ' + self.trace + ']' return self.str def __repr__(self): return "<%s.EvaluateException %s>" % (__name__, _get_idstr(self)) class FaultException(ZSIException): '''Exception raised when a fault is received. ''' def __init__(self, fault): self.fault = fault def __str__(self): return str(self.fault) def __repr__(self): return "<%s.FaultException %s>" % (__name__, _get_idstr(self)) class WSActionException(ZSIException): '''Exception raised when WS-Address Action Header is incorrectly specified when received by client or server. ''' pass ## ## Importing the rest of ZSI. import version def Version(): return version.Version from writer import SoapWriter from parse import ParsedSoap from fault import Fault, \ FaultFromActor, FaultFromException, FaultFromFaultMessage, \ FaultFromNotUnderstood, FaultFromZSIException import TC TC.RegisterType(TC.String, minOccurs=0, nillable=False) TC.RegisterType(TC.URI, minOccurs=0, nillable=False) TC.RegisterType(TC.Base64String, minOccurs=0, nillable=False) TC.RegisterType(TC.HexBinaryString, minOccurs=0, nillable=False) #TC.RegisterType(TC.Integer) #TC.RegisterType(TC.Decimal) for pyclass in (TC.IunsignedByte, TC.IunsignedShort, TC.IunsignedInt, TC.IunsignedLong, TC.Ibyte, TC.Ishort, TC.Iint, TC.Ilong, TC.InegativeInteger, TC.InonPositiveInteger, TC.InonNegativeInteger, TC.IpositiveInteger, TC.Iinteger, TC.FPfloat, TC.FPdouble, ): TC.RegisterType(pyclass, minOccurs=0, nillable=False) TC.RegisterType(TC.Boolean, minOccurs=0, nillable=False) TC.RegisterType(TC.Duration, minOccurs=0, nillable=False) TC.RegisterType(TC.gDateTime, minOccurs=0, nillable=False) TC.RegisterType(TC.gDate, minOccurs=0, nillable=False) TC.RegisterType(TC.gYearMonth, minOccurs=0, nillable=False) TC.RegisterType(TC.gYear, minOccurs=0, nillable=False) TC.RegisterType(TC.gMonthDay, minOccurs=0, nillable=False) TC.RegisterType(TC.gDay, minOccurs=0, nillable=False) TC.RegisterType(TC.gTime, minOccurs=0, nillable=False) TC.RegisterType(TC.Apache.Map, minOccurs=0, nillable=False) ## ## Register Wrappers for builtin types. ## TC.AnyElement wraps builtins so element name information can be saved ## import schema for i in [int,float,str,tuple,list,unicode]: schema._GetPyobjWrapper.RegisterBuiltin(i) ## Load up Wrappers for builtin types schema.RegisterAnyElement() #try: # from ServiceProxy import * #except: # pass if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/writer.py0000644000175100017510000001443310602267217013061 0ustar zsizsi#! /usr/bin/env python # $Id: writer.py 1367 2007-03-27 19:20:47Z boverhof $ '''SOAP message serialization. ''' from ZSI import _copyright, _get_idstr, ZSI_SCHEMA_URI from ZSI import _backtrace, _stringtypes, _seqtypes from ZSI.wstools.Utility import MessageInterface, ElementProxy from ZSI.wstools.Namespaces import XMLNS, SOAP, SCHEMA from ZSI.wstools.c14n import Canonicalize import types _standard_ns = [ ('xml', XMLNS.XML), ('xmlns', XMLNS.BASE) ] _reserved_ns = { 'SOAP-ENV': SOAP.ENV, 'SOAP-ENC': SOAP.ENC, 'ZSI': ZSI_SCHEMA_URI, 'xsd': SCHEMA.BASE, 'xsi': SCHEMA.BASE + '-instance', } class SoapWriter: '''SOAP output formatter. Instance Data: memo -- memory for id/href envelope -- add Envelope? encodingStyle -- header -- add SOAP Header? outputclass -- ElementProxy class. ''' def __init__(self, envelope=True, encodingStyle=None, header=True, nsdict={}, outputclass=None, **kw): '''Initialize. ''' outputclass = outputclass or ElementProxy if not issubclass(outputclass, MessageInterface): raise TypeError, 'outputclass must subclass MessageInterface' self.dom, self.memo, self.nsdict= \ outputclass(self), [], nsdict self.envelope = envelope self.encodingStyle = encodingStyle self.header = header self.body = None self.callbacks = [] self.closed = False def __str__(self): self.close() return str(self.dom) def getSOAPHeader(self): if self.header in (True, False): return None return self.header def serialize_header(self, pyobj, typecode=None, **kw): '''Serialize a Python object in SOAP-ENV:Header, make sure everything in Header unique (no #href). Must call serialize first to create a document. Parameters: pyobjs -- instances to serialize in SOAP Header typecode -- default typecode ''' kw['unique'] = True soap_env = _reserved_ns['SOAP-ENV'] #header = self.dom.getElement(soap_env, 'Header') header = self._header if header is None: header = self._header = self.dom.createAppendElement(soap_env, 'Header') typecode = getattr(pyobj, 'typecode', typecode) if typecode is None: raise RuntimeError( 'typecode is required to serialize pyobj in header') helt = typecode.serialize(header, self, pyobj, **kw) def serialize(self, pyobj, typecode=None, root=None, header_pyobjs=(), **kw): '''Serialize a Python object to the output stream. pyobj -- python instance to serialize in body. typecode -- typecode describing body root -- SOAP-ENC:root header_pyobjs -- list of pyobj for soap header inclusion, each instance must specify the typecode attribute. ''' self.body = None if self.envelope: soap_env = _reserved_ns['SOAP-ENV'] self.dom.createDocument(soap_env, 'Envelope') for prefix, nsuri in _reserved_ns.items(): self.dom.setNamespaceAttribute(prefix, nsuri) self.writeNSdict(self.nsdict) if self.encodingStyle: self.dom.setAttributeNS(soap_env, 'encodingStyle', self.encodingStyle) if self.header: self._header = self.dom.createAppendElement(soap_env, 'Header') for h in header_pyobjs: self.serialize_header(h, **kw) self.body = self.dom.createAppendElement(soap_env, 'Body') else: self.dom.createDocument(None,None) if typecode is None: typecode = pyobj.__class__.typecode if self.body is None: elt = typecode.serialize(self.dom, self, pyobj, **kw) else: elt = typecode.serialize(self.body, self, pyobj, **kw) if root is not None: if root not in [ 0, 1 ]: raise ValueError, "SOAP-ENC root attribute not in [0,1]" elt.setAttributeNS(SOAP.ENC, 'root', root) return self def writeNSdict(self, nsdict): '''Write a namespace dictionary, taking care to not clobber the standard (or reserved by us) prefixes. ''' for k,v in nsdict.items(): if (k,v) in _standard_ns: continue rv = _reserved_ns.get(k) if rv: if rv != v: raise KeyError("Reserved namespace " + str((k,v)) + " used") continue if k: self.dom.setNamespaceAttribute(k, v) else: self.dom.setNamespaceAttribute('xmlns', v) def ReservedNS(self, prefix, uri): '''Is this namespace (prefix,uri) reserved by us? ''' return _reserved_ns.get(prefix, uri) != uri def AddCallback(self, func, *arglist): '''Add a callback function and argument list to be invoked before closing off the SOAP Body. ''' self.callbacks.append((func, arglist)) def Known(self, obj): '''Seen this object (known by its id()? Return 1 if so, otherwise add it to our memory and return 0. ''' obj = _get_idstr(obj) if obj in self.memo: return 1 self.memo.append(obj) return 0 def Forget(self, obj): '''Forget we've seen this object. ''' obj = _get_idstr(obj) try: self.memo.remove(obj) except ValueError: pass def Backtrace(self, elt): '''Return a human-readable "backtrace" from the document root to the specified element. ''' return _backtrace(elt._getNode(), self.dom._getNode()) def close(self): '''Invoke all the callbacks, and close off the SOAP message. ''' if self.closed: return for func,arglist in self.callbacks: apply(func, arglist) self.closed = True def __del__(self): if not self.closed: self.close() if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/typeinterpreter.py0000644000175100017510000001120010425515732015000 0ustar zsizsi########################################################################### # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import ZSI from ZSI import TC, TCtimes, TCcompound from ZSI.TC import TypeCode from ZSI import _copyright, EvaluateException from ZSI.wstools.Utility import SplitQName from ZSI.wstools.Namespaces import SOAP, SCHEMA ########################################################################### # Module Classes: BaseTypeInterpreter ########################################################################### class NamespaceException(Exception): pass class BaseTypeInterpreter: """Example mapping of xsd/soapenc types to zsi python types. Checks against all available classes in ZSI.TC. Used in wsdl2python, wsdlInterpreter, and ServiceProxy. """ def __init__(self): self._type_list = [TC.Iinteger, TC.IunsignedShort, TC.gYearMonth, \ TC.InonNegativeInteger, TC.Iint, TC.String, \ TC.gDateTime, TC.IunsignedInt, TC.Duration,\ TC.IpositiveInteger, TC.FPfloat, TC.gDay, TC.gMonth, \ TC.InegativeInteger, TC.gDate, TC.URI, \ TC.HexBinaryString, TC.IunsignedByte, \ TC.gMonthDay, TC.InonPositiveInteger, \ TC.Ibyte, TC.FPdouble, TC.gTime, TC.gYear, \ TC.Ilong, TC.IunsignedLong, TC.Ishort, \ TC.Token, TC.QName] self._tc_to_int = [ ZSI.TCnumbers.IEnumeration, ZSI.TCnumbers.Iint, ZSI.TCnumbers.Iinteger, ZSI.TCnumbers.Ilong, ZSI.TCnumbers.InegativeInteger, ZSI.TCnumbers.InonNegativeInteger, ZSI.TCnumbers.InonPositiveInteger, ZSI.TC.Integer, ZSI.TCnumbers.IpositiveInteger, ZSI.TCnumbers.Ishort] self._tc_to_float = [ ZSI.TC.Decimal, ZSI.TCnumbers.FPEnumeration, ZSI.TCnumbers.FPdouble, ZSI.TCnumbers.FPfloat] self._tc_to_string = [ ZSI.TC.Base64String, ZSI.TC.Enumeration, ZSI.TC.HexBinaryString, ZSI.TCnumbers.Ibyte, ZSI.TCnumbers.IunsignedByte, ZSI.TCnumbers.IunsignedInt, ZSI.TCnumbers.IunsignedLong, ZSI.TCnumbers.IunsignedShort, ZSI.TC.String, ZSI.TC.URI, ZSI.TC.XMLString, ZSI.TC.Token] self._tc_to_tuple = [ ZSI.TC.Duration, ZSI.TC.QName, ZSI.TCtimes.gDate, ZSI.TCtimes.gDateTime, ZSI.TCtimes.gDay, ZSI.TCtimes.gMonthDay, ZSI.TCtimes.gTime, ZSI.TCtimes.gYear, ZSI.TCtimes.gMonth, ZSI.TCtimes.gYearMonth] return def _get_xsd_typecode(self, msg_type): untaged_xsd_types = {'boolean':TC.Boolean, 'decimal':TC.Decimal, 'base64Binary':TC.Base64String} if untaged_xsd_types.has_key(msg_type): return untaged_xsd_types[msg_type] for tc in self._type_list: if tc.type == (SCHEMA.XSD3,msg_type): break else: tc = TC.AnyType return tc def _get_soapenc_typecode(self, msg_type): if msg_type == 'Array': return TCcompound.Array if msg_type == 'Struct': return TCcompound.Struct return self._get_xsd_typecode(msg_type) def get_typeclass(self, msg_type, targetNamespace): prefix, name = SplitQName(msg_type) if targetNamespace in SCHEMA.XSD_LIST: return self._get_xsd_typecode(name) elif targetNamespace in [SOAP.ENC]: return self._get_soapenc_typecode(name) return None def get_pythontype(self, msg_type, targetNamespace, typeclass=None): if not typeclass: tc = self.get_typeclass(msg_type, targetNamespace) else: tc = typeclass if tc in self._tc_to_int: return 'int' elif tc in self._tc_to_float: return 'float' elif tc in self._tc_to_string: return 'str' elif tc in self._tc_to_tuple: return 'tuple' elif tc in [TCcompound.Array]: return 'list' elif tc in [TC.Boolean]: return 'bool' elif isinstance(tc, TypeCode): raise EvaluateException,\ 'failed to map zsi typecode to a python type' return None ZSI-2.1-a1/ZSI/TCcompound.py0000644000175100017510000006434010700251315013611 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Compound typecodes. ''' from ZSI import _copyright, _children, _child_elements, \ _inttypes, _stringtypes, _seqtypes, _find_arraytype, _find_href, \ _find_type, _find_xmlns_prefix, _get_idstr, EvaluateException, \ ParseException from TC import _get_element_nsuri_name, \ _get_xsitype, TypeCode, Any, AnyElement, AnyType, \ Nilled, UNBOUNDED from schema import GED, ElementDeclaration, TypeDefinition, \ _get_substitute_element, _get_type_definition, _is_substitute_element from ZSI.wstools.Namespaces import SCHEMA, SOAP from ZSI.wstools.Utility import SplitQName from ZSI.wstools.logging import getLogger as _GetLogger import re, types from copy import copy as _copy _find_arrayoffset = lambda E: E.getAttributeNS(SOAP.ENC, "offset") _find_arrayposition = lambda E: E.getAttributeNS(SOAP.ENC, "position") _offset_pat = re.compile(r'\[[0-9]+\]') _position_pat = _offset_pat def _check_typecode_list(ofwhat, tcname): '''Check a list of typecodes for compliance with Struct requirements.''' for o in ofwhat: if callable(o): #skip if _Mirage continue if not isinstance(o, TypeCode): raise TypeError( tcname + ' ofwhat outside the TypeCode hierarchy, ' + str(o.__class__)) if o.pname is None and not isinstance(o, AnyElement): raise TypeError(tcname + ' element ' + str(o) + ' has no name') def _get_type_or_substitute(typecode, pyobj, sw, elt): '''return typecode or substitute type for wildcard or derived type. For serialization only. ''' sub = getattr(pyobj, 'typecode', typecode) if sub is typecode or sub is None: return typecode # Element WildCard if isinstance(typecode, AnyElement): return sub # Global Element Declaration if isinstance(sub, ElementDeclaration): if (typecode.nspname,typecode.pname) == (sub.nspname,sub.pname): raise TypeError(\ 'bad usage, failed to serialize element reference (%s, %s), in: %s' % (typecode.nspname, typecode.pname, sw.Backtrace(elt),)) # check substitutionGroup if _is_substitute_element(typecode, sub): return sub raise TypeError(\ 'failed to serialize (%s, %s) illegal sub GED (%s,%s): %s' % (typecode.nspname, typecode.pname, sub.nspname, sub.pname, sw.Backtrace(elt),)) # Local Element if not isinstance(typecode, AnyType) and not isinstance(sub, typecode.__class__): raise TypeError(\ 'failed to serialize substitute %s for %s, not derivation: %s' % (sub, typecode, sw.Backtrace(elt),)) # Make our substitution type match the elements facets, # since typecode is created for a single existing pyobj # some facets are irrelevant. sub = _copy(sub) sub.nspname = typecode.nspname sub.pname = typecode.pname sub.aname = typecode.aname sub.minOccurs = sub.maxOccurs = 1 return sub class ComplexType(TypeCode): '''Represents an element of complexType, potentially containing other elements. ''' logger = _GetLogger('ZSI.TCcompound.ComplexType') def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, mutable=True, mixed=False, mixed_aname='_text', **kw): '''pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the complexType inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations type -- the (URI,localname) of the datatype mixed -- mixed content model? True/False mixed_aname -- if mixed is True, specify text content here. Default _text ''' TypeCode.__init__(self, pname, pyclass=pyclass, **kw) self.inorder = inorder self.inline = inline self.mutable = mutable self.mixed = mixed self.mixed_aname = None if mixed is True: self.mixed_aname = mixed_aname if self.mutable is True: self.inline = True self.type = kw.get('type') or _get_xsitype(self) t = type(ofwhat) if t not in _seqtypes: raise TypeError( 'Struct ofwhat must be list or sequence, not ' + str(t)) self.ofwhat = tuple(ofwhat) if TypeCode.typechecks: # XXX Not sure how to determine if new-style class.. if self.pyclass is not None and \ type(self.pyclass) is not types.ClassType and not isinstance(self.pyclass, object): raise TypeError('pyclass must be None or an old-style/new-style class, not ' + str(type(self.pyclass))) _check_typecode_list(self.ofwhat, 'ComplexType') def parse(self, elt, ps): debug = self.logger.debugOn() debug and self.logger.debug('parse') xtype = self.checkname(elt, ps) if self.type and xtype not in [ self.type, (None,None) ]: if not isinstance(self, TypeDefinition): raise EvaluateException(\ 'ComplexType for %s has wrong type(%s), looking for %s' % (self.pname, self.checktype(elt,ps), self.type), ps.Backtrace(elt)) else: #TODO: mabye change MRO to handle this debug and self.logger.debug('delegate to substitute type') what = TypeDefinition.getSubstituteType(self, elt, ps) return what.parse(elt, ps) href = _find_href(elt) if href: if _children(elt): raise EvaluateException('Struct has content and HREF', ps.Backtrace(elt)) elt = ps.FindLocalHREF(href, elt) c = _child_elements(elt) count = len(c) if self.nilled(elt, ps): return Nilled # Create the object. v = {} # parse all attributes contained in attribute_typecode_dict (user-defined attributes), # the values (if not None) will be keyed in self.attributes dictionary. attributes = self.parse_attributes(elt, ps) if attributes: v[self.attrs_aname] = attributes #MIXED if self.mixed is True: v[self.mixed_aname] = self.simple_value(elt,ps, mixed=True) # Clone list of kids (we null it out as we process) c, crange = c[:], range(len(c)) # Loop over all items we're expecting if debug: self.logger.debug("ofwhat: %s",str(self.ofwhat)) any = None for i,what in [ (i, self.ofwhat[i]) for i in range(len(self.ofwhat)) ]: # retrieve typecode if it is hidden if callable(what): what = what() # Loop over all available kids if debug: self.logger.debug("what: (%s,%s)", what.nspname, what.pname) for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]: # Parse value, and mark this one done. if debug: self.logger.debug("child node: (%s,%s)", c_elt.namespaceURI, c_elt.tagName) match = False if what.name_match(c_elt): match = True value = what.parse(c_elt, ps) else: # substitutionGroup head must be a global element declaration # if successful delegate to matching GED subwhat = _get_substitute_element(what, c_elt, ps) if subwhat: match = True value = subwhat.parse(c_elt, ps) if debug: self.logger.debug("substitutionGroup: %s", subwhat) if match: if what.maxOccurs > 1: if v.has_key(what.aname): v[what.aname].append(value) else: v[what.aname] = [value] c[j] = None continue else: v[what.aname] = value c[j] = None break if debug: self.logger.debug("no element (%s,%s)", what.nspname, what.pname) # No match; if it was supposed to be here, that's an error. if self.inorder is True and i == j: raise EvaluateException('Out of order complexType', ps.Backtrace(c_elt)) else: # only supporting 1 declaration in content. if isinstance(what,AnyElement): any = what elif hasattr(what, 'default'): v[what.aname] = what.default elif what.minOccurs > 0 and not v.has_key(what.aname): raise EvaluateException('Element "' + what.aname + \ '" missing from complexType', ps.Backtrace(elt)) # Look for wildcards and unprocessed children # XXX Stick all this stuff in "any", hope for no collisions if any is not None: occurs = 0 v[any.aname] = [] for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]: value = any.parse(c_elt, ps) if any.maxOccurs == UNBOUNDED or any.maxOccurs > 1: v[any.aname].append(value) else: v[any.aname] = value occurs += 1 # No such thing as nillable if any.maxOccurs == 1 and occurs == 0: v[any.aname] = None elif occurs < any.minOccurs or (any.maxOccurs!=UNBOUNDED and any.maxOccurs elements(#%d) bound by (%d,%s)' %( occurs, any.minOccurs,str(any.maxOccurs)), ps.Backtrace(elt)) if not self.pyclass: return v # type definition must be informed of element tag (nspname,pname), # element declaration is initialized with a tag. try: pyobj = self.pyclass() except Exception, e: raise TypeError("Constructing element (%s,%s) with pyclass(%s), %s" \ %(self.nspname, self.pname, self.pyclass.__name__, str(e))) for key in v.keys(): setattr(pyobj, key, v[key]) return pyobj def serialize(self, elt, sw, pyobj, inline=False, name=None, **kw): if inline or self.inline: self.cb(elt, sw, pyobj, name=name, **kw) else: objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) el = elt.createAppendElement(ns, n) el.setAttributeNS(None, 'href', "#%s" %objid) sw.AddCallback(self.cb, elt, sw, pyobj) def cb(self, elt, sw, pyobj, name=None, **kw): debug = self.logger.debugOn() if debug: self.logger.debug("cb: %s" %str(self.ofwhat)) objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) if pyobj is None: if self.nillable is True: elem = elt.createAppendElement(ns, n) self.serialize_as_nil(elem) return raise EvaluateException, 'element(%s,%s) is not nillable(%s)' %( self.nspname,self.pname,self.nillable) if self.mutable is False and sw.Known(pyobj): return if debug: self.logger.debug("element: (%s, %s)", str(ns), n) if n is not None: elem = elt.createAppendElement(ns, n) self.set_attributes(elem, pyobj) if kw.get('typed', self.typed) is True: self.set_attribute_xsi_type(elem) #MIXED For now just stick it in front. if self.mixed is True and self.mixed_aname is not None: if hasattr(pyobj, self.mixed_aname): textContent = getattr(pyobj, self.mixed_aname) if hasattr(textContent, 'typecode'): textContent.typecode.serialize_text_node(elem, sw, textContent) elif type(textContent) in _stringtypes: if debug: self.logger.debug("mixed text content:\n\t%s", textContent) elem.createAppendTextNode(textContent) else: raise EvaluateException('mixed test content in element (%s,%s) must be a string type' %( self.nspname,self.pname), sw.Backtrace(elt)) else: if debug: self.logger.debug("mixed NO text content in %s", self.mixed_aname) else: #For information items w/o tagNames # ie. model groups,SOAP-ENC:Header elem = elt if self.inline: pass elif not self.inline and self.unique: raise EvaluateException('Not inline, but unique makes no sense. No href/id.', sw.Backtrace(elt)) elif n is not None: self.set_attribute_id(elem, objid) if self.pyclass and type(self.pyclass) is type: f = lambda attr: getattr(pyobj, attr, None) elif self.pyclass: d = pyobj.__dict__ f = lambda attr: d.get(attr) else: d = pyobj f = lambda attr: pyobj.get(attr) if TypeCode.typechecks and type(d) != types.DictType: raise TypeError("Classless complexType didn't get dictionary") indx, lenofwhat = 0, len(self.ofwhat) if debug: self.logger.debug('element declaration (%s,%s)', self.nspname, self.pname) if self.type: self.logger.debug('xsi:type definition (%s,%s)', self.type[0], self.type[1]) else: self.logger.warning('NO xsi:type') while indx < lenofwhat: occurs = 0 what = self.ofwhat[indx] # retrieve typecode if hidden if callable(what): what = what() if debug: self.logger.debug('serialize what -- %s', what.__class__.__name__) # No way to order instances, so just grab any unmatched # anames and serialize them. Only support one in all content. # Must be self-describing instances # Regular handling of declared elements aname = what.aname v = f(aname) indx += 1 if what.minOccurs == 0 and v is None: continue # Default to typecode, if self-describing instance, and check # to make sure it is derived from what. whatTC = what if whatTC.maxOccurs > 1 and v is not None: if type(v) not in _seqtypes: raise EvaluateException('pyobj (%s,%s), aname "%s": maxOccurs %s, expecting a %s' %( self.nspname,self.pname,what.aname,whatTC.maxOccurs,_seqtypes), sw.Backtrace(elt)) for v2 in v: occurs += 1 if occurs > whatTC.maxOccurs: raise EvaluateException('occurances (%d) exceeded maxOccurs(%d) for <%s>' %( occurs, whatTC.maxOccurs, what.pname), sw.Backtrace(elt)) what = _get_type_or_substitute(whatTC, v2, sw, elt) if debug and what is not whatTC: self.logger.debug('substitute derived type: %s' % what.__class__) what.serialize(elem, sw, v2, **kw) # try: # what.serialize(elem, sw, v2, **kw) # except Exception, e: # raise EvaluateException('Serializing %s.%s, %s %s' % # (n, whatTC.aname or '?', e.__class__.__name__, str(e))) if occurs < whatTC.minOccurs: raise EvaluateException(\ 'occurances(%d) less than minOccurs(%d) for <%s>' % (occurs, whatTC.minOccurs, what.pname), sw.Backtrace(elt)) continue if v is not None or what.nillable is True: what = _get_type_or_substitute(whatTC, v, sw, elt) if debug and what is not whatTC: self.logger.debug('substitute derived type: %s' % what.__class__) what.serialize(elem, sw, v, **kw) # try: # what.serialize(elem, sw, v, **kw) # except (ParseException, EvaluateException), e: # raise # except Exception, e: # raise EvaluateException('Serializing %s.%s, %s %s' % # (n, whatTC.aname or '?', e.__class__.__name__, str(e)), # sw.Backtrace(elt)) continue raise EvaluateException('Got None for nillable(%s), minOccurs(%d) element (%s,%s), %s' % (what.nillable, what.minOccurs, what.nspname, what.pname, elem), sw.Backtrace(elt)) def setDerivedTypeContents(self, extensions=None, restrictions=None): """For derived types set appropriate parameter and """ if extensions: ofwhat = list(self.ofwhat) if type(extensions) in _seqtypes: ofwhat += list(extensions) else: ofwhat.append(extensions) elif restrictions: if type(restrictions) in _seqtypes: ofwhat = restrictions else: ofwhat = (restrictions,) else: return self.ofwhat = tuple(ofwhat) self.lenofwhat = len(self.ofwhat) class Struct(ComplexType): '''Struct is a complex type for accessors identified by name. Constraint: No element may have the same name as any other, nor may any element have a maxOccurs > 1. ''' logger = _GetLogger('ZSI.TCcompound.Struct') def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, mutable=True, **kw): '''pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the struct inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations ''' ComplexType.__init__(self, pyclass, ofwhat, pname=pname, inorder=inorder, inline=inline, mutable=mutable, **kw ) # Check Constraints whats = map(lambda what: (what.nspname,what.pname), self.ofwhat) for idx in range(len(self.ofwhat)): what = self.ofwhat[idx] key = (what.nspname,what.pname) if not isinstance(what, AnyElement) and what.maxOccurs > 1: raise TypeError,\ 'Constraint: no element can have a maxOccurs>1' if key in whats[idx+1:]: raise TypeError,\ 'Constraint: No element may have the same name as any other' class Array(TypeCode): '''An array. atype -- arrayType, (namespace,ncname) mutable -- object could change between multiple serializations undeclared -- do not serialize/parse arrayType attribute. ''' logger = _GetLogger('ZSI.TCcompound.Array') def __init__(self, atype, ofwhat, pname=None, dimensions=1, fill=None, sparse=False, mutable=False, size=None, nooffset=0, undeclared=False, childnames=None, **kw): TypeCode.__init__(self, pname, **kw) self.dimensions = dimensions self.atype = atype if undeclared is False and self.atype[1].endswith(']') is False: self.atype = (self.atype[0], '%s[]' %self.atype[1]) # Support multiple dimensions if self.dimensions != 1: raise TypeError("Only single-dimensioned arrays supported") self.fill = fill self.sparse = sparse #if self.sparse: ofwhat.minOccurs = 0 self.mutable = mutable self.size = size self.nooffset = nooffset self.undeclared = undeclared self.childnames = childnames if self.size: t = type(self.size) if t in _inttypes: self.size = (self.size,) elif t in _seqtypes: self.size = tuple(self.size) elif TypeCode.typechecks: raise TypeError('Size must be integer or list, not ' + str(t)) # by default use Any ofwhat = ofwhat or Any() if TypeCode.typechecks: if self.undeclared is False and type(atype) not in _seqtypes and len(atype) == 2: raise TypeError("Array type must be a sequence of len 2.") t = type(ofwhat) if not isinstance(ofwhat, TypeCode): raise TypeError( 'Array ofwhat outside the TypeCode hierarchy, ' + str(ofwhat.__class__)) if self.size: if len(self.size) != self.dimensions: raise TypeError('Array dimension/size mismatch') for s in self.size: if type(s) not in _inttypes: raise TypeError('Array size "' + str(s) + '" is not an integer.') self.ofwhat = ofwhat def parse_offset(self, elt, ps): o = _find_arrayoffset(elt) if not o: return 0 if not _offset_pat.match(o): raise EvaluateException('Bad offset "' + o + '"', ps.Backtrace(elt)) return int(o[1:-1]) def parse_position(self, elt, ps): o = _find_arrayposition(elt) if not o: return None if o.find(',') > -1: raise EvaluateException('Sorry, no multi-dimensional arrays', ps.Backtrace(elt)) if not _position_pat.match(o): raise EvaluateException('Bad array position "' + o + '"', ps.Backtrace(elt)) return int(o[1:-1]) def parse(self, elt, ps): href = _find_href(elt) if href: if _children(elt): raise EvaluateException('Array has content and HREF', ps.Backtrace(elt)) elt = ps.FindLocalHREF(href, elt) if self.nilled(elt, ps): return Nilled if not _find_arraytype(elt) and self.undeclared is False: raise EvaluateException('Array expected', ps.Backtrace(elt)) t = _find_type(elt) if t: pass # XXX should check the type, but parsing that is hairy. offset = self.parse_offset(elt, ps) v, vlen = [], 0 if offset and not self.sparse: while vlen < offset: vlen += 1 v.append(self.fill) for c in _child_elements(elt): item = self.ofwhat.parse(c, ps) position = self.parse_position(c, ps) or offset if self.sparse: v.append((position, item)) else: while offset < position: offset += 1 v.append(self.fill) v.append(item) offset += 1 return v def serialize(self, elt, sw, pyobj, name=None, childnames=None, **kw): debug = self.logger.debugOn() if debug: self.logger.debug("serialize: %r" %pyobj) if self.mutable is False and sw.Known(pyobj): return objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) el = elt.createAppendElement(ns, n) # nillable if self.nillable is True and pyobj is None: self.serialize_as_nil(el) return None # other attributes self.set_attributes(el, pyobj) # soap href attribute unique = self.unique or kw.get('unique', False) if unique is False and sw.Known(pyobj): self.set_attribute_href(el, objid) return None # xsi:type attribute if kw.get('typed', self.typed) is True: self.set_attribute_xsi_type(el, **kw) # soap id attribute if self.unique is False: self.set_attribute_id(el, objid) offset = 0 if self.sparse is False and self.nooffset is False: offset, end = 0, len(pyobj) while offset < end and pyobj[offset] == self.fill: offset += 1 if offset: el.setAttributeNS(SOAP.ENC, 'offset', '[%d]' %offset) if self.undeclared is False: el.setAttributeNS(SOAP.ENC, 'arrayType', '%s:%s' %(el.getPrefix(self.atype[0]), self.atype[1]) ) if debug: self.logger.debug("ofwhat: %r" %self.ofwhat) d = {} kn = childnames or self.childnames if kn: d['name'] = kn elif not self.ofwhat.aname: d['name'] = 'element' if self.sparse is False: for e in pyobj[offset:]: self.ofwhat.serialize(el, sw, e, **d) else: position = 0 for pos, v in pyobj: if pos != position: el.setAttributeNS(SOAP.ENC, 'position', '[%d]' %pos) position = pos self.ofwhat.serialize(el, sw, v, **d) position += 1 if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/ServiceProxy.py0000755000175100017510000003406310641306321014204 0ustar zsizsi# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. import weakref, re, os, sys from ConfigParser import SafeConfigParser as ConfigParser,\ NoSectionError, NoOptionError from urlparse import urlparse from ZSI import TC from ZSI.client import _Binding from ZSI.generate import commands,containers from ZSI.schema import GED, GTD import wstools #url_to_mod = re.compile(r'<([^ \t\n\r\f\v:]+:)?include\s+location\s*=\s*"(\S+)"') def _urn_to_module(urn): return '%s_types' %re.sub(_urn_to_module.regex, '_', urn) _urn_to_module.regex = re.compile(r'[\W]') class ServiceProxy: """A ServiceProxy provides a convenient way to call a remote web service that is described with WSDL. The proxy exposes methods that reflect the methods of the remote web service.""" def __init__(self, wsdl, url=None, service=None, port=None, cachedir=os.path.join(os.path.expanduser('~'), '.zsi_service_proxy_dir'), asdict=True, lazy=False, pyclass=False, force=False, **kw): """ Parameters: wsdl -- URL of WSDL. url -- override WSDL SOAP address location service -- service name or index port -- port name or index cachedir -- where to store generated files asdict -- use dicts, else use generated pyclass lazy -- use lazy typecode evaluation pyclass -- use pyclass_type metaclass adds properties, "new_", "set_, "get_" methods for schema element and attribute declarations. force -- regenerate all WSDL code, write over cache. NOTE: all other **kw will be passed to the underlying ZSI.client._Binding constructor. """ self._asdict = asdict # client._Binding self._url = url self._kw = kw # WSDL self._wsdl = wstools.WSDLTools.WSDLReader().loadFromURL(wsdl) self._service = self._wsdl.services[service or 0] self.__doc__ = self._service.documentation self._port = self._service.ports[port or 0] self._name = self._service.name self._methods = {} self._cachedir = cachedir self._lazy = lazy self._pyclass = pyclass self._force = force # Set up rpc methods for service/port port = self._port binding = port.getBinding() portType = binding.getPortType() for port in self._service.ports: for item in port.getPortType().operations: try: callinfo = wstools.WSDLTools.callInfoFromWSDL(port, item.name) except: # ignore non soap-1.1 bindings continue method = MethodProxy(self, callinfo) setattr(self, item.name, method) self._methods.setdefault(item.name, []).append(method) self._mod = self._load(wsdl) def _load(self, location): """ location -- URL or file location isxsd -- is this a xsd file? """ cachedir = self._cachedir # wsdl2py: deal with XML Schema if not os.path.isdir(cachedir): os.mkdir(cachedir) file = os.path.join(cachedir, '.cache') section = 'TYPES' cp = ConfigParser() try: cp.readfp(open(file, 'r')) except IOError: del cp; cp = None option = location.replace(':', '-') # colons seem to screw up option if (not self._force and cp is not None and cp.has_section(section) and cp.has_option(section, option)): types = cp.get(section, option) else: # dont do anything to anames if not self._pyclass: containers.ContainerBase.func_aname = lambda instnc,n: str(n) args = ['-o', cachedir, location] if self._lazy: args.insert(0, '-l') if self._pyclass: args.insert(0, '-b') files = commands.wsdl2py(args) if cp is None: cp = ConfigParser() if not cp.has_section(section): cp.add_section(section) types = filter(lambda f: f.endswith('_types.py'), files)[0] cp.set(section, option, types) cp.write(open(file, 'w')) if os.path.abspath(cachedir) not in sys.path: sys.path.append(os.path.abspath(cachedir)) mod = os.path.split(types)[-1].rstrip('.py') return __import__(mod) def _load_schema(self, location, xml=None): """ location -- location of schema, also used as a key xml -- optional string representation of schema """ cachedir = self._cachedir # wsdl2py: deal with XML Schema if not os.path.isdir(cachedir): os.mkdir(cachedir) file = os.path.join(cachedir, '.cache') section = 'TYPES' cp = ConfigParser() try: cp.readfp(open(file, 'r')) except IOError: del cp; cp = None option = location.replace(':', '-') # colons seem to screw up option if (cp is not None and cp.has_section(section) and cp.has_option(section, option)): types = cp.get(section, option) else: # dont do anything to anames if not self._pyclass: containers.ContainerBase.func_aname = lambda instnc,n: str(n) from ZSI.wstools import XMLSchema reader = XMLSchema.SchemaReader(base_url=location) if xml is not None and isinstance(xml, basestring): schema = reader.loadFromString(xml) elif xml is not None: raise RuntimeError, 'Unsupported: XML must be string' elif not os.path.isfile(location): schema = reader.loadFromURL(location) else: schema = reader.reader.loadFromFile(location) # TODO: change this to keyword list class options: output_dir = cachedir schema = True simple_naming = False address = False lazy = self._lazy complexType = self._pyclass schema.location = location files = commands._wsdl2py(options, schema) if cp is None: cp = ConfigParser() if not cp.has_section(section): cp.add_section(section) types = filter(lambda f: f.endswith('_types.py'), files)[0] cp.set(section, option, types) cp.write(open(file, 'w')) if os.path.abspath(cachedir) not in sys.path: sys.path.append(os.path.abspath(cachedir)) mod = os.path.split(types)[-1].rstrip('.py') return __import__(mod) def _call(self, name, soapheaders): """return the Call to the named remote web service method. closure used to prevent multiple values for name and soapheaders parameters """ def call_closure(*args, **kwargs): """Call the named remote web service method.""" if len(args) and len(kwargs): raise TypeError, 'Use positional or keyword argument only.' if len(args) > 0: raise TypeError, 'Not supporting SOAPENC:Arrays or XSD:List' if len(kwargs): args = kwargs callinfo = getattr(self, name).callinfo # go through the list of defined methods, and look for the one with # the same number of arguments as what was passed. this is a weak # check that should probably be improved in the future to check the # types of the arguments to allow for polymorphism for method in self._methods[name]: if len(method.callinfo.inparams) == len(kwargs): callinfo = method.callinfo binding = _Binding(url=self._url or callinfo.location, soapaction=callinfo.soapAction, **self._kw) kw = dict(unique=True) if callinfo.use == 'encoded': kw['unique'] = False if callinfo.style == 'rpc': request = TC.Struct(None, ofwhat=[], pname=(callinfo.namespace, name), **kw) response = TC.Struct(None, ofwhat=[], pname=(callinfo.namespace, name+"Response"), **kw) if len(callinfo.getInParameters()) != len(args): raise RuntimeError('expecting "%s" parts, got %s' %( str(callinfo.getInParameters(), str(args)))) for msg,pms in ((request,callinfo.getInParameters()), (response,callinfo.getOutParameters())): msg.ofwhat = [] for part in pms: klass = GTD(*part.type) if klass is None: if part.type: klass = filter(lambda gt: part.type==gt.type,TC.TYPES) if len(klass) == 0: klass = filter(lambda gt: part.type[1]==gt.type[1],TC.TYPES) if not len(klass):klass = [TC.Any] if len(klass) > 1: #Enumerations, XMLString, etc klass = filter(lambda i: i.__dict__.has_key('type'), klass) klass = klass[0] else: klass = TC.Any msg.ofwhat.append(klass(part.name)) msg.ofwhat = tuple(msg.ofwhat) if not args: args = {} else: # Grab attribute ipart,opart = callinfo.getInParameters(),callinfo.getOutParameters() if ( len(ipart) != 1 or not ipart[0].element_type or ipart[0].type is None ): raise RuntimeError, 'Bad Input Message "%s"' %callinfo.name if ( len(opart) not in (0,1) or not opart[0].element_type or opart[0].type is None ): raise RuntimeError, 'Bad Output Message "%s"' %callinfo.name # if ( len(args) > 1 ): # raise RuntimeError, 'Message has only one part: %s' %str(args) ipart = ipart[0] request,response = GED(*ipart.type),None if opart: response = GED(*opart[0].type) msg = args if self._asdict: if not msg: msg = dict() self._nullpyclass(request) elif request.pyclass is not None: if type(args) is dict: msg = request.pyclass() msg.__dict__.update(args) elif type(args) is list and len(args) == 1: msg = request.pyclass(args[0]) else: msg = request.pyclass() binding.Send(None, None, msg, requesttypecode=request, soapheaders=soapheaders, encodingStyle=callinfo.encodingStyle) if response is None: return None if self._asdict: self._nullpyclass(response) return binding.Receive(replytype=response, encodingStyle=callinfo.encodingStyle) return call_closure def _nullpyclass(cls, typecode): typecode.pyclass = None if not hasattr(typecode, 'ofwhat'): return if type(typecode.ofwhat) not in (list,tuple): #Array cls._nullpyclass(typecode.ofwhat) else: #Struct/ComplexType for i in typecode.ofwhat: cls._nullpyclass(i) _nullpyclass = classmethod(_nullpyclass) class MethodProxy: """ """ def __init__(self, parent, callinfo): self.__name__ = callinfo.methodName self.__doc__ = callinfo.documentation self.callinfo = callinfo self.parent = weakref.ref(parent) self.soapheaders = [] def __call__(self, *args, **kwargs): return self.parent()._call(self.__name__, self.soapheaders)(*args, **kwargs) def add_headers(self, **headers): """packing dicts into typecode pyclass, may fail if typecodes are used in the body (when asdict=True) """ class _holder: pass def _remap(pyobj, **d): pyobj.__dict__ = d for k,v in pyobj.__dict__.items(): if type(v) is not dict: continue pyobj.__dict__[k] = p = _holder() _remap(p, **v) for k,v in headers.items(): h = filter(lambda i: k in i.type, self.callinfo.inheaders)[0] if h.element_type != 1: raise RuntimeError, 'not implemented' typecode = GED(*h.type) if typecode is None: raise RuntimeError, 'no matching element for %s' %str(h.type) pyclass = typecode.pyclass if pyclass is None: raise RuntimeError, 'no pyclass for typecode %s' %str(h.type) if type(v) is not dict: pyobj = pyclass(v) else: pyobj = pyclass() _remap(pyobj, **v) self.soapheaders.append(pyobj) ZSI-2.1-a1/ZSI/version.py0000644000175100017510000000006710560472646013237 0ustar zsizsi# Auto-generated file; do not edit Version = (2, 1, 0) ZSI-2.1-a1/ZSI/fault.py0000644000175100017510000001764110560302574012663 0ustar zsizsi#! /usr/bin/env python # $Header$ '''Faults. ''' from ZSI import _copyright, _children, _child_elements, \ _get_idstr, _stringtypes, _seqtypes, _Node, SoapWriter, ZSIException from ZSI.TCcompound import Struct from ZSI.TC import QName, URI, String, XMLString, AnyElement, UNBOUNDED from ZSI.wstools.Namespaces import SOAP, ZSI_SCHEMA_URI from ZSI.wstools.c14n import Canonicalize from ZSI.TC import ElementDeclaration import traceback, cStringIO as StringIO class Detail: def __init__(self, any=None): self.any = any Detail.typecode = Struct(Detail, [AnyElement(aname='any',minOccurs=0, maxOccurs="unbounded",processContents="lax")], pname='detail', minOccurs=0) class FaultType: def __init__(self, faultcode=None, faultstring=None, faultactor=None, detail=None): self.faultcode = faultcode self.faultstring= faultstring self.faultactor = faultactor self.detail = detail FaultType.typecode = \ Struct(FaultType, [QName(pname='faultcode'), String(pname='faultstring'), URI(pname=(SOAP.ENV,'faultactor'), minOccurs=0), Detail.typecode, AnyElement(aname='any',minOccurs=0, maxOccurs=UNBOUNDED, processContents="lax"), ], pname=(SOAP.ENV,'Fault'), inline=True, hasextras=0, ) class ZSIHeaderDetail: def __init__(self, detail): self.any = detail ZSIHeaderDetail.typecode =\ Struct(ZSIHeaderDetail, [AnyElement(aname='any', minOccurs=0, maxOccurs=UNBOUNDED, processContents="lax")], pname=(ZSI_SCHEMA_URI, 'detail')) class ZSIFaultDetailTypeCode(ElementDeclaration, Struct): ''' %s %s ''' schema = ZSI_SCHEMA_URI literal = 'FaultDetail' def __init__(self, **kw): Struct.__init__(self, ZSIFaultDetail, [String(pname=(ZSI_SCHEMA_URI, 'string')), String(pname=(ZSI_SCHEMA_URI, 'trace'),minOccurs=0),], pname=(ZSI_SCHEMA_URI, 'FaultDetail'), **kw ) class ZSIFaultDetail: def __init__(self, string=None, trace=None): self.string = string self.trace = trace def __str__(self): if self.trace: return self.string + '\n[trace: ' + self.trace + ']' return self.string def __repr__(self): return "<%s.ZSIFaultDetail %s>" % (__name__, _get_idstr(self)) ZSIFaultDetail.typecode = ZSIFaultDetailTypeCode() class URIFaultDetailTypeCode(ElementDeclaration, Struct): ''' uri localname ''' schema = ZSI_SCHEMA_URI literal = 'URIFaultDetail' def __init__(self, **kw): Struct.__init__(self, URIFaultDetail, [String(pname=(ZSI_SCHEMA_URI, 'URI')), String(pname=(ZSI_SCHEMA_URI, 'localname')),], pname=(ZSI_SCHEMA_URI, 'URIFaultDetail'), **kw ) class URIFaultDetail: def __init__(self, uri=None, localname=None): self.URI = uri self.localname = localname URIFaultDetail.typecode = URIFaultDetailTypeCode() class ActorFaultDetailTypeCode(ElementDeclaration, Struct): ''' %s ''' schema = ZSI_SCHEMA_URI literal = 'ActorFaultDetail' def __init__(self, **kw): Struct.__init__(self, ActorFaultDetail, [String(pname=(ZSI_SCHEMA_URI, 'URI')),], pname=(ZSI_SCHEMA_URI, 'ActorFaultDetail'), **kw ) class ActorFaultDetail: def __init__(self, uri=None): self.URI = uri ActorFaultDetail.typecode = ActorFaultDetailTypeCode() class Fault(ZSIException): '''SOAP Faults. ''' Client = "SOAP-ENV:Client" Server = "SOAP-ENV:Server" MU = "SOAP-ENV:MustUnderstand" def __init__(self, code, string, actor=None, detail=None, headerdetail=None): if detail is not None and type(detail) not in _seqtypes: detail = (detail,) if headerdetail is not None and type(headerdetail) not in _seqtypes: headerdetail = (headerdetail,) self.code, self.string, self.actor, self.detail, self.headerdetail = \ code, string, actor, detail, headerdetail ZSIException.__init__(self, code, string, actor, detail, headerdetail) def DataForSOAPHeader(self): if not self.headerdetail: return None # SOAP spec doesn't say how to encode header fault data. return ZSIHeaderDetail(self.headerdetail) def serialize(self, sw): '''Serialize the object.''' detail = None if self.detail is not None: detail = Detail() detail.any = self.detail pyobj = FaultType(self.code, self.string, self.actor, detail) sw.serialize(pyobj, typed=False) def AsSOAP(self, **kw): header = self.DataForSOAPHeader() sw = SoapWriter(**kw) self.serialize(sw) if header is not None: sw.serialize_header(header, header.typecode, typed=False) return str(sw) def __str__(self): strng = str(self.string) + "\n" if hasattr(self, 'detail'): if hasattr(self.detail, '__len__'): for d in self.detail: strng += str(d) else: strng += str(self.detail) return strng def __repr__(self): return "<%s.Fault at %s>" % (__name__, _get_idstr(self)) AsSoap = AsSOAP def FaultFromNotUnderstood(uri, localname, actor=None): detail, headerdetail = None, URIFaultDetail(uri, localname) return Fault(Fault.MU, 'SOAP mustUnderstand not understood', actor, detail, headerdetail) def FaultFromActor(uri, actor=None): detail, headerdetail = None, ActorFaultDetail(uri) return Fault(Fault.Client, 'Cannot process specified actor', actor, detail, headerdetail) def FaultFromZSIException(ex, actor=None): '''Return a Fault object created from a ZSI exception object. ''' mystr = getattr(ex, 'str', None) or str(ex) mytrace = getattr(ex, 'trace', '') elt = ''' %s %s ''' % (mystr, mytrace) if getattr(ex, 'inheader', 0): detail, headerdetail = None, elt else: detail, headerdetail = elt, None return Fault(Fault.Client, 'Unparseable message', actor, detail, headerdetail) def FaultFromException(ex, inheader, tb=None, actor=None): '''Return a Fault object created from a Python exception. SOAP-ENV:Server Processing Failure ''' tracetext = None if tb: try: lines = '\n'.join(['%s:%d:%s' % (name, line, func) for name, line, func, text in traceback.extract_tb(tb)]) except: pass else: tracetext = lines exceptionName = "" try: exceptionName = ":".join([ex.__module__, ex.__class__.__name__]) except: pass elt = ZSIFaultDetail(string=exceptionName + "\n" + str(ex), trace=tracetext) if inheader: detail, headerdetail = None, elt else: detail, headerdetail = elt, None return Fault(Fault.Server, 'Processing Failure', actor, detail, headerdetail) def FaultFromFaultMessage(ps): '''Parse the message as a fault. ''' pyobj = ps.Parse(FaultType.typecode) if pyobj.detail == None: detailany = None else: detailany = pyobj.detail.any return Fault(pyobj.faultcode, pyobj.faultstring, pyobj.faultactor, detailany) if __name__ == '__main__': print _copyright ZSI-2.1-a1/ZSI/wstools/0000755000175100017510000000000010712455110012671 5ustar zsizsiZSI-2.1-a1/ZSI/wstools/license.txt0000644000175100017510000000461707707035575015107 0ustar zsizsi********* Copyright (c) 2003, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form. ********* ZSI-2.1-a1/ZSI/wstools/ZPL0000644000175100017510000000450007652014323013266 0ustar zsizsiZope Public License (ZPL) Version 2.0 ----------------------------------------------- This software is Copyright (c) Zope Corporation (tm) and Contributors. All rights reserved. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name Zope Corporation (tm) must not be used to endorse or promote products derived from this software without prior written permission from Zope Corporation. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of Zope Corporation. Use of them is covered in a separate agreement (see http://www.zope.com/Marks). 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of contributions made by Zope Corporation and many individuals on behalf of Zope Corporation. Specific attributions are listed in the accompanying credits file. ZSI-2.1-a1/ZSI/wstools/Namespaces.py0000755000175100017510000002124510406606713015340 0ustar zsizsi# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. """Namespace module, so you don't need PyXML """ ident = "$Id: Namespaces.py 1160 2006-03-17 19:28:11Z boverhof $" try: from xml.ns import SOAP, SCHEMA, WSDL, XMLNS, DSIG, ENCRYPTION DSIG.C14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" except: class SOAP: ENV = "http://schemas.xmlsoap.org/soap/envelope/" ENC = "http://schemas.xmlsoap.org/soap/encoding/" ACTOR_NEXT = "http://schemas.xmlsoap.org/soap/actor/next" class SCHEMA: XSD1 = "http://www.w3.org/1999/XMLSchema" XSD2 = "http://www.w3.org/2000/10/XMLSchema" XSD3 = "http://www.w3.org/2001/XMLSchema" XSD_LIST = [ XSD1, XSD2, XSD3 ] XSI1 = "http://www.w3.org/1999/XMLSchema-instance" XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" XSI3 = "http://www.w3.org/2001/XMLSchema-instance" XSI_LIST = [ XSI1, XSI2, XSI3 ] BASE = XSD3 class WSDL: BASE = "http://schemas.xmlsoap.org/wsdl/" BIND_HTTP = "http://schemas.xmlsoap.org/wsdl/http/" BIND_MIME = "http://schemas.xmlsoap.org/wsdl/mime/" BIND_SOAP = "http://schemas.xmlsoap.org/wsdl/soap/" BIND_SOAP12 = "http://schemas.xmlsoap.org/wsdl/soap12/" class XMLNS: BASE = "http://www.w3.org/2000/xmlns/" XML = "http://www.w3.org/XML/1998/namespace" HTML = "http://www.w3.org/TR/REC-html40" class DSIG: BASE = "http://www.w3.org/2000/09/xmldsig#" C14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" C14N_COMM = "http://www.w3.org/TR/2000/CR-xml-c14n-20010315#WithComments" C14N_EXCL = "http://www.w3.org/2001/10/xml-exc-c14n#" DIGEST_MD2 = "http://www.w3.org/2000/09/xmldsig#md2" DIGEST_MD5 = "http://www.w3.org/2000/09/xmldsig#md5" DIGEST_SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1" ENC_BASE64 = "http://www.w3.org/2000/09/xmldsig#base64" ENVELOPED = "http://www.w3.org/2000/09/xmldsig#enveloped-signature" HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1" SIG_DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1" SIG_RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" XPATH = "http://www.w3.org/TR/1999/REC-xpath-19991116" XSLT = "http://www.w3.org/TR/1999/REC-xslt-19991116" class ENCRYPTION: BASE = "http://www.w3.org/2001/04/xmlenc#" BLOCK_3DES = "http://www.w3.org/2001/04/xmlenc#des-cbc" BLOCK_AES128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc" BLOCK_AES192 = "http://www.w3.org/2001/04/xmlenc#aes192-cbc" BLOCK_AES256 = "http://www.w3.org/2001/04/xmlenc#aes256-cbc" DIGEST_RIPEMD160 = "http://www.w3.org/2001/04/xmlenc#ripemd160" DIGEST_SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256" DIGEST_SHA512 = "http://www.w3.org/2001/04/xmlenc#sha512" KA_DH = "http://www.w3.org/2001/04/xmlenc#dh" KT_RSA_1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" KT_RSA_OAEP = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" STREAM_ARCFOUR = "http://www.w3.org/2001/04/xmlenc#arcfour" WRAP_3DES = "http://www.w3.org/2001/04/xmlenc#kw-3des" WRAP_AES128 = "http://www.w3.org/2001/04/xmlenc#kw-aes128" WRAP_AES192 = "http://www.w3.org/2001/04/xmlenc#kw-aes192" WRAP_AES256 = "http://www.w3.org/2001/04/xmlenc#kw-aes256" class WSRF_V1_2: '''OASIS WSRF Specifications Version 1.2 ''' class LIFETIME: XSD_DRAFT1 = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.xsd" XSD_DRAFT4 = "http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-ResourceLifetime-1.2-draft-04.xsd" WSDL_DRAFT1 = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl" WSDL_DRAFT4 = "http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-ResourceLifetime-1.2-draft-04.wsdl" LATEST = WSDL_DRAFT4 WSDL_LIST = (WSDL_DRAFT1, WSDL_DRAFT4) XSD_LIST = (XSD_DRAFT1, XSD_DRAFT4) class PROPERTIES: XSD_DRAFT1 = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd" XSD_DRAFT5 = "http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-ResourceProperties-1.2-draft-05.xsd" WSDL_DRAFT1 = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl" WSDL_DRAFT5 = "http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-ResourceProperties-1.2-draft-05.wsdl" LATEST = WSDL_DRAFT5 WSDL_LIST = (WSDL_DRAFT1, WSDL_DRAFT5) XSD_LIST = (XSD_DRAFT1, XSD_DRAFT5) class BASENOTIFICATION: XSD_DRAFT1 = "http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification-1.2-draft-01.xsd" WSDL_DRAFT1 = "http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification-1.2-draft-01.wsdl" LATEST = WSDL_DRAFT1 WSDL_LIST = (WSDL_DRAFT1,) XSD_LIST = (XSD_DRAFT1,) class BASEFAULTS: XSD_DRAFT1 = "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-BaseFaults-1.2-draft-01.xsd" XSD_DRAFT3 = "http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-BaseFaults-1.2-draft-03.xsd" #LATEST = DRAFT3 #WSDL_LIST = (WSDL_DRAFT1, WSDL_DRAFT3) XSD_LIST = (XSD_DRAFT1, XSD_DRAFT3) WSRF = WSRF_V1_2 WSRFLIST = (WSRF_V1_2,) class OASIS: '''URLs for Oasis specifications ''' WSSE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" UTILITY = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" class X509TOKEN: Base64Binary = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" STRTransform = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0" PKCS7 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#PKCS7" X509 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509" X509PKIPathv1 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" X509v3SubjectKeyIdentifier = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3SubjectKeyIdentifier" LIFETIME = WSRF_V1_2.LIFETIME.XSD_DRAFT1 PROPERTIES = WSRF_V1_2.PROPERTIES.XSD_DRAFT1 BASENOTIFICATION = WSRF_V1_2.BASENOTIFICATION.XSD_DRAFT1 BASEFAULTS = WSRF_V1_2.BASEFAULTS.XSD_DRAFT1 class WSTRUST: BASE = "http://schemas.xmlsoap.org/ws/2004/04/trust" ISSUE = "http://schemas.xmlsoap.org/ws/2004/04/trust/Issue" class WSSE: BASE = "http://schemas.xmlsoap.org/ws/2002/04/secext" TRUST = WSTRUST.BASE class WSU: BASE = "http://schemas.xmlsoap.org/ws/2002/04/utility" UTILITY = "http://schemas.xmlsoap.org/ws/2002/07/utility" class WSR: PROPERTIES = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" LIFETIME = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime" class WSA200408: ADDRESS = "http://schemas.xmlsoap.org/ws/2004/08/addressing" ANONYMOUS = "%s/role/anonymous" %ADDRESS FAULT = "%s/fault" %ADDRESS class WSA200403: ADDRESS = "http://schemas.xmlsoap.org/ws/2004/03/addressing" ANONYMOUS = "%s/role/anonymous" %ADDRESS FAULT = "%s/fault" %ADDRESS class WSA200303: ADDRESS = "http://schemas.xmlsoap.org/ws/2003/03/addressing" ANONYMOUS = "%s/role/anonymous" %ADDRESS FAULT = None WSA = WSA200408 WSA_LIST = (WSA200408, WSA200403, WSA200303) class WSP: POLICY = "http://schemas.xmlsoap.org/ws/2002/12/policy" class BEA: SECCONV = "http://schemas.xmlsoap.org/ws/2004/04/sc" SCTOKEN = "http://schemas.xmlsoap.org/ws/2004/04/security/sc/sct" class GLOBUS: SECCONV = "http://wsrf.globus.org/core/2004/07/security/secconv" CORE = "http://www.globus.org/namespaces/2004/06/core" SIG = "http://www.globus.org/2002/04/xmlenc#gssapi-sign" TOKEN = "http://www.globus.org/ws/2004/09/security/sc#GSSAPI_GSI_TOKEN" ZSI_SCHEMA_URI = 'http://www.zolera.com/schemas/ZSI/' ZSI-2.1-a1/ZSI/wstools/.cvsignore0000644000175100017510000000000607653240736014705 0ustar zsizsi*.pyc ZSI-2.1-a1/ZSI/wstools/XMLname.py0000644000175100017510000000473410204656221014556 0ustar zsizsi"""Translate strings to and from SOAP 1.2 XML name encoding Implements rules for mapping application defined name to XML names specified by the w3 SOAP working group for SOAP version 1.2 in Appendix A of "SOAP Version 1.2 Part 2: Adjuncts", W3C Working Draft 17, December 2001, Also see . Author: Gregory R. Warnes Date:: 2002-04-25 Version 0.9.0 """ ident = "$Id: XMLname.py 954 2005-02-16 14:45:37Z warnes $" from re import * def _NCNameChar(x): return x.isalpha() or x.isdigit() or x=="." or x=='-' or x=="_" def _NCNameStartChar(x): return x.isalpha() or x=="_" def _toUnicodeHex(x): hexval = hex(ord(x[0]))[2:] hexlen = len(hexval) # Make hexval have either 4 or 8 digits by prepending 0's if (hexlen==1): hexval = "000" + hexval elif (hexlen==2): hexval = "00" + hexval elif (hexlen==3): hexval = "0" + hexval elif (hexlen==4): hexval = "" + hexval elif (hexlen==5): hexval = "000" + hexval elif (hexlen==6): hexval = "00" + hexval elif (hexlen==7): hexval = "0" + hexval elif (hexlen==8): hexval = "" + hexval else: raise Exception, "Illegal Value returned from hex(ord(x))" return "_x"+ hexval + "_" def _fromUnicodeHex(x): return eval( r'u"\u'+x[2:-1]+'"' ) def toXMLname(string): """Convert string to a XML name.""" if string.find(':') != -1 : (prefix, localname) = string.split(':',1) else: prefix = None localname = string T = unicode(localname) N = len(localname) X = []; for i in range(N) : if i< N-1 and T[i]==u'_' and T[i+1]==u'x': X.append(u'_x005F_') elif i==0 and N >= 3 and \ ( T[0]==u'x' or T[0]==u'X' ) and \ ( T[1]==u'm' or T[1]==u'M' ) and \ ( T[2]==u'l' or T[2]==u'L' ): X.append(u'_xFFFF_' + T[0]) elif (not _NCNameChar(T[i])) or (i==0 and not _NCNameStartChar(T[i])): X.append(_toUnicodeHex(T[i])) else: X.append(T[i]) if prefix: return "%s:%s" % (prefix, u''.join(X)) return u''.join(X) def fromXMLname(string): """Convert XML name to unicode string.""" retval = sub(r'_xFFFF_','', string ) def fun( matchobj ): return _fromUnicodeHex( matchobj.group(0) ) retval = sub(r'_x[0-9A-Za-z]+_', fun, retval ) return retval ZSI-2.1-a1/ZSI/wstools/TimeoutSocket.py0000755000175100017510000001234007662514666016073 0ustar zsizsi"""Based on code from timeout_socket.py, with some tweaks for compatibility. These tweaks should really be rolled back into timeout_socket, but it's not totally clear who is maintaining it at this point. In the meantime, we'll use a different module name for our tweaked version to avoid any confusion. The original timeout_socket is by: Scott Cotton Lloyd Zusman Phil Mayes Piers Lauder Radovan Garabik """ ident = "$Id: TimeoutSocket.py 237 2003-05-20 21:10:14Z warnes $" import string, socket, select, errno WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022) class TimeoutSocket: """A socket imposter that supports timeout limits.""" def __init__(self, timeout=20, sock=None): self.timeout = float(timeout) self.inbuf = '' if sock is None: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = sock self.sock.setblocking(0) self._rbuf = '' self._wbuf = '' def __getattr__(self, name): # Delegate to real socket attributes. return getattr(self.sock, name) def connect(self, *addr): timeout = self.timeout sock = self.sock try: # Non-blocking mode sock.setblocking(0) apply(sock.connect, addr) sock.setblocking(timeout != 0) return 1 except socket.error,why: if not timeout: raise sock.setblocking(1) if len(why.args) == 1: code = 0 else: code, why = why if code not in ( errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK ): raise r,w,e = select.select([],[sock],[],timeout) if w: try: apply(sock.connect, addr) return 1 except socket.error,why: if len(why.args) == 1: code = 0 else: code, why = why if code in (errno.EISCONN, WSAEINVAL): return 1 raise raise TimeoutError('socket connect() timeout.') def send(self, data, flags=0): total = len(data) next = 0 while 1: r, w, e = select.select([],[self.sock], [], self.timeout) if w: buff = data[next:next + 8192] sent = self.sock.send(buff, flags) next = next + sent if next == total: return total continue raise TimeoutError('socket send() timeout.') def recv(self, amt, flags=0): if select.select([self.sock], [], [], self.timeout)[0]: return self.sock.recv(amt, flags) raise TimeoutError('socket recv() timeout.') buffsize = 4096 handles = 1 def makefile(self, mode="r", buffsize=-1): self.handles = self.handles + 1 self.mode = mode return self def close(self): self.handles = self.handles - 1 if self.handles == 0 and self.sock.fileno() >= 0: self.sock.close() def read(self, n=-1): if not isinstance(n, type(1)): n = -1 if n >= 0: k = len(self._rbuf) if n <= k: data = self._rbuf[:n] self._rbuf = self._rbuf[n:] return data n = n - k L = [self._rbuf] self._rbuf = "" while n > 0: new = self.recv(max(n, self.buffsize)) if not new: break k = len(new) if k > n: L.append(new[:n]) self._rbuf = new[n:] break L.append(new) n = n - k return "".join(L) k = max(4096, self.buffsize) L = [self._rbuf] self._rbuf = "" while 1: new = self.recv(k) if not new: break L.append(new) k = min(k*2, 1024**2) return "".join(L) def readline(self, limit=-1): data = "" i = self._rbuf.find('\n') while i < 0 and not (0 < limit <= len(self._rbuf)): new = self.recv(self.buffsize) if not new: break i = new.find('\n') if i >= 0: i = i + len(self._rbuf) self._rbuf = self._rbuf + new if i < 0: i = len(self._rbuf) else: i = i+1 if 0 <= limit < len(self._rbuf): i = limit data, self._rbuf = self._rbuf[:i], self._rbuf[i:] return data def readlines(self, sizehint = 0): total = 0 list = [] while 1: line = self.readline() if not line: break list.append(line) total += len(line) if sizehint and total >= sizehint: break return list def writelines(self, list): self.send(''.join(list)) def write(self, data): self.send(data) def flush(self): pass class TimeoutError(Exception): pass ZSI-2.1-a1/ZSI/wstools/logging.py0000644000175100017510000002005310634162377014706 0ustar zsizsi# Copyright (c) 2003, The Regents of the University of California, # through Lawrence Berkeley National Laboratory (subject to receipt of # any required approvals from the U.S. Dept. of Energy). All rights # reserved. # """Logging""" ident = "$Id: logging.py 1395 2007-06-14 06:49:35Z boverhof $" import os, sys WARN = 1 DEBUG = 2 class ILogger: '''Logger interface, by default this class will be used and logging calls are no-ops. ''' level = 0 def __init__(self, msg): return def warning(self, *args, **kw): return def debug(self, *args, **kw): return def error(self, *args, **kw): return def setLevel(cls, level): cls.level = level setLevel = classmethod(setLevel) debugOn = lambda self: self.level >= DEBUG warnOn = lambda self: self.level >= WARN class BasicLogger(ILogger): last = '' def __init__(self, msg, out=sys.stdout): self.msg, self.out = msg, out def warning(self, msg, *args, **kw): if self.warnOn() is False: return if BasicLogger.last != self.msg: BasicLogger.last = self.msg print >>self, "---- ", self.msg, " ----" print >>self, " %s " %self.WARN, print >>self, msg %args WARN = '[WARN]' def debug(self, msg, *args, **kw): if self.debugOn() is False: return if BasicLogger.last != self.msg: BasicLogger.last = self.msg print >>self, "---- ", self.msg, " ----" print >>self, " %s " %self.DEBUG, print >>self, msg %args DEBUG = '[DEBUG]' def error(self, msg, *args, **kw): if BasicLogger.last != self.msg: BasicLogger.last = self.msg print >>self, "---- ", self.msg, " ----" print >>self, " %s " %self.ERROR, print >>self, msg %args ERROR = '[ERROR]' def write(self, *args): '''Write convenience function; writes strings. ''' for s in args: self.out.write(s) event = ''.join(*args) _LoggerClass = BasicLogger class GridLogger(ILogger): def debug(self, msg, *args, **kw): kw['component'] = self.msg gridLog(event=msg %args, level='DEBUG', **kw) def warning(self, msg, *args, **kw): kw['component'] = self.msg gridLog(event=msg %args, level='WARNING', **kw) def error(self, msg, *args, **kw): kw['component'] = self.msg gridLog(event=msg %args, level='ERROR', **kw) # # Registry of send functions for gridLog # GLRegistry = {} class GLRecord(dict): """Grid Logging Best Practices Record, Distributed Logging Utilities The following names are reserved: event -- log event name Below is EBNF for the event name part of a log message. name = ( "." )? nodot = {RFC3896-chars except "."} Suffixes: start: Immediately before the first action in a task. end: Immediately after the last action in a task (that succeeded). error: an error condition that does not correspond to an end event. ts -- timestamp level -- logging level (see levels below) status -- integer status code gid -- global grid identifier gid, cgid -- parent/child identifiers prog -- program name More info: http://www.cedps.net/wiki/index.php/LoggingBestPractices#Python reserved -- list of reserved names, omitname -- list of reserved names, output only values ('ts', 'event',) levels -- dict of levels and description """ reserved = ('ts', 'event', 'level', 'status', 'gid', 'prog') omitname = () levels = dict(FATAL='Component cannot continue, or system is unusable.', ALERT='Action must be taken immediately.', CRITICAL='Critical conditions (on the system).', ERROR='Errors in the component; not errors from elsewhere.', WARNING='Problems that are recovered from, usually.', NOTICE='Normal but significant condition.', INFO='Informational messages that would be useful to a deployer or administrator.', DEBUG='Lower level information concerning program logic decisions, internal state, etc.', TRACE='Finest granularity, similar to "stepping through" the component or system.', ) def __init__(self, date=None, **kw): kw['ts'] = date or self.GLDate() kw['gid'] = kw.get('gid') or os.getpid() dict.__init__(self, kw) def __str__(self): """ """ from cStringIO import StringIO s = StringIO(); n = " " reserved = self.reserved; omitname = self.omitname; levels = self.levels for k in ( list(filter(lambda i: self.has_key(i), reserved)) + list(filter(lambda i: i not in reserved, self.keys())) ): v = self[k] if k in omitname: s.write( "%s " %self.format[type(v)](v) ) continue if k == reserved[2] and v not in levels: pass s.write( "%s=%s " %(k, self.format[type(v)](v) ) ) s.write("\n") return s.getvalue() class GLDate(str): """Grid logging Date Format all timestamps should all be in the same time zone (UTC). Grid timestamp value format that is a highly readable variant of the ISO8601 time standard [1]: YYYY-MM-DDTHH:MM:SS.SSSSSSZ """ def __new__(self, args=None): """args -- datetime (year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]) """ import datetime args = args or datetime.datetime.utcnow() l = (args.year, args.month, args.day, args.hour, args.minute, args.second, args.microsecond, args.tzinfo or 'Z') return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" %l) format = { int:str, float:lambda x: "%lf" % x, long:str, str:lambda x:x, unicode:str, GLDate:str, } def gridLog(**kw): """Send GLRecord, Distributed Logging Utilities If the scheme is passed as a keyword parameter the value is expected to be a callable function that takes 2 parameters: url, outputStr GRIDLOG_ON -- turn grid logging on GRIDLOG_DEST -- provide URL destination """ import os if not bool( int(os.environ.get('GRIDLOG_ON', 0)) ): return url = os.environ.get('GRIDLOG_DEST') if url is None: return ## NOTE: urlparse problem w/customized schemes try: scheme = url[:url.find('://')] send = GLRegistry[scheme] send( url, str(GLRecord(**kw)), ) except Exception, ex: print >>sys.stderr, "*** gridLog failed -- %s" %(str(kw)) def sendUDP(url, outputStr): from socket import socket, AF_INET, SOCK_DGRAM idx1 = url.find('://') + 3; idx2 = url.find('/', idx1) if idx2 < idx1: idx2 = len(url) netloc = url[idx1:idx2] host,port = (netloc.split(':')+[80])[0:2] socket(AF_INET, SOCK_DGRAM).sendto( outputStr, (host,int(port)), ) def writeToFile(url, outputStr): print >> open(url.split('://')[1], 'a+'), outputStr GLRegistry["gridlog-udp"] = sendUDP GLRegistry["file"] = writeToFile def setBasicLogger(): '''Use Basic Logger. ''' setLoggerClass(BasicLogger) BasicLogger.setLevel(0) def setGridLogger(): '''Use GridLogger for all logging events. ''' setLoggerClass(GridLogger) def setBasicLoggerWARN(): '''Use Basic Logger. ''' setLoggerClass(BasicLogger) BasicLogger.setLevel(WARN) def setBasicLoggerDEBUG(): '''Use Basic Logger. ''' setLoggerClass(BasicLogger) BasicLogger.setLevel(DEBUG) def setLoggerClass(loggingClass): '''Set Logging Class. ''' def setLoggerClass(loggingClass): '''Set Logging Class. ''' assert issubclass(loggingClass, ILogger), 'loggingClass must subclass ILogger' global _LoggerClass _LoggerClass = loggingClass def setLevel(level=0): '''Set Global Logging Level. ''' ILogger.level = level def getLevel(): return ILogger.level def getLogger(msg): '''Return instance of Logging class. ''' return _LoggerClass(msg) ZSI-2.1-a1/ZSI/wstools/WSDLTools.py0000755000175100017510000016634410371001142015047 0ustar zsizsi# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ident = "$Id: WSDLTools.py 1122 2006-02-04 01:24:50Z boverhof $" import weakref from cStringIO import StringIO from Namespaces import OASIS, XMLNS, WSA, WSA_LIST, WSRF_V1_2, WSRF from Utility import Collection, CollectionNS, DOM, ElementProxy, basejoin from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter class WSDLReader: """A WSDLReader creates WSDL instances from urls and xml data.""" # Custom subclasses of WSDLReader may wish to implement a caching # strategy or other optimizations. Because application needs vary # so widely, we don't try to provide any caching by default. def loadFromStream(self, stream, name=None): """Return a WSDL instance loaded from a stream object.""" document = DOM.loadDocument(stream) wsdl = WSDL() if name: wsdl.location = name elif hasattr(stream, 'name'): wsdl.location = stream.name wsdl.load(document) return wsdl def loadFromURL(self, url): """Return a WSDL instance loaded from the given url.""" document = DOM.loadFromURL(url) wsdl = WSDL() wsdl.location = url wsdl.load(document) return wsdl def loadFromString(self, data): """Return a WSDL instance loaded from an xml string.""" return self.loadFromStream(StringIO(data)) def loadFromFile(self, filename): """Return a WSDL instance loaded from the given file.""" file = open(filename, 'rb') try: wsdl = self.loadFromStream(file) finally: file.close() return wsdl class WSDL: """A WSDL object models a WSDL service description. WSDL objects may be created manually or loaded from an xml representation using a WSDLReader instance.""" def __init__(self, targetNamespace=None, strict=1): self.targetNamespace = targetNamespace or 'urn:this-document.wsdl' self.documentation = '' self.location = None self.document = None self.name = None self.services = CollectionNS(self) self.messages = CollectionNS(self) self.portTypes = CollectionNS(self) self.bindings = CollectionNS(self) self.imports = Collection(self) self.types = Types(self) self.extensions = [] self.strict = strict def __del__(self): if self.document is not None: self.document.unlink() version = '1.1' def addService(self, name, documentation='', targetNamespace=None): if self.services.has_key(name): raise WSDLError( 'Duplicate service element: %s' % name ) item = Service(name, documentation) if targetNamespace: item.targetNamespace = targetNamespace self.services[name] = item return item def addMessage(self, name, documentation='', targetNamespace=None): if self.messages.has_key(name): raise WSDLError( 'Duplicate message element: %s.' % name ) item = Message(name, documentation) if targetNamespace: item.targetNamespace = targetNamespace self.messages[name] = item return item def addPortType(self, name, documentation='', targetNamespace=None): if self.portTypes.has_key(name): raise WSDLError( 'Duplicate portType element: name' ) item = PortType(name, documentation) if targetNamespace: item.targetNamespace = targetNamespace self.portTypes[name] = item return item def addBinding(self, name, type, documentation='', targetNamespace=None): if self.bindings.has_key(name): raise WSDLError( 'Duplicate binding element: %s' % name ) item = Binding(name, type, documentation) if targetNamespace: item.targetNamespace = targetNamespace self.bindings[name] = item return item def addImport(self, namespace, location): item = ImportElement(namespace, location) self.imports[namespace] = item return item def toDom(self): """ Generate a DOM representation of the WSDL instance. Not dealing with generating XML Schema, thus the targetNamespace of all XML Schema elements or types used by WSDL message parts needs to be specified via import information items. """ namespaceURI = DOM.GetWSDLUri(self.version) self.document = DOM.createDocument(namespaceURI ,'wsdl:definitions') # Set up a couple prefixes for easy reading. child = DOM.getElement(self.document, None) child.setAttributeNS(None, 'targetNamespace', self.targetNamespace) child.setAttributeNS(XMLNS.BASE, 'xmlns:wsdl', namespaceURI) child.setAttributeNS(XMLNS.BASE, 'xmlns:xsd', 'http://www.w3.org/1999/XMLSchema') child.setAttributeNS(XMLNS.BASE, 'xmlns:soap', 'http://schemas.xmlsoap.org/wsdl/soap/') child.setAttributeNS(XMLNS.BASE, 'xmlns:tns', self.targetNamespace) if self.name: child.setAttributeNS(None, 'name', self.name) # wsdl:import for item in self.imports: item.toDom() # wsdl:message for item in self.messages: item.toDom() # wsdl:portType for item in self.portTypes: item.toDom() # wsdl:binding for item in self.bindings: item.toDom() # wsdl:service for item in self.services: item.toDom() def load(self, document): # We save a reference to the DOM document to ensure that elements # saved as "extensions" will continue to have a meaningful context # for things like namespace references. The lifetime of the DOM # document is bound to the lifetime of the WSDL instance. self.document = document definitions = DOM.getElement(document, 'definitions', None, None) if definitions is None: raise WSDLError( 'Missing element.' ) self.version = DOM.WSDLUriToVersion(definitions.namespaceURI) NS_WSDL = DOM.GetWSDLUri(self.version) self.targetNamespace = DOM.getAttr(definitions, 'targetNamespace', None, None) self.name = DOM.getAttr(definitions, 'name', None, None) self.documentation = GetDocumentation(definitions) # # Retrieve all 's, append all children of imported # document to main document. First iteration grab all original # 's from document, second iteration grab all # "imported" from document, etc break out when # no more 's. # imported = [] base_location = self.location do_it = True while do_it: do_it = False for element in DOM.getElements(definitions, 'import', NS_WSDL): location = DOM.getAttr(element, 'location') if base_location is not None: location = basejoin(base_location, location) if location not in imported: do_it = True self._import(document, element, base_location) imported.append(location) else: definitions.removeChild(element) base_location = None # # No more 's, now load up all other # WSDL information items. # for element in DOM.getElements(definitions, None, None): targetNamespace = DOM.getAttr(element, 'targetNamespace') localName = element.localName if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL): if localName == 'schema': tns = DOM.getAttr(element, 'targetNamespace') reader = SchemaReader(base_url=self.imports[tns].location) schema = reader.loadFromNode(WSDLToolsAdapter(self), element) # schema.setBaseUrl(self.location) self.types.addSchema(schema) else: self.extensions.append(element) continue elif localName == 'message': name = DOM.getAttr(element, 'name') docs = GetDocumentation(element) message = self.addMessage(name, docs, targetNamespace) parts = DOM.getElements(element, 'part', NS_WSDL) message.load(parts) continue elif localName == 'portType': name = DOM.getAttr(element, 'name') docs = GetDocumentation(element) ptype = self.addPortType(name, docs, targetNamespace) #operations = DOM.getElements(element, 'operation', NS_WSDL) #ptype.load(operations) ptype.load(element) continue elif localName == 'binding': name = DOM.getAttr(element, 'name') type = DOM.getAttr(element, 'type', default=None) if type is None: raise WSDLError( 'Missing type attribute for binding %s.' % name ) type = ParseQName(type, element) docs = GetDocumentation(element) binding = self.addBinding(name, type, docs, targetNamespace) operations = DOM.getElements(element, 'operation', NS_WSDL) binding.load(operations) binding.load_ex(GetExtensions(element)) continue elif localName == 'service': name = DOM.getAttr(element, 'name') docs = GetDocumentation(element) service = self.addService(name, docs, targetNamespace) ports = DOM.getElements(element, 'port', NS_WSDL) service.load(ports) service.load_ex(GetExtensions(element)) continue elif localName == 'types': self.types.documentation = GetDocumentation(element) base_location = DOM.getAttr(element, 'base-location') if base_location: element.removeAttribute('base-location') base_location = base_location or self.location reader = SchemaReader(base_url=base_location) for item in DOM.getElements(element, None, None): if item.localName == 'schema': schema = reader.loadFromNode(WSDLToolsAdapter(self), item) # XXX could have been imported #schema.setBaseUrl(self.location) schema.setBaseUrl(base_location) self.types.addSchema(schema) else: self.types.addExtension(item) # XXX remove the attribute # element.removeAttribute('base-location') continue def _import(self, document, element, base_location=None): '''Algo take element's children, clone them, and add them to the main document. Support for relative locations is a bit complicated. The orig document context is lost, so we need to store base location in DOM elements representing , by creating a special temporary "base-location" attribute, and , by resolving the relative "location" and storing it as "location". document -- document we are loading element -- DOM Element representing base_location -- location of document from which this was gleaned. ''' namespace = DOM.getAttr(element, 'namespace', default=None) location = DOM.getAttr(element, 'location', default=None) if namespace is None or location is None: raise WSDLError( 'Invalid import element (missing namespace or location).' ) if base_location: location = basejoin(base_location, location) element.setAttributeNS(None, 'location', location) obimport = self.addImport(namespace, location) obimport._loaded = 1 importdoc = DOM.loadFromURL(location) try: if location.find('#') > -1: idref = location.split('#')[-1] imported = DOM.getElementById(importdoc, idref) else: imported = importdoc.documentElement if imported is None: raise WSDLError( 'Import target element not found for: %s' % location ) imported_tns = DOM.findTargetNS(imported) if imported_tns != namespace: return if imported.localName == 'definitions': imported_nodes = imported.childNodes else: imported_nodes = [imported] parent = element.parentNode parent.removeChild(element) for node in imported_nodes: if node.nodeType != node.ELEMENT_NODE: continue child = DOM.importNode(document, node, 1) parent.appendChild(child) child.setAttribute('targetNamespace', namespace) attrsNS = imported._attrsNS for attrkey in attrsNS.keys(): if attrkey[0] == DOM.NS_XMLNS: attr = attrsNS[attrkey].cloneNode(1) child.setAttributeNode(attr) #XXX Quick Hack, should be in WSDL Namespace. if child.localName == 'import': rlocation = child.getAttributeNS(None, 'location') alocation = basejoin(location, rlocation) child.setAttribute('location', alocation) elif child.localName == 'types': child.setAttribute('base-location', location) finally: importdoc.unlink() return location class Element: """A class that provides common functions for WSDL element classes.""" def __init__(self, name=None, documentation=''): self.name = name self.documentation = documentation self.extensions = [] def addExtension(self, item): item.parent = weakref.ref(self) self.extensions.append(item) def getWSDL(self): """Return the WSDL object that contains this information item.""" parent = self while 1: # skip any collections if isinstance(parent, WSDL): return parent try: parent = parent.parent() except: break return None class ImportElement(Element): def __init__(self, namespace, location): self.namespace = namespace self.location = location # def getWSDL(self): # """Return the WSDL object that contains this Message Part.""" # return self.parent().parent() def toDom(self): wsdl = self.getWSDL() ep = ElementProxy(None, DOM.getElement(wsdl.document, None)) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'import') epc.setAttributeNS(None, 'namespace', self.namespace) epc.setAttributeNS(None, 'location', self.location) _loaded = None class Types(Collection): default = lambda self,k: k.targetNamespace def __init__(self, parent): Collection.__init__(self, parent) self.documentation = '' self.extensions = [] def addSchema(self, schema): name = schema.targetNamespace self[name] = schema return schema def addExtension(self, item): self.extensions.append(item) class Message(Element): def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.parts = Collection(self) def addPart(self, name, type=None, element=None): if self.parts.has_key(name): raise WSDLError( 'Duplicate message part element: %s' % name ) if type is None and element is None: raise WSDLError( 'Missing type or element attribute for part: %s' % name ) item = MessagePart(name) item.element = element item.type = type self.parts[name] = item return item def load(self, elements): for element in elements: name = DOM.getAttr(element, 'name') part = MessagePart(name) self.parts[name] = part elemref = DOM.getAttr(element, 'element', default=None) typeref = DOM.getAttr(element, 'type', default=None) if typeref is None and elemref is None: raise WSDLError( 'No type or element attribute for part: %s' % name ) if typeref is not None: part.type = ParseTypeRef(typeref, element) if elemref is not None: part.element = ParseTypeRef(elemref, element) # def getElementDeclaration(self): # """Return the XMLSchema.ElementDeclaration instance or None""" # element = None # if self.element: # nsuri,name = self.element # wsdl = self.getWSDL() # if wsdl.types.has_key(nsuri) and wsdl.types[nsuri].elements.has_key(name): # element = wsdl.types[nsuri].elements[name] # return element # # def getTypeDefinition(self): # """Return the XMLSchema.TypeDefinition instance or None""" # type = None # if self.type: # nsuri,name = self.type # wsdl = self.getWSDL() # if wsdl.types.has_key(nsuri) and wsdl.types[nsuri].types.has_key(name): # type = wsdl.types[nsuri].types[name] # return type # def getWSDL(self): # """Return the WSDL object that contains this Message Part.""" # return self.parent().parent() def toDom(self): wsdl = self.getWSDL() ep = ElementProxy(None, DOM.getElement(wsdl.document, None)) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'message') epc.setAttributeNS(None, 'name', self.name) for part in self.parts: part.toDom(epc._getNode()) class MessagePart(Element): def __init__(self, name): Element.__init__(self, name, '') self.element = None self.type = None # def getWSDL(self): # """Return the WSDL object that contains this Message Part.""" # return self.parent().parent().parent().parent() def getTypeDefinition(self): wsdl = self.getWSDL() nsuri,name = self.type schema = wsdl.types.get(nsuri, {}) return schema.get(name) def getElementDeclaration(self): wsdl = self.getWSDL() nsuri,name = self.element schema = wsdl.types.get(nsuri, {}) return schema.get(name) def toDom(self, node): """node -- node representing message""" wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'part') epc.setAttributeNS(None, 'name', self.name) if self.element is not None: ns,name = self.element prefix = epc.getPrefix(ns) epc.setAttributeNS(None, 'element', '%s:%s'%(prefix,name)) elif self.type is not None: ns,name = self.type prefix = epc.getPrefix(ns) epc.setAttributeNS(None, 'type', '%s:%s'%(prefix,name)) class PortType(Element): '''PortType has a anyAttribute, thus must provide for an extensible mechanism for supporting such attributes. ResourceProperties is specified in WS-ResourceProperties. wsa:Action is specified in WS-Address. Instance Data: name -- name attribute resourceProperties -- optional. wsr:ResourceProperties attribute, value is a QName this is Parsed into a (namespaceURI, name) that represents a Global Element Declaration. operations ''' def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.operations = Collection(self) self.resourceProperties = None # def getWSDL(self): # return self.parent().parent() def getTargetNamespace(self): return self.targetNamespace or self.getWSDL().targetNamespace def getResourceProperties(self): return self.resourceProperties def addOperation(self, name, documentation='', parameterOrder=None): item = Operation(name, documentation, parameterOrder) self.operations[name] = item return item def load(self, element): self.name = DOM.getAttr(element, 'name') self.documentation = GetDocumentation(element) self.targetNamespace = DOM.getAttr(element, 'targetNamespace') for nsuri in WSRF_V1_2.PROPERTIES.XSD_LIST: if DOM.hasAttr(element, 'ResourceProperties', nsuri): rpref = DOM.getAttr(element, 'ResourceProperties', nsuri) self.resourceProperties = ParseQName(rpref, element) NS_WSDL = DOM.GetWSDLUri(self.getWSDL().version) elements = DOM.getElements(element, 'operation', NS_WSDL) for element in elements: name = DOM.getAttr(element, 'name') docs = GetDocumentation(element) param_order = DOM.getAttr(element, 'parameterOrder', default=None) if param_order is not None: param_order = param_order.split(' ') operation = self.addOperation(name, docs, param_order) item = DOM.getElement(element, 'input', None, None) if item is not None: name = DOM.getAttr(item, 'name') docs = GetDocumentation(item) msgref = DOM.getAttr(item, 'message') message = ParseQName(msgref, item) for WSA in WSA_LIST: action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) if action: break operation.setInput(message, name, docs, action) item = DOM.getElement(element, 'output', None, None) if item is not None: name = DOM.getAttr(item, 'name') docs = GetDocumentation(item) msgref = DOM.getAttr(item, 'message') message = ParseQName(msgref, item) for WSA in WSA_LIST: action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) if action: break operation.setOutput(message, name, docs, action) for item in DOM.getElements(element, 'fault', None): name = DOM.getAttr(item, 'name') docs = GetDocumentation(item) msgref = DOM.getAttr(item, 'message') message = ParseQName(msgref, item) for WSA in WSA_LIST: action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) if action: break operation.addFault(message, name, docs, action) def toDom(self): wsdl = self.getWSDL() ep = ElementProxy(None, DOM.getElement(wsdl.document, None)) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'portType') epc.setAttributeNS(None, 'name', self.name) if self.resourceProperties: ns,name = self.resourceProperties prefix = epc.getPrefix(ns) epc.setAttributeNS(WSRF.PROPERTIES.LATEST, 'ResourceProperties', '%s:%s'%(prefix,name)) for op in self.operations: op.toDom(epc._getNode()) class Operation(Element): def __init__(self, name, documentation='', parameterOrder=None): Element.__init__(self, name, documentation) self.parameterOrder = parameterOrder self.faults = Collection(self) self.input = None self.output = None def getWSDL(self): """Return the WSDL object that contains this Operation.""" return self.parent().parent().parent().parent() def getPortType(self): return self.parent().parent() def getInputAction(self): """wsa:Action attribute""" return GetWSAActionInput(self) def getInputMessage(self): if self.input is None: return None wsdl = self.getPortType().getWSDL() return wsdl.messages[self.input.message] def getOutputAction(self): """wsa:Action attribute""" return GetWSAActionOutput(self) def getOutputMessage(self): if self.output is None: return None wsdl = self.getPortType().getWSDL() return wsdl.messages[self.output.message] def getFaultAction(self, name): """wsa:Action attribute""" return GetWSAActionFault(self, name) def getFaultMessage(self, name): wsdl = self.getPortType().getWSDL() return wsdl.messages[self.faults[name].message] def addFault(self, message, name, documentation='', action=None): if self.faults.has_key(name): raise WSDLError( 'Duplicate fault element: %s' % name ) item = MessageRole('fault', message, name, documentation, action) self.faults[name] = item return item def setInput(self, message, name='', documentation='', action=None): self.input = MessageRole('input', message, name, documentation, action) self.input.parent = weakref.ref(self) return self.input def setOutput(self, message, name='', documentation='', action=None): self.output = MessageRole('output', message, name, documentation, action) self.output.parent = weakref.ref(self) return self.output def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'operation') epc.setAttributeNS(None, 'name', self.name) node = epc._getNode() if self.input: self.input.toDom(node) if self.output: self.output.toDom(node) for fault in self.faults: fault.toDom(node) class MessageRole(Element): def __init__(self, type, message, name='', documentation='', action=None): Element.__init__(self, name, documentation) self.message = message self.type = type self.action = action def getWSDL(self): """Return the WSDL object that contains this information item.""" parent = self while 1: # skip any collections if isinstance(parent, WSDL): return parent try: parent = parent.parent() except: break return None def getMessage(self): """Return the WSDL object that represents the attribute message (namespaceURI, name) tuple """ wsdl = self.getWSDL() return wsdl.messages[self.message] def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type) if not isinstance(self.message, basestring) and len(self.message) == 2: ns,name = self.message prefix = epc.getPrefix(ns) epc.setAttributeNS(None, 'message', '%s:%s' %(prefix,name)) else: epc.setAttributeNS(None, 'message', self.message) if self.action: epc.setAttributeNS(WSA.ADDRESS, 'Action', self.action) if self.name: epc.setAttributeNS(None, 'name', self.name) class Binding(Element): def __init__(self, name, type, documentation=''): Element.__init__(self, name, documentation) self.operations = Collection(self) self.type = type # def getWSDL(self): # """Return the WSDL object that contains this binding.""" # return self.parent().parent() def getPortType(self): """Return the PortType object associated with this binding.""" return self.getWSDL().portTypes[self.type] def findBinding(self, kind): for item in self.extensions: if isinstance(item, kind): return item return None def findBindings(self, kind): return [ item for item in self.extensions if isinstance(item, kind) ] def addOperationBinding(self, name, documentation=''): item = OperationBinding(name, documentation) self.operations[name] = item return item def load(self, elements): for element in elements: name = DOM.getAttr(element, 'name') docs = GetDocumentation(element) opbinding = self.addOperationBinding(name, docs) opbinding.load_ex(GetExtensions(element)) item = DOM.getElement(element, 'input', None, None) if item is not None: #TODO: addInputBinding? mbinding = MessageRoleBinding('input') mbinding.documentation = GetDocumentation(item) opbinding.input = mbinding mbinding.load_ex(GetExtensions(item)) mbinding.parent = weakref.ref(opbinding) item = DOM.getElement(element, 'output', None, None) if item is not None: mbinding = MessageRoleBinding('output') mbinding.documentation = GetDocumentation(item) opbinding.output = mbinding mbinding.load_ex(GetExtensions(item)) mbinding.parent = weakref.ref(opbinding) for item in DOM.getElements(element, 'fault', None): name = DOM.getAttr(item, 'name') mbinding = MessageRoleBinding('fault', name) mbinding.documentation = GetDocumentation(item) opbinding.faults[name] = mbinding mbinding.load_ex(GetExtensions(item)) mbinding.parent = weakref.ref(opbinding) def load_ex(self, elements): for e in elements: ns, name = e.namespaceURI, e.localName if ns in DOM.NS_SOAP_BINDING_ALL and name == 'binding': transport = DOM.getAttr(e, 'transport', default=None) style = DOM.getAttr(e, 'style', default='document') ob = SoapBinding(transport, style) self.addExtension(ob) continue elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'binding': verb = DOM.getAttr(e, 'verb') ob = HttpBinding(verb) self.addExtension(ob) continue else: self.addExtension(e) def toDom(self): wsdl = self.getWSDL() ep = ElementProxy(None, DOM.getElement(wsdl.document, None)) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'binding') epc.setAttributeNS(None, 'name', self.name) ns,name = self.type prefix = epc.getPrefix(ns) epc.setAttributeNS(None, 'type', '%s:%s' %(prefix,name)) node = epc._getNode() for ext in self.extensions: ext.toDom(node) for op_binding in self.operations: op_binding.toDom(node) class OperationBinding(Element): def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.input = None self.output = None self.faults = Collection(self) # def getWSDL(self): # """Return the WSDL object that contains this binding.""" # return self.parent().parent().parent().parent() def getBinding(self): """Return the parent Binding object of the operation binding.""" return self.parent().parent() def getOperation(self): """Return the abstract Operation associated with this binding.""" return self.getBinding().getPortType().operations[self.name] def findBinding(self, kind): for item in self.extensions: if isinstance(item, kind): return item return None def findBindings(self, kind): return [ item for item in self.extensions if isinstance(item, kind) ] def addInputBinding(self, binding): if self.input is None: self.input = MessageRoleBinding('input') self.input.parent = weakref.ref(self) self.input.addExtension(binding) return binding def addOutputBinding(self, binding): if self.output is None: self.output = MessageRoleBinding('output') self.output.parent = weakref.ref(self) self.output.addExtension(binding) return binding def addFaultBinding(self, name, binding): fault = self.get(name, None) if fault is None: fault = MessageRoleBinding('fault', name) fault.addExtension(binding) return binding def load_ex(self, elements): for e in elements: ns, name = e.namespaceURI, e.localName if ns in DOM.NS_SOAP_BINDING_ALL and name == 'operation': soapaction = DOM.getAttr(e, 'soapAction', default=None) style = DOM.getAttr(e, 'style', default=None) ob = SoapOperationBinding(soapaction, style) self.addExtension(ob) continue elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'operation': location = DOM.getAttr(e, 'location') ob = HttpOperationBinding(location) self.addExtension(ob) continue else: self.addExtension(e) def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'operation') epc.setAttributeNS(None, 'name', self.name) node = epc._getNode() for ext in self.extensions: ext.toDom(node) if self.input: self.input.toDom(node) if self.output: self.output.toDom(node) for fault in self.faults: fault.toDom(node) class MessageRoleBinding(Element): def __init__(self, type, name='', documentation=''): Element.__init__(self, name, documentation) self.type = type def findBinding(self, kind): for item in self.extensions: if isinstance(item, kind): return item return None def findBindings(self, kind): return [ item for item in self.extensions if isinstance(item, kind) ] def load_ex(self, elements): for e in elements: ns, name = e.namespaceURI, e.localName if ns in DOM.NS_SOAP_BINDING_ALL and name == 'body': encstyle = DOM.getAttr(e, 'encodingStyle', default=None) namespace = DOM.getAttr(e, 'namespace', default=None) parts = DOM.getAttr(e, 'parts', default=None) use = DOM.getAttr(e, 'use', default=None) if use is None: raise WSDLError( 'Invalid soap:body binding element.' ) ob = SoapBodyBinding(use, namespace, encstyle, parts) self.addExtension(ob) continue elif ns in DOM.NS_SOAP_BINDING_ALL and name == 'fault': encstyle = DOM.getAttr(e, 'encodingStyle', default=None) namespace = DOM.getAttr(e, 'namespace', default=None) name = DOM.getAttr(e, 'name', default=None) use = DOM.getAttr(e, 'use', default=None) if use is None or name is None: raise WSDLError( 'Invalid soap:fault binding element.' ) ob = SoapFaultBinding(name, use, namespace, encstyle) self.addExtension(ob) continue elif ns in DOM.NS_SOAP_BINDING_ALL and name in ( 'header', 'headerfault' ): encstyle = DOM.getAttr(e, 'encodingStyle', default=None) namespace = DOM.getAttr(e, 'namespace', default=None) message = DOM.getAttr(e, 'message') part = DOM.getAttr(e, 'part') use = DOM.getAttr(e, 'use') if name == 'header': _class = SoapHeaderBinding else: _class = SoapHeaderFaultBinding message = ParseQName(message, e) ob = _class(message, part, use, namespace, encstyle) self.addExtension(ob) continue elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'urlReplacement': ob = HttpUrlReplacementBinding() self.addExtension(ob) continue elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'urlEncoded': ob = HttpUrlEncodedBinding() self.addExtension(ob) continue elif ns in DOM.NS_MIME_BINDING_ALL and name == 'multipartRelated': ob = MimeMultipartRelatedBinding() self.addExtension(ob) ob.load_ex(GetExtensions(e)) continue elif ns in DOM.NS_MIME_BINDING_ALL and name == 'content': part = DOM.getAttr(e, 'part', default=None) type = DOM.getAttr(e, 'type', default=None) ob = MimeContentBinding(part, type) self.addExtension(ob) continue elif ns in DOM.NS_MIME_BINDING_ALL and name == 'mimeXml': part = DOM.getAttr(e, 'part', default=None) ob = MimeXmlBinding(part) self.addExtension(ob) continue else: self.addExtension(e) def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type) node = epc._getNode() for item in self.extensions: if item: item.toDom(node) class Service(Element): def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.ports = Collection(self) def getWSDL(self): return self.parent().parent() def addPort(self, name, binding, documentation=''): item = Port(name, binding, documentation) self.ports[name] = item return item def load(self, elements): for element in elements: name = DOM.getAttr(element, 'name', default=None) docs = GetDocumentation(element) binding = DOM.getAttr(element, 'binding', default=None) if name is None or binding is None: raise WSDLError( 'Invalid port element.' ) binding = ParseQName(binding, element) port = self.addPort(name, binding, docs) port.load_ex(GetExtensions(element)) def load_ex(self, elements): for e in elements: self.addExtension(e) def toDom(self): wsdl = self.getWSDL() ep = ElementProxy(None, DOM.getElement(wsdl.document, None)) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "service") epc.setAttributeNS(None, "name", self.name) node = epc._getNode() for port in self.ports: port.toDom(node) class Port(Element): def __init__(self, name, binding, documentation=''): Element.__init__(self, name, documentation) self.binding = binding # def getWSDL(self): # return self.parent().parent().getWSDL() def getService(self): """Return the Service object associated with this port.""" return self.parent().parent() def getBinding(self): """Return the Binding object that is referenced by this port.""" wsdl = self.getService().getWSDL() return wsdl.bindings[self.binding] def getPortType(self): """Return the PortType object that is referenced by this port.""" wsdl = self.getService().getWSDL() binding = wsdl.bindings[self.binding] return wsdl.portTypes[binding.type] def getAddressBinding(self): """A convenience method to obtain the extension element used as the address binding for the port.""" for item in self.extensions: if isinstance(item, SoapAddressBinding) or \ isinstance(item, HttpAddressBinding): return item raise WSDLError( 'No address binding found in port.' ) def load_ex(self, elements): for e in elements: ns, name = e.namespaceURI, e.localName if ns in DOM.NS_SOAP_BINDING_ALL and name == 'address': location = DOM.getAttr(e, 'location', default=None) ob = SoapAddressBinding(location) self.addExtension(ob) continue elif ns in DOM.NS_HTTP_BINDING_ALL and name == 'address': location = DOM.getAttr(e, 'location', default=None) ob = HttpAddressBinding(location) self.addExtension(ob) continue else: self.addExtension(e) def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "port") epc.setAttributeNS(None, "name", self.name) ns,name = self.binding prefix = epc.getPrefix(ns) epc.setAttributeNS(None, "binding", "%s:%s" %(prefix,name)) node = epc._getNode() for ext in self.extensions: ext.toDom(node) class SoapBinding: def __init__(self, transport, style='rpc'): self.transport = transport self.style = style def getWSDL(self): return self.parent().getWSDL() def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'binding') if self.transport: epc.setAttributeNS(None, "transport", self.transport) if self.style: epc.setAttributeNS(None, "style", self.style) class SoapAddressBinding: def __init__(self, location): self.location = location def getWSDL(self): return self.parent().getWSDL() def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'address') epc.setAttributeNS(None, "location", self.location) class SoapOperationBinding: def __init__(self, soapAction=None, style=None): self.soapAction = soapAction self.style = style def getWSDL(self): return self.parent().getWSDL() def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'operation') if self.soapAction: epc.setAttributeNS(None, 'soapAction', self.soapAction) if self.style: epc.setAttributeNS(None, 'style', self.style) class SoapBodyBinding: def __init__(self, use, namespace=None, encodingStyle=None, parts=None): if not use in ('literal', 'encoded'): raise WSDLError( 'Invalid use attribute value: %s' % use ) self.encodingStyle = encodingStyle self.namespace = namespace if type(parts) in (type(''), type(u'')): parts = parts.split() self.parts = parts self.use = use def getWSDL(self): return self.parent().getWSDL() def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'body') epc.setAttributeNS(None, "use", self.use) epc.setAttributeNS(None, "namespace", self.namespace) class SoapFaultBinding: def __init__(self, name, use, namespace=None, encodingStyle=None): if not use in ('literal', 'encoded'): raise WSDLError( 'Invalid use attribute value: %s' % use ) self.encodingStyle = encodingStyle self.namespace = namespace self.name = name self.use = use def getWSDL(self): return self.parent().getWSDL() def toDom(self, node): wsdl = self.getWSDL() ep = ElementProxy(None, node) epc = ep.createAppendElement(DOM.GetWSDLSoapBindingUri(wsdl.version), 'body') epc.setAttributeNS(None, "use", self.use) epc.setAttributeNS(None, "name", self.name) if self.namespace is not None: epc.setAttributeNS(None, "namespace", self.namespace) if self.encodingStyle is not None: epc.setAttributeNS(None, "encodingStyle", self.encodingStyle) class SoapHeaderBinding: def __init__(self, message, part, use, namespace=None, encodingStyle=None): if not use in ('literal', 'encoded'): raise WSDLError( 'Invalid use attribute value: %s' % use ) self.encodingStyle = encodingStyle self.namespace = namespace self.message = message self.part = part self.use = use tagname = 'header' class SoapHeaderFaultBinding(SoapHeaderBinding): tagname = 'headerfault' class HttpBinding: def __init__(self, verb): self.verb = verb class HttpAddressBinding: def __init__(self, location): self.location = location class HttpOperationBinding: def __init__(self, location): self.location = location class HttpUrlReplacementBinding: pass class HttpUrlEncodedBinding: pass class MimeContentBinding: def __init__(self, part=None, type=None): self.part = part self.type = type class MimeXmlBinding: def __init__(self, part=None): self.part = part class MimeMultipartRelatedBinding: def __init__(self): self.parts = [] def load_ex(self, elements): for e in elements: ns, name = e.namespaceURI, e.localName if ns in DOM.NS_MIME_BINDING_ALL and name == 'part': self.parts.append(MimePartBinding()) continue class MimePartBinding: def __init__(self): self.items = [] def load_ex(self, elements): for e in elements: ns, name = e.namespaceURI, e.localName if ns in DOM.NS_MIME_BINDING_ALL and name == 'content': part = DOM.getAttr(e, 'part', default=None) type = DOM.getAttr(e, 'type', default=None) ob = MimeContentBinding(part, type) self.items.append(ob) continue elif ns in DOM.NS_MIME_BINDING_ALL and name == 'mimeXml': part = DOM.getAttr(e, 'part', default=None) ob = MimeXmlBinding(part) self.items.append(ob) continue elif ns in DOM.NS_SOAP_BINDING_ALL and name == 'body': encstyle = DOM.getAttr(e, 'encodingStyle', default=None) namespace = DOM.getAttr(e, 'namespace', default=None) parts = DOM.getAttr(e, 'parts', default=None) use = DOM.getAttr(e, 'use', default=None) if use is None: raise WSDLError( 'Invalid soap:body binding element.' ) ob = SoapBodyBinding(use, namespace, encstyle, parts) self.items.append(ob) continue class WSDLError(Exception): pass def DeclareNSPrefix(writer, prefix, nsuri): if writer.hasNSPrefix(nsuri): return writer.declareNSPrefix(prefix, nsuri) def ParseTypeRef(value, element): parts = value.split(':', 1) if len(parts) == 1: return (DOM.findTargetNS(element), value) nsuri = DOM.findNamespaceURI(parts[0], element) return (nsuri, parts[1]) def ParseQName(value, element): nameref = value.split(':', 1) if len(nameref) == 2: nsuri = DOM.findNamespaceURI(nameref[0], element) name = nameref[-1] else: nsuri = DOM.findTargetNS(element) name = nameref[-1] return nsuri, name def GetDocumentation(element): docnode = DOM.getElement(element, 'documentation', None, None) if docnode is not None: return DOM.getElementText(docnode) return '' def GetExtensions(element): return [ item for item in DOM.getElements(element, None, None) if item.namespaceURI != DOM.NS_WSDL ] def GetWSAActionFault(operation, name): """Find wsa:Action attribute, and return value or WSA.FAULT for the default. """ attr = operation.faults[name].action if attr is not None: return attr return WSA.FAULT def GetWSAActionInput(operation): """Find wsa:Action attribute, and return value or the default.""" attr = operation.input.action if attr is not None: return attr portType = operation.getPortType() targetNamespace = portType.getTargetNamespace() ptName = portType.name msgName = operation.input.name if not msgName: msgName = operation.name + 'Request' if targetNamespace.endswith('/'): return '%s%s/%s' %(targetNamespace, ptName, msgName) return '%s/%s/%s' %(targetNamespace, ptName, msgName) def GetWSAActionOutput(operation): """Find wsa:Action attribute, and return value or the default.""" attr = operation.output.action if attr is not None: return attr targetNamespace = operation.getPortType().getTargetNamespace() ptName = operation.getPortType().name msgName = operation.output.name if not msgName: msgName = operation.name + 'Response' if targetNamespace.endswith('/'): return '%s%s/%s' %(targetNamespace, ptName, msgName) return '%s/%s/%s' %(targetNamespace, ptName, msgName) def FindExtensions(object, kind, t_type=type(())): if isinstance(kind, t_type): result = [] namespaceURI, name = kind return [ item for item in object.extensions if hasattr(item, 'nodeType') \ and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ and item.name == name ] return [ item for item in object.extensions if isinstance(item, kind) ] def FindExtension(object, kind, t_type=type(())): if isinstance(kind, t_type): namespaceURI, name = kind for item in object.extensions: if hasattr(item, 'nodeType') \ and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ and item.name == name: return item else: for item in object.extensions: if isinstance(item, kind): return item return None class SOAPCallInfo: """SOAPCallInfo captures the important binding information about a SOAP operation, in a structure that is easier to work with than raw WSDL structures.""" def __init__(self, methodName): self.methodName = methodName self.inheaders = [] self.outheaders = [] self.inparams = [] self.outparams = [] self.retval = None encodingStyle = DOM.NS_SOAP_ENC documentation = '' soapAction = None transport = None namespace = None location = None use = 'encoded' style = 'rpc' def addInParameter(self, name, type, namespace=None, element_type=0): """Add an input parameter description to the call info.""" parameter = ParameterInfo(name, type, namespace, element_type) self.inparams.append(parameter) return parameter def addOutParameter(self, name, type, namespace=None, element_type=0): """Add an output parameter description to the call info.""" parameter = ParameterInfo(name, type, namespace, element_type) self.outparams.append(parameter) return parameter def setReturnParameter(self, name, type, namespace=None, element_type=0): """Set the return parameter description for the call info.""" parameter = ParameterInfo(name, type, namespace, element_type) self.retval = parameter return parameter def addInHeaderInfo(self, name, type, namespace, element_type=0, mustUnderstand=0): """Add an input SOAP header description to the call info.""" headerinfo = HeaderInfo(name, type, namespace, element_type) if mustUnderstand: headerinfo.mustUnderstand = 1 self.inheaders.append(headerinfo) return headerinfo def addOutHeaderInfo(self, name, type, namespace, element_type=0, mustUnderstand=0): """Add an output SOAP header description to the call info.""" headerinfo = HeaderInfo(name, type, namespace, element_type) if mustUnderstand: headerinfo.mustUnderstand = 1 self.outheaders.append(headerinfo) return headerinfo def getInParameters(self): """Return a sequence of the in parameters of the method.""" return self.inparams def getOutParameters(self): """Return a sequence of the out parameters of the method.""" return self.outparams def getReturnParameter(self): """Return param info about the return value of the method.""" return self.retval def getInHeaders(self): """Return a sequence of the in headers of the method.""" return self.inheaders def getOutHeaders(self): """Return a sequence of the out headers of the method.""" return self.outheaders class ParameterInfo: """A ParameterInfo object captures parameter binding information.""" def __init__(self, name, type, namespace=None, element_type=0): if element_type: self.element_type = 1 if namespace is not None: self.namespace = namespace self.name = name self.type = type element_type = 0 namespace = None default = None class HeaderInfo(ParameterInfo): """A HeaderInfo object captures SOAP header binding information.""" def __init__(self, name, type, namespace, element_type=None): ParameterInfo.__init__(self, name, type, namespace, element_type) mustUnderstand = 0 actor = None def callInfoFromWSDL(port, name): """Return a SOAPCallInfo given a WSDL port and operation name.""" wsdl = port.getService().getWSDL() binding = port.getBinding() portType = binding.getPortType() operation = portType.operations[name] opbinding = binding.operations[name] messages = wsdl.messages callinfo = SOAPCallInfo(name) addrbinding = port.getAddressBinding() if not isinstance(addrbinding, SoapAddressBinding): raise ValueError, 'Unsupported binding type.' callinfo.location = addrbinding.location soapbinding = binding.findBinding(SoapBinding) if soapbinding is None: raise ValueError, 'Missing soap:binding element.' callinfo.transport = soapbinding.transport callinfo.style = soapbinding.style or 'document' soap_op_binding = opbinding.findBinding(SoapOperationBinding) if soap_op_binding is not None: callinfo.soapAction = soap_op_binding.soapAction callinfo.style = soap_op_binding.style or callinfo.style parameterOrder = operation.parameterOrder if operation.input is not None: message = messages[operation.input.message] msgrole = opbinding.input mime = msgrole.findBinding(MimeMultipartRelatedBinding) if mime is not None: raise ValueError, 'Mime bindings are not supported.' else: for item in msgrole.findBindings(SoapHeaderBinding): part = messages[item.message].parts[item.part] header = callinfo.addInHeaderInfo( part.name, part.element or part.type, item.namespace, element_type = part.element and 1 or 0 ) header.encodingStyle = item.encodingStyle body = msgrole.findBinding(SoapBodyBinding) if body is None: raise ValueError, 'Missing soap:body binding.' callinfo.encodingStyle = body.encodingStyle callinfo.namespace = body.namespace callinfo.use = body.use if body.parts is not None: parts = [] for name in body.parts: parts.append(message.parts[name]) else: parts = message.parts.values() for part in parts: callinfo.addInParameter( part.name, part.element or part.type, element_type = part.element and 1 or 0 ) if operation.output is not None: try: message = messages[operation.output.message] except KeyError: if self.strict: raise RuntimeError( "Recieved message not defined in the WSDL schema: %s" % operation.output.message) else: message = wsdl.addMessage(operation.output.message) print "Warning:", \ "Recieved message not defined in the WSDL schema.", \ "Adding it." print "Message:", operation.output.message msgrole = opbinding.output mime = msgrole.findBinding(MimeMultipartRelatedBinding) if mime is not None: raise ValueError, 'Mime bindings are not supported.' else: for item in msgrole.findBindings(SoapHeaderBinding): part = messages[item.message].parts[item.part] header = callinfo.addOutHeaderInfo( part.name, part.element or part.type, item.namespace, element_type = part.element and 1 or 0 ) header.encodingStyle = item.encodingStyle body = msgrole.findBinding(SoapBodyBinding) if body is None: raise ValueError, 'Missing soap:body binding.' callinfo.encodingStyle = body.encodingStyle callinfo.namespace = body.namespace callinfo.use = body.use if body.parts is not None: parts = [] for name in body.parts: parts.append(message.parts[name]) else: parts = message.parts.values() if parts: for part in parts: callinfo.addOutParameter( part.name, part.element or part.type, element_type = part.element and 1 or 0 ) return callinfo ZSI-2.1-a1/ZSI/wstools/XMLSchema.py0000755000175100017510000032626310712453147015053 0ustar zsizsi# Copyright (c) 2003, The Regents of the University of California, # through Lawrence Berkeley National Laboratory (subject to receipt of # any required approvals from the U.S. Dept. of Energy). All rights # reserved. # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ident = "$Id: XMLSchema.py 1434 2007-11-01 22:42:47Z boverhof $" import types, weakref, sys, warnings from Namespaces import SCHEMA, XMLNS, SOAP from Utility import DOM, DOMException, Collection, SplitQName, basejoin from StringIO import StringIO # If we have no threading, this should be a no-op try: from threading import RLock except ImportError: class RLock: def acquire(): pass def release(): pass # # Collections in XMLSchema class # TYPES = 'types' ATTRIBUTE_GROUPS = 'attr_groups' ATTRIBUTES = 'attr_decl' ELEMENTS = 'elements' MODEL_GROUPS = 'model_groups' BUILT_IN_NAMESPACES = [SOAP.ENC,] + SCHEMA.XSD_LIST def GetSchema(component): """convience function for finding the parent XMLSchema instance. """ parent = component while not isinstance(parent, XMLSchema): parent = parent._parent() return parent class SchemaReader: """A SchemaReader creates XMLSchema objects from urls and xml data. """ namespaceToSchema = {} def __init__(self, domReader=None, base_url=None): """domReader -- class must implement DOMAdapterInterface base_url -- base url string """ self.__base_url = base_url self.__readerClass = domReader if not self.__readerClass: self.__readerClass = DOMAdapter self._includes = {} self._imports = {} def __setImports(self, schema): """Add dictionary of imports to schema instance. schema -- XMLSchema instance """ for ns,val in schema.imports.items(): if self._imports.has_key(ns): schema.addImportSchema(self._imports[ns]) def __setIncludes(self, schema): """Add dictionary of includes to schema instance. schema -- XMLSchema instance """ for schemaLocation, val in schema.includes.items(): if self._includes.has_key(schemaLocation): schema.addIncludeSchema(schemaLocation, self._imports[schemaLocation]) def addSchemaByLocation(self, location, schema): """provide reader with schema document for a location. """ self._includes[location] = schema def addSchemaByNamespace(self, schema): """provide reader with schema document for a targetNamespace. """ self._imports[schema.targetNamespace] = schema def loadFromNode(self, parent, element): """element -- DOM node or document parent -- WSDLAdapter instance """ reader = self.__readerClass(element) schema = XMLSchema(parent) #HACK to keep a reference schema.wsdl = parent schema.setBaseUrl(self.__base_url) schema.load(reader) return schema def loadFromStream(self, file, url=None): """Return an XMLSchema instance loaded from a file object. file -- file object url -- base location for resolving imports/includes. """ reader = self.__readerClass() reader.loadDocument(file) schema = XMLSchema() if url is not None: schema.setBaseUrl(url) schema.load(reader) self.__setIncludes(schema) self.__setImports(schema) return schema def loadFromString(self, data): """Return an XMLSchema instance loaded from an XML string. data -- XML string """ return self.loadFromStream(StringIO(data)) def loadFromURL(self, url, schema=None): """Return an XMLSchema instance loaded from the given url. url -- URL to dereference schema -- Optional XMLSchema instance. """ reader = self.__readerClass() if self.__base_url: url = basejoin(self.__base_url,url) reader.loadFromURL(url) schema = schema or XMLSchema() schema.setBaseUrl(url) schema.load(reader) self.__setIncludes(schema) self.__setImports(schema) return schema def loadFromFile(self, filename): """Return an XMLSchema instance loaded from the given file. filename -- name of file to open """ if self.__base_url: filename = basejoin(self.__base_url,filename) file = open(filename, 'rb') try: schema = self.loadFromStream(file, filename) finally: file.close() return schema class SchemaError(Exception): pass class NoSchemaLocationWarning(Exception): pass ########################### # DOM Utility Adapters ########################## class DOMAdapterInterface: def hasattr(self, attr, ns=None): """return true if node has attribute attr -- attribute to check for ns -- namespace of attribute, by default None """ raise NotImplementedError, 'adapter method not implemented' def getContentList(self, *contents): """returns an ordered list of child nodes *contents -- list of node names to return """ raise NotImplementedError, 'adapter method not implemented' def setAttributeDictionary(self, attributes): """set attribute dictionary """ raise NotImplementedError, 'adapter method not implemented' def getAttributeDictionary(self): """returns a dict of node's attributes """ raise NotImplementedError, 'adapter method not implemented' def getNamespace(self, prefix): """returns namespace referenced by prefix. """ raise NotImplementedError, 'adapter method not implemented' def getTagName(self): """returns tagName of node """ raise NotImplementedError, 'adapter method not implemented' def getParentNode(self): """returns parent element in DOMAdapter or None """ raise NotImplementedError, 'adapter method not implemented' def loadDocument(self, file): """load a Document from a file object file -- """ raise NotImplementedError, 'adapter method not implemented' def loadFromURL(self, url): """load a Document from an url url -- URL to dereference """ raise NotImplementedError, 'adapter method not implemented' class DOMAdapter(DOMAdapterInterface): """Adapter for ZSI.Utility.DOM """ def __init__(self, node=None): """Reset all instance variables. element -- DOM document, node, or None """ if hasattr(node, 'documentElement'): self.__node = node.documentElement else: self.__node = node self.__attributes = None def getNode(self): return self.__node def hasattr(self, attr, ns=None): """attr -- attribute ns -- optional namespace, None means unprefixed attribute. """ if not self.__attributes: self.setAttributeDictionary() if ns: return self.__attributes.get(ns,{}).has_key(attr) return self.__attributes.has_key(attr) def getContentList(self, *contents): nodes = [] ELEMENT_NODE = self.__node.ELEMENT_NODE for child in DOM.getElements(self.__node, None): if child.nodeType == ELEMENT_NODE and\ SplitQName(child.tagName)[1] in contents: nodes.append(child) return map(self.__class__, nodes) def setAttributeDictionary(self): self.__attributes = {} for v in self.__node._attrs.values(): self.__attributes[v.nodeName] = v.nodeValue def getAttributeDictionary(self): if not self.__attributes: self.setAttributeDictionary() return self.__attributes def getTagName(self): return self.__node.tagName def getParentNode(self): if self.__node.parentNode.nodeType == self.__node.ELEMENT_NODE: return DOMAdapter(self.__node.parentNode) return None def getNamespace(self, prefix): """prefix -- deference namespace prefix in node's context. Ascends parent nodes until found. """ namespace = None if prefix == 'xmlns': namespace = DOM.findDefaultNS(prefix, self.__node) else: try: namespace = DOM.findNamespaceURI(prefix, self.__node) except DOMException, ex: if prefix != 'xml': raise SchemaError, '%s namespace not declared for %s'\ %(prefix, self.__node._get_tagName()) namespace = XMLNS.XML return namespace def loadDocument(self, file): self.__node = DOM.loadDocument(file) if hasattr(self.__node, 'documentElement'): self.__node = self.__node.documentElement def loadFromURL(self, url): self.__node = DOM.loadFromURL(url) if hasattr(self.__node, 'documentElement'): self.__node = self.__node.documentElement class XMLBase: """ These class variables are for string indentation. """ tag = None __indent = 0 __rlock = RLock() def __str__(self): XMLBase.__rlock.acquire() XMLBase.__indent += 1 tmp = "<" + str(self.__class__) + '>\n' for k,v in self.__dict__.items(): tmp += "%s* %s = %s\n" %(XMLBase.__indent*' ', k, v) XMLBase.__indent -= 1 XMLBase.__rlock.release() return tmp """Marker Interface: can determine something about an instances properties by using the provided convenience functions. """ class DefinitionMarker: """marker for definitions """ pass class DeclarationMarker: """marker for declarations """ pass class AttributeMarker: """marker for attributes """ pass class AttributeGroupMarker: """marker for attribute groups """ pass class WildCardMarker: """marker for wildcards """ pass class ElementMarker: """marker for wildcards """ pass class ReferenceMarker: """marker for references """ pass class ModelGroupMarker: """marker for model groups """ pass class AllMarker(ModelGroupMarker): """marker for all model group """ pass class ChoiceMarker(ModelGroupMarker): """marker for choice model group """ pass class SequenceMarker(ModelGroupMarker): """marker for sequence model group """ pass class ExtensionMarker: """marker for extensions """ pass class RestrictionMarker: """marker for restrictions """ facets = ['enumeration', 'length', 'maxExclusive', 'maxInclusive',\ 'maxLength', 'minExclusive', 'minInclusive', 'minLength',\ 'pattern', 'fractionDigits', 'totalDigits', 'whiteSpace'] class SimpleMarker: """marker for simple type information """ pass class ListMarker: """marker for simple type list """ pass class UnionMarker: """marker for simple type Union """ pass class ComplexMarker: """marker for complex type information """ pass class LocalMarker: """marker for complex type information """ pass class MarkerInterface: def isDefinition(self): return isinstance(self, DefinitionMarker) def isDeclaration(self): return isinstance(self, DeclarationMarker) def isAttribute(self): return isinstance(self, AttributeMarker) def isAttributeGroup(self): return isinstance(self, AttributeGroupMarker) def isElement(self): return isinstance(self, ElementMarker) def isReference(self): return isinstance(self, ReferenceMarker) def isWildCard(self): return isinstance(self, WildCardMarker) def isModelGroup(self): return isinstance(self, ModelGroupMarker) def isAll(self): return isinstance(self, AllMarker) def isChoice(self): return isinstance(self, ChoiceMarker) def isSequence(self): return isinstance(self, SequenceMarker) def isExtension(self): return isinstance(self, ExtensionMarker) def isRestriction(self): return isinstance(self, RestrictionMarker) def isSimple(self): return isinstance(self, SimpleMarker) def isComplex(self): return isinstance(self, ComplexMarker) def isLocal(self): return isinstance(self, LocalMarker) def isList(self): return isinstance(self, ListMarker) def isUnion(self): return isinstance(self, UnionMarker) ########################################################## # Schema Components ######################################################### class XMLSchemaComponent(XMLBase, MarkerInterface): """ class variables: required -- list of required attributes attributes -- dict of default attribute values, including None. Value can be a function for runtime dependencies. contents -- dict of namespace keyed content lists. 'xsd' content of xsd namespace. xmlns_key -- key for declared xmlns namespace. xmlns -- xmlns is special prefix for namespace dictionary xml -- special xml prefix for xml namespace. """ required = [] attributes = {} contents = {} xmlns_key = '' xmlns = 'xmlns' xml = 'xml' def __init__(self, parent=None): """parent -- parent instance instance variables: attributes -- dictionary of node's attributes """ self.attributes = None self._parent = parent if self._parent: self._parent = weakref.ref(parent) if not self.__class__ == XMLSchemaComponent\ and not (type(self.__class__.required) == type(XMLSchemaComponent.required)\ and type(self.__class__.attributes) == type(XMLSchemaComponent.attributes)\ and type(self.__class__.contents) == type(XMLSchemaComponent.contents)): raise RuntimeError, 'Bad type for a class variable in %s' %self.__class__ def getItemTrace(self): """Returns a node trace up to the item. """ item, path, name, ref = self, [], 'name', 'ref' while not isinstance(item,XMLSchema) and not isinstance(item,WSDLToolsAdapter): attr = item.getAttribute(name) if not attr: attr = item.getAttribute(ref) if not attr: path.append('<%s>' %(item.tag)) else: path.append('<%s ref="%s">' %(item.tag, attr)) else: path.append('<%s name="%s">' %(item.tag,attr)) item = item._parent() try: tns = item.getTargetNamespace() except: tns = '' path.append('<%s targetNamespace="%s">' %(item.tag, tns)) path.reverse() return ''.join(path) def getTargetNamespace(self): """return targetNamespace """ parent = self targetNamespace = 'targetNamespace' tns = self.attributes.get(targetNamespace) while not tns and parent and parent._parent is not None: parent = parent._parent() tns = parent.attributes.get(targetNamespace) return tns or '' def getAttributeDeclaration(self, attribute): """attribute -- attribute with a QName value (eg. type). collection -- check types collection in parent Schema instance """ return self.getQNameAttribute(ATTRIBUTES, attribute) def getAttributeGroup(self, attribute): """attribute -- attribute with a QName value (eg. type). collection -- check types collection in parent Schema instance """ return self.getQNameAttribute(ATTRIBUTE_GROUPS, attribute) def getTypeDefinition(self, attribute): """attribute -- attribute with a QName value (eg. type). collection -- check types collection in parent Schema instance """ return self.getQNameAttribute(TYPES, attribute) def getElementDeclaration(self, attribute): """attribute -- attribute with a QName value (eg. element). collection -- check elements collection in parent Schema instance. """ return self.getQNameAttribute(ELEMENTS, attribute) def getModelGroup(self, attribute): """attribute -- attribute with a QName value (eg. ref). collection -- check model_group collection in parent Schema instance. """ return self.getQNameAttribute(MODEL_GROUPS, attribute) def getQNameAttribute(self, collection, attribute): """returns object instance representing QName --> (namespace,name), or if does not exist return None. attribute -- an information item attribute, with a QName value. collection -- collection in parent Schema instance to search. """ tdc = self.getAttributeQName(attribute) if not tdc: return obj = self.getSchemaItem(collection, tdc.getTargetNamespace(), tdc.getName()) if obj: return obj # raise SchemaError, 'No schema item "%s" in collection %s' %(tdc, collection) return def getSchemaItem(self, collection, namespace, name): """returns object instance representing namespace, name, or if does not exist return None if built-in, else raise SchemaError. namespace -- namespace item defined in. name -- name of item. collection -- collection in parent Schema instance to search. """ parent = GetSchema(self) if parent.targetNamespace == namespace: try: obj = getattr(parent, collection)[name] except KeyError, ex: raise KeyError, 'targetNamespace(%s) collection(%s) has no item(%s)'\ %(namespace, collection, name) return obj if not parent.imports.has_key(namespace): if namespace in BUILT_IN_NAMESPACES: # built-in just return # WARNING: expecting import if "redefine" or add to built-in namespace. return raise SchemaError, 'schema "%s" does not import namespace "%s"' %( parent.targetNamespace, namespace) # Lazy Eval schema = parent.imports[namespace] if not isinstance(schema, XMLSchema): schema = schema.getSchema() if schema is not None: parent.imports[namespace] = schema if schema is None: if namespace in BUILT_IN_NAMESPACES: # built-in just return return raise SchemaError, 'no schema instance for imported namespace (%s).'\ %(namespace) if not isinstance(schema, XMLSchema): raise TypeError, 'expecting XMLSchema instance not "%r"' %schema try: obj = getattr(schema, collection)[name] except KeyError, ex: raise KeyError, 'targetNamespace(%s) collection(%s) has no item(%s)'\ %(namespace, collection, name) return obj def getXMLNS(self, prefix=None): """deference prefix or by default xmlns, returns namespace. """ if prefix == XMLSchemaComponent.xml: return XMLNS.XML parent = self ns = self.attributes[XMLSchemaComponent.xmlns].get(prefix or\ XMLSchemaComponent.xmlns_key) while not ns: parent = parent._parent() ns = parent.attributes[XMLSchemaComponent.xmlns].get(prefix or\ XMLSchemaComponent.xmlns_key) if not ns and isinstance(parent, WSDLToolsAdapter): if prefix is None: return '' raise SchemaError, 'unknown prefix %s' %prefix return ns def getAttribute(self, attribute): """return requested attribute value or None """ if type(attribute) in (list, tuple): if len(attribute) != 2: raise LookupError, 'To access attributes must use name or (namespace,name)' ns_dict = self.attributes.get(attribute[0]) if ns_dict is None: return None return ns_dict.get(attribute[1]) return self.attributes.get(attribute) def getAttributeQName(self, attribute): """return requested attribute value as (namespace,name) or None """ qname = self.getAttribute(attribute) if isinstance(qname, TypeDescriptionComponent) is True: return qname if qname is None: return None prefix,ncname = SplitQName(qname) namespace = self.getXMLNS(prefix) return TypeDescriptionComponent((namespace,ncname)) def getAttributeName(self): """return attribute name or None """ return self.getAttribute('name') def setAttributes(self, node): """Sets up attribute dictionary, checks for required attributes and sets default attribute values. attr is for default attribute values determined at runtime. structure of attributes dictionary ['xmlns'][xmlns_key] -- xmlns namespace ['xmlns'][prefix] -- declared namespace prefix [namespace][prefix] -- attributes declared in a namespace [attribute] -- attributes w/o prefix, default namespaces do not directly apply to attributes, ie Name can't collide with QName. """ self.attributes = {XMLSchemaComponent.xmlns:{}} for k,v in node.getAttributeDictionary().items(): prefix,value = SplitQName(k) if value == XMLSchemaComponent.xmlns: self.attributes[value][prefix or XMLSchemaComponent.xmlns_key] = v elif prefix: ns = node.getNamespace(prefix) if not ns: raise SchemaError, 'no namespace for attribute prefix %s'\ %prefix if not self.attributes.has_key(ns): self.attributes[ns] = {} elif self.attributes[ns].has_key(value): raise SchemaError, 'attribute %s declared multiple times in %s'\ %(value, ns) self.attributes[ns][value] = v elif not self.attributes.has_key(value): self.attributes[value] = v else: raise SchemaError, 'attribute %s declared multiple times' %value if not isinstance(self, WSDLToolsAdapter): self.__checkAttributes() self.__setAttributeDefaults() #set QNames for k in ['type', 'element', 'base', 'ref', 'substitutionGroup', 'itemType']: if self.attributes.has_key(k): prefix, value = SplitQName(self.attributes.get(k)) self.attributes[k] = \ TypeDescriptionComponent((self.getXMLNS(prefix), value)) #Union, memberTypes is a whitespace separated list of QNames for k in ['memberTypes']: if self.attributes.has_key(k): qnames = self.attributes[k] self.attributes[k] = [] for qname in qnames.split(): prefix, value = SplitQName(qname) self.attributes['memberTypes'].append(\ TypeDescriptionComponent(\ (self.getXMLNS(prefix), value))) def getContents(self, node): """retrieve xsd contents """ return node.getContentList(*self.__class__.contents['xsd']) def __setAttributeDefaults(self): """Looks for default values for unset attributes. If class variable representing attribute is None, then it must be defined as an instance variable. """ for k,v in self.__class__.attributes.items(): if v is not None and self.attributes.has_key(k) is False: if isinstance(v, types.FunctionType): self.attributes[k] = v(self) else: self.attributes[k] = v def __checkAttributes(self): """Checks that required attributes have been defined, attributes w/default cannot be required. Checks all defined attributes are legal, attribute references are not subject to this test. """ for a in self.__class__.required: if not self.attributes.has_key(a): raise SchemaError,\ 'class instance %s, missing required attribute %s'\ %(self.__class__, a) for a,v in self.attributes.items(): # attribute #other, ie. not in empty namespace if type(v) is dict: continue # predefined prefixes xmlns, xml if a in (XMLSchemaComponent.xmlns, XMLNS.XML): continue if (a not in self.__class__.attributes.keys()) and not\ (self.isAttribute() and self.isReference()): raise SchemaError, '%s, unknown attribute(%s,%s)' \ %(self.getItemTrace(), a, self.attributes[a]) class WSDLToolsAdapter(XMLSchemaComponent): """WSDL Adapter to grab the attributes from the wsdl document node. """ attributes = {'name':None, 'targetNamespace':None} tag = 'definitions' def __init__(self, wsdl): XMLSchemaComponent.__init__(self, parent=wsdl) self.setAttributes(DOMAdapter(wsdl.document)) def getImportSchemas(self): """returns WSDLTools.WSDL types Collection """ return self._parent().types class Notation(XMLSchemaComponent): """ parent: schema attributes: id -- ID name -- NCName, Required public -- token, Required system -- anyURI contents: annotation? """ required = ['name', 'public'] attributes = {'id':None, 'name':None, 'public':None, 'system':None} contents = {'xsd':('annotation')} tag = 'notation' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class Annotation(XMLSchemaComponent): """ parent: all,any,anyAttribute,attribute,attributeGroup,choice,complexContent, complexType,element,extension,field,group,import,include,key,keyref, list,notation,redefine,restriction,schema,selector,simpleContent, simpleType,union,unique attributes: id -- ID contents: (documentation | appinfo)* """ attributes = {'id':None} contents = {'xsd':('documentation', 'appinfo')} tag = 'annotation' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for i in contents: component = SplitQName(i.getTagName())[1] if component == 'documentation': #print_debug('class %s, documentation skipped' %self.__class__, 5) continue elif component == 'appinfo': #print_debug('class %s, appinfo skipped' %self.__class__, 5) continue else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class Documentation(XMLSchemaComponent): """ parent: annotation attributes: source, anyURI xml:lang, language contents: mixed, any """ attributes = {'source':None, 'xml:lang':None} contents = {'xsd':('mixed', 'any')} tag = 'documentation' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for i in contents: component = SplitQName(i.getTagName())[1] if component == 'mixed': #print_debug('class %s, mixed skipped' %self.__class__, 5) continue elif component == 'any': #print_debug('class %s, any skipped' %self.__class__, 5) continue else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class Appinfo(XMLSchemaComponent): """ parent: annotation attributes: source, anyURI contents: mixed, any """ attributes = {'source':None, 'anyURI':None} contents = {'xsd':('mixed', 'any')} tag = 'appinfo' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for i in contents: component = SplitQName(i.getTagName())[1] if component == 'mixed': #print_debug('class %s, mixed skipped' %self.__class__, 5) continue elif component == 'any': #print_debug('class %s, any skipped' %self.__class__, 5) continue else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class XMLSchemaFake: # This is temporary, for the benefit of WSDL until the real thing works. def __init__(self, element): self.targetNamespace = DOM.getAttr(element, 'targetNamespace') self.element = element class XMLSchema(XMLSchemaComponent): """A schema is a collection of schema components derived from one or more schema documents, that is, one or more element information items. It represents the abstract notion of a schema rather than a single schema document (or other representation). parent: ROOT attributes: id -- ID version -- token xml:lang -- language targetNamespace -- anyURI attributeFormDefault -- 'qualified' | 'unqualified', 'unqualified' elementFormDefault -- 'qualified' | 'unqualified', 'unqualified' blockDefault -- '#all' | list of ('substitution | 'extension' | 'restriction') finalDefault -- '#all' | list of ('extension' | 'restriction' | 'list' | 'union') contents: ((include | import | redefine | annotation)*, (attribute, attributeGroup, complexType, element, group, notation, simpleType)*, annotation*)* attributes -- schema attributes imports -- import statements includes -- include statements redefines -- types -- global simpleType, complexType definitions elements -- global element declarations attr_decl -- global attribute declarations attr_groups -- attribute Groups model_groups -- model Groups notations -- global notations """ attributes = {'id':None, 'version':None, 'xml:lang':None, 'targetNamespace':None, 'attributeFormDefault':'unqualified', 'elementFormDefault':'unqualified', 'blockDefault':None, 'finalDefault':None} contents = {'xsd':('include', 'import', 'redefine', 'annotation', 'attribute', 'attributeGroup', 'complexType', 'element', 'group', 'notation', 'simpleType', 'annotation')} empty_namespace = '' tag = 'schema' def __init__(self, parent=None): """parent -- instance variables: targetNamespace -- schema's declared targetNamespace, or empty string. _imported_schemas -- namespace keyed dict of schema dependencies, if a schema is provided instance will not resolve import statement. _included_schemas -- schemaLocation keyed dict of component schemas, if schema is provided instance will not resolve include statement. _base_url -- needed for relative URLs support, only works with URLs relative to initial document. includes -- collection of include statements imports -- collection of import statements elements -- collection of global element declarations types -- collection of global type definitions attr_decl -- collection of global attribute declarations attr_groups -- collection of global attribute group definitions model_groups -- collection of model group definitions notations -- collection of notations """ self.__node = None self.targetNamespace = None XMLSchemaComponent.__init__(self, parent) f = lambda k: k.attributes['name'] ns = lambda k: k.attributes['namespace'] sl = lambda k: k.attributes['schemaLocation'] self.includes = Collection(self, key=sl) self.imports = Collection(self, key=ns) self.elements = Collection(self, key=f) self.types = Collection(self, key=f) self.attr_decl = Collection(self, key=f) self.attr_groups = Collection(self, key=f) self.model_groups = Collection(self, key=f) self.notations = Collection(self, key=f) self._imported_schemas = {} self._included_schemas = {} self._base_url = None def getNode(self): """ Interacting with the underlying DOM tree. """ return self.__node def addImportSchema(self, schema): """for resolving import statements in Schema instance schema -- schema instance _imported_schemas """ if not isinstance(schema, XMLSchema): raise TypeError, 'expecting a Schema instance' if schema.targetNamespace != self.targetNamespace: self._imported_schemas[schema.targetNamespace] = schema else: raise SchemaError, 'import schema bad targetNamespace' def addIncludeSchema(self, schemaLocation, schema): """for resolving include statements in Schema instance schemaLocation -- schema location schema -- schema instance _included_schemas """ if not isinstance(schema, XMLSchema): raise TypeError, 'expecting a Schema instance' if not schema.targetNamespace or\ schema.targetNamespace == self.targetNamespace: self._included_schemas[schemaLocation] = schema else: raise SchemaError, 'include schema bad targetNamespace' def setImportSchemas(self, schema_dict): """set the import schema dictionary, which is used to reference depedent schemas. """ self._imported_schemas = schema_dict def getImportSchemas(self): """get the import schema dictionary, which is used to reference depedent schemas. """ return self._imported_schemas def getSchemaNamespacesToImport(self): """returns tuple of namespaces the schema instance has declared itself to be depedent upon. """ return tuple(self.includes.keys()) def setIncludeSchemas(self, schema_dict): """set the include schema dictionary, which is keyed with schemaLocation (uri). This is a means of providing schemas to the current schema for content inclusion. """ self._included_schemas = schema_dict def getIncludeSchemas(self): """get the include schema dictionary, which is keyed with schemaLocation (uri). """ return self._included_schemas def getBaseUrl(self): """get base url, used for normalizing all relative uri's """ return self._base_url def setBaseUrl(self, url): """set base url, used for normalizing all relative uri's """ self._base_url = url def getElementFormDefault(self): """return elementFormDefault attribute """ return self.attributes.get('elementFormDefault') def isElementFormDefaultQualified(self): return self.attributes.get('elementFormDefault') == 'qualified' def getAttributeFormDefault(self): """return attributeFormDefault attribute """ return self.attributes.get('attributeFormDefault') def getBlockDefault(self): """return blockDefault attribute """ return self.attributes.get('blockDefault') def getFinalDefault(self): """return finalDefault attribute """ return self.attributes.get('finalDefault') def load(self, node, location=None): self.__node = node pnode = node.getParentNode() if pnode: pname = SplitQName(pnode.getTagName())[1] if pname == 'types': attributes = {} self.setAttributes(pnode) attributes.update(self.attributes) self.setAttributes(node) for k,v in attributes['xmlns'].items(): if not self.attributes['xmlns'].has_key(k): self.attributes['xmlns'][k] = v else: self.setAttributes(node) else: self.setAttributes(node) self.targetNamespace = self.getTargetNamespace() for childNode in self.getContents(node): component = SplitQName(childNode.getTagName())[1] if component == 'include': tp = self.__class__.Include(self) tp.fromDom(childNode) sl = tp.attributes['schemaLocation'] schema = tp.getSchema() if not self.getIncludeSchemas().has_key(sl): self.addIncludeSchema(sl, schema) self.includes[sl] = tp pn = childNode.getParentNode().getNode() pn.removeChild(childNode.getNode()) for child in schema.getNode().getNode().childNodes: pn.appendChild(child.cloneNode(1)) for collection in ['imports','elements','types', 'attr_decl','attr_groups','model_groups', 'notations']: for k,v in getattr(schema,collection).items(): if not getattr(self,collection).has_key(k): v._parent = weakref.ref(self) getattr(self,collection)[k] = v else: warnings.warn("Not keeping schema component.") elif component == 'import': slocd = SchemaReader.namespaceToSchema tp = self.__class__.Import(self) tp.fromDom(childNode) import_ns = tp.getAttribute('namespace') or\ self.__class__.empty_namespace schema = slocd.get(import_ns) if schema is None: schema = XMLSchema() slocd[import_ns] = schema try: tp.loadSchema(schema) except NoSchemaLocationWarning, ex: # Dependency declaration, hopefully implementation # is aware of this namespace (eg. SOAP,WSDL,?) del slocd[import_ns] continue except SchemaError, ex: warnings.warn(\ ', %s'\ %(import_ns, 'failed to load schema instance, resort to lazy eval when necessary') ) del slocd[import_ns] class _LazyEvalImport(str): '''Lazy evaluation of import, replace entry in self.imports.''' #attributes = dict(namespace=import_ns) def getSchema(namespace): schema = slocd.get(namespace) if schema is None: parent = self._parent() wstypes = parent if isinstance(parent, WSDLToolsAdapter): wstypes = parent.getImportSchemas() schema = wstypes.get(namespace) if isinstance(schema, XMLSchema): self.imports[namespace] = schema return schema return None self.imports[import_ns] = _LazyEvalImport(import_ns) continue else: tp._schema = schema if self.getImportSchemas().has_key(import_ns): warnings.warn(\ 'Detected multiple imports of the namespace "%s" '\ %import_ns) self.addImportSchema(schema) # spec says can have multiple imports of same namespace # but purpose of import is just dependency declaration. self.imports[import_ns] = tp elif component == 'redefine': warnings.warn('redefine is ignored') elif component == 'annotation': warnings.warn('annotation is ignored') elif component == 'attribute': tp = AttributeDeclaration(self) tp.fromDom(childNode) self.attr_decl[tp.getAttribute('name')] = tp elif component == 'attributeGroup': tp = AttributeGroupDefinition(self) tp.fromDom(childNode) self.attr_groups[tp.getAttribute('name')] = tp elif component == 'element': tp = ElementDeclaration(self) tp.fromDom(childNode) self.elements[tp.getAttribute('name')] = tp elif component == 'group': tp = ModelGroupDefinition(self) tp.fromDom(childNode) self.model_groups[tp.getAttribute('name')] = tp elif component == 'notation': tp = Notation(self) tp.fromDom(childNode) self.notations[tp.getAttribute('name')] = tp elif component == 'complexType': tp = ComplexType(self) tp.fromDom(childNode) self.types[tp.getAttribute('name')] = tp elif component == 'simpleType': tp = SimpleType(self) tp.fromDom(childNode) self.types[tp.getAttribute('name')] = tp else: break class Import(XMLSchemaComponent): """ parent: schema attributes: id -- ID namespace -- anyURI schemaLocation -- anyURI contents: annotation? """ attributes = {'id':None, 'namespace':None, 'schemaLocation':None} contents = {'xsd':['annotation']} tag = 'import' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self._schema = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) if self.attributes['namespace'] == self.getTargetNamespace(): raise SchemaError, 'namespace of schema and import match' for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) def getSchema(self): """if schema is not defined, first look for a Schema class instance in parent Schema. Else if not defined resolve schemaLocation and create a new Schema class instance, and keep a hard reference. """ if not self._schema: ns = self.attributes['namespace'] schema = self._parent().getImportSchemas().get(ns) if not schema and self._parent()._parent: schema = self._parent()._parent().getImportSchemas().get(ns) if not schema: url = self.attributes.get('schemaLocation') if not url: raise SchemaError, 'namespace(%s) is unknown' %ns base_url = self._parent().getBaseUrl() reader = SchemaReader(base_url=base_url) reader._imports = self._parent().getImportSchemas() reader._includes = self._parent().getIncludeSchemas() self._schema = reader.loadFromURL(url) return self._schema or schema def loadSchema(self, schema): """ """ base_url = self._parent().getBaseUrl() reader = SchemaReader(base_url=base_url) reader._imports = self._parent().getImportSchemas() reader._includes = self._parent().getIncludeSchemas() self._schema = schema if not self.attributes.has_key('schemaLocation'): raise NoSchemaLocationWarning('no schemaLocation attribute in import') reader.loadFromURL(self.attributes.get('schemaLocation'), schema) class Include(XMLSchemaComponent): """ parent: schema attributes: id -- ID schemaLocation -- anyURI, required contents: annotation? """ required = ['schemaLocation'] attributes = {'id':None, 'schemaLocation':None} contents = {'xsd':['annotation']} tag = 'include' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self._schema = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) def getSchema(self): """if schema is not defined, first look for a Schema class instance in parent Schema. Else if not defined resolve schemaLocation and create a new Schema class instance. """ if not self._schema: schema = self._parent() self._schema = schema.getIncludeSchemas().get(\ self.attributes['schemaLocation'] ) if not self._schema: url = self.attributes['schemaLocation'] reader = SchemaReader(base_url=schema.getBaseUrl()) reader._imports = schema.getImportSchemas() reader._includes = schema.getIncludeSchemas() # create schema before loading so chameleon include # will evalute targetNamespace correctly. self._schema = XMLSchema(schema) reader.loadFromURL(url, self._schema) return self._schema class AttributeDeclaration(XMLSchemaComponent,\ AttributeMarker,\ DeclarationMarker): """ parent: schema attributes: id -- ID name -- NCName, required type -- QName default -- string fixed -- string contents: annotation?, simpleType? """ required = ['name'] attributes = {'id':None, 'name':None, 'type':None, 'default':None, 'fixed':None} contents = {'xsd':['annotation','simpleType']} tag = 'attribute' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): """ No list or union support """ self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) elif component == 'simpleType': self.content = AnonymousSimpleType(self) self.content.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class LocalAttributeDeclaration(AttributeDeclaration,\ AttributeMarker,\ LocalMarker,\ DeclarationMarker): """ parent: complexType, restriction, extension, attributeGroup attributes: id -- ID name -- NCName, required type -- QName form -- ('qualified' | 'unqualified'), schema.attributeFormDefault use -- ('optional' | 'prohibited' | 'required'), optional default -- string fixed -- string contents: annotation?, simpleType? """ required = ['name'] attributes = {'id':None, 'name':None, 'type':None, 'form':lambda self: GetSchema(self).getAttributeFormDefault(), 'use':'optional', 'default':None, 'fixed':None} contents = {'xsd':['annotation','simpleType']} def __init__(self, parent): AttributeDeclaration.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) elif component == 'simpleType': self.content = AnonymousSimpleType(self) self.content.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class AttributeWildCard(XMLSchemaComponent,\ AttributeMarker,\ DeclarationMarker,\ WildCardMarker): """ parents: complexType, restriction, extension, attributeGroup attributes: id -- ID namespace -- '##any' | '##other' | (anyURI* | '##targetNamespace' | '##local'), ##any processContents -- 'lax' | 'skip' | 'strict', strict contents: annotation? """ attributes = {'id':None, 'namespace':'##any', 'processContents':'strict'} contents = {'xsd':['annotation']} tag = 'anyAttribute' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class AttributeReference(XMLSchemaComponent,\ AttributeMarker,\ ReferenceMarker): """ parents: complexType, restriction, extension, attributeGroup attributes: id -- ID ref -- QName, required use -- ('optional' | 'prohibited' | 'required'), optional default -- string fixed -- string contents: annotation? """ required = ['ref'] attributes = {'id':None, 'ref':None, 'use':'optional', 'default':None, 'fixed':None} contents = {'xsd':['annotation']} tag = 'attribute' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def getAttributeDeclaration(self, attribute='ref'): return XMLSchemaComponent.getAttributeDeclaration(self, attribute) def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class AttributeGroupDefinition(XMLSchemaComponent,\ AttributeGroupMarker,\ DefinitionMarker): """ parents: schema, redefine attributes: id -- ID name -- NCName, required contents: annotation?, (attribute | attributeGroup)*, anyAttribute? """ required = ['name'] attributes = {'id':None, 'name':None} contents = {'xsd':['annotation', 'attribute', 'attributeGroup', 'anyAttribute']} tag = 'attributeGroup' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.attr_content = None def getAttributeContent(self): return self.attr_content def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for indx in range(len(contents)): component = SplitQName(contents[indx].getTagName())[1] if (component == 'annotation') and (not indx): self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) elif component == 'attribute': if contents[indx].hasattr('name'): content.append(LocalAttributeDeclaration(self)) elif contents[indx].hasattr('ref'): content.append(AttributeReference(self)) else: raise SchemaError, 'Unknown attribute type' content[-1].fromDom(contents[indx]) elif component == 'attributeGroup': content.append(AttributeGroupReference(self)) content[-1].fromDom(contents[indx]) elif component == 'anyAttribute': if len(contents) != indx+1: raise SchemaError, 'anyAttribute is out of order in %s' %self.getItemTrace() content.append(AttributeWildCard(self)) content[-1].fromDom(contents[indx]) else: raise SchemaError, 'Unknown component (%s)' %(contents[indx].getTagName()) self.attr_content = tuple(content) class AttributeGroupReference(XMLSchemaComponent,\ AttributeGroupMarker,\ ReferenceMarker): """ parents: complexType, restriction, extension, attributeGroup attributes: id -- ID ref -- QName, required contents: annotation? """ required = ['ref'] attributes = {'id':None, 'ref':None} contents = {'xsd':['annotation']} tag = 'attributeGroup' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def getAttributeGroup(self, attribute='ref'): """attribute -- attribute with a QName value (eg. type). collection -- check types collection in parent Schema instance """ return XMLSchemaComponent.getAttributeGroup(self, attribute) def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) ###################################################### # Elements ##################################################### class IdentityConstrants(XMLSchemaComponent): """Allow one to uniquely identify nodes in a document and ensure the integrity of references between them. attributes -- dictionary of attributes selector -- XPath to selected nodes fields -- list of XPath to key field """ def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.selector = None self.fields = None self.annotation = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) fields = [] for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) elif component == 'selector': self.selector = self.Selector(self) self.selector.fromDom(i) continue elif component == 'field': fields.append(self.Field(self)) fields[-1].fromDom(i) continue else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.fields = tuple(fields) class Constraint(XMLSchemaComponent): def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class Selector(Constraint): """ parent: unique, key, keyref attributes: id -- ID xpath -- XPath subset, required contents: annotation? """ required = ['xpath'] attributes = {'id':None, 'xpath':None} contents = {'xsd':['annotation']} tag = 'selector' class Field(Constraint): """ parent: unique, key, keyref attributes: id -- ID xpath -- XPath subset, required contents: annotation? """ required = ['xpath'] attributes = {'id':None, 'xpath':None} contents = {'xsd':['annotation']} tag = 'field' class Unique(IdentityConstrants): """ Enforce fields are unique w/i a specified scope. parent: element attributes: id -- ID name -- NCName, required contents: annotation?, selector, field+ """ required = ['name'] attributes = {'id':None, 'name':None} contents = {'xsd':['annotation', 'selector', 'field']} tag = 'unique' class Key(IdentityConstrants): """ Enforce fields are unique w/i a specified scope, and all field values are present w/i document. Fields cannot be nillable. parent: element attributes: id -- ID name -- NCName, required contents: annotation?, selector, field+ """ required = ['name'] attributes = {'id':None, 'name':None} contents = {'xsd':['annotation', 'selector', 'field']} tag = 'key' class KeyRef(IdentityConstrants): """ Ensure a match between two sets of values in an instance. parent: element attributes: id -- ID name -- NCName, required refer -- QName, required contents: annotation?, selector, field+ """ required = ['name', 'refer'] attributes = {'id':None, 'name':None, 'refer':None} contents = {'xsd':['annotation', 'selector', 'field']} tag = 'keyref' class ElementDeclaration(XMLSchemaComponent,\ ElementMarker,\ DeclarationMarker): """ parents: schema attributes: id -- ID name -- NCName, required type -- QName default -- string fixed -- string nillable -- boolean, false abstract -- boolean, false substitutionGroup -- QName block -- ('#all' | ('substition' | 'extension' | 'restriction')*), schema.blockDefault final -- ('#all' | ('extension' | 'restriction')*), schema.finalDefault contents: annotation?, (simpleType,complexType)?, (key | keyref | unique)* """ required = ['name'] attributes = {'id':None, 'name':None, 'type':None, 'default':None, 'fixed':None, 'nillable':0, 'abstract':0, 'substitutionGroup':None, 'block':lambda self: self._parent().getBlockDefault(), 'final':lambda self: self._parent().getFinalDefault()} contents = {'xsd':['annotation', 'simpleType', 'complexType', 'key',\ 'keyref', 'unique']} tag = 'element' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None self.constraints = () def isQualified(self): """Global elements are always qualified. """ return True def getAttribute(self, attribute): """return attribute. If attribute is type and it's None, and no simple or complex content, return the default type "xsd:anyType" """ value = XMLSchemaComponent.getAttribute(self, attribute) if attribute != 'type' or value is not None: return value if self.content is not None: return None parent = self while 1: nsdict = parent.attributes[XMLSchemaComponent.xmlns] for k,v in nsdict.items(): if v not in SCHEMA.XSD_LIST: continue return TypeDescriptionComponent((v, 'anyType')) if isinstance(parent, WSDLToolsAdapter)\ or not hasattr(parent, '_parent'): break parent = parent._parent() raise SchemaError, 'failed to locate the XSD namespace' def getElementDeclaration(self, attribute): raise Warning, 'invalid operation for <%s>' %self.tag def getTypeDefinition(self, attribute=None): """If attribute is None, "type" is assumed, return the corresponding representation of the global type definition (TypeDefinition), or the local definition if don't find "type". To maintain backwards compat, if attribute is provided call base class method. """ if attribute: return XMLSchemaComponent.getTypeDefinition(self, attribute) gt = XMLSchemaComponent.getTypeDefinition(self, 'type') if gt: return gt return self.content def getConstraints(self): return self._constraints def setConstraints(self, constraints): self._constraints = tuple(constraints) constraints = property(getConstraints, setConstraints, None, "tuple of key, keyref, unique constraints") def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) constraints = [] for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) elif component == 'simpleType' and not self.content: self.content = AnonymousSimpleType(self) self.content.fromDom(i) elif component == 'complexType' and not self.content: self.content = LocalComplexType(self) self.content.fromDom(i) elif component == 'key': constraints.append(Key(self)) constraints[-1].fromDom(i) elif component == 'keyref': constraints.append(KeyRef(self)) constraints[-1].fromDom(i) elif component == 'unique': constraints.append(Unique(self)) constraints[-1].fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.constraints = constraints class LocalElementDeclaration(ElementDeclaration,\ LocalMarker): """ parents: all, choice, sequence attributes: id -- ID name -- NCName, required form -- ('qualified' | 'unqualified'), schema.elementFormDefault type -- QName minOccurs -- Whole Number, 1 maxOccurs -- (Whole Number | 'unbounded'), 1 default -- string fixed -- string nillable -- boolean, false block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault contents: annotation?, (simpleType,complexType)?, (key | keyref | unique)* """ required = ['name'] attributes = {'id':None, 'name':None, 'form':lambda self: GetSchema(self).getElementFormDefault(), 'type':None, 'minOccurs':'1', 'maxOccurs':'1', 'default':None, 'fixed':None, 'nillable':0, 'abstract':0, 'block':lambda self: GetSchema(self).getBlockDefault()} contents = {'xsd':['annotation', 'simpleType', 'complexType', 'key',\ 'keyref', 'unique']} def isQualified(self): """ Local elements can be qualified or unqualifed according to the attribute form, or the elementFormDefault. By default local elements are unqualified. """ form = self.getAttribute('form') if form == 'qualified': return True if form == 'unqualified': return False raise SchemaError, 'Bad form (%s) for element: %s' %(form, self.getItemTrace()) class ElementReference(XMLSchemaComponent,\ ElementMarker,\ ReferenceMarker): """ parents: all, choice, sequence attributes: id -- ID ref -- QName, required minOccurs -- Whole Number, 1 maxOccurs -- (Whole Number | 'unbounded'), 1 contents: annotation? """ required = ['ref'] attributes = {'id':None, 'ref':None, 'minOccurs':'1', 'maxOccurs':'1'} contents = {'xsd':['annotation']} tag = 'element' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def getElementDeclaration(self, attribute=None): """If attribute is None, "ref" is assumed, return the corresponding representation of the global element declaration (ElementDeclaration), To maintain backwards compat, if attribute is provided call base class method. """ if attribute: return XMLSchemaComponent.getElementDeclaration(self, attribute) return XMLSchemaComponent.getElementDeclaration(self, 'ref') def fromDom(self, node): self.annotation = None self.setAttributes(node) for i in self.getContents(node): component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class ElementWildCard(LocalElementDeclaration, WildCardMarker): """ parents: choice, sequence attributes: id -- ID minOccurs -- Whole Number, 1 maxOccurs -- (Whole Number | 'unbounded'), 1 namespace -- '##any' | '##other' | (anyURI* | '##targetNamespace' | '##local'), ##any processContents -- 'lax' | 'skip' | 'strict', strict contents: annotation? """ required = [] attributes = {'id':None, 'minOccurs':'1', 'maxOccurs':'1', 'namespace':'##any', 'processContents':'strict'} contents = {'xsd':['annotation']} tag = 'any' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def isQualified(self): """ Global elements are always qualified, but if processContents are not strict could have dynamically generated local elements. """ return GetSchema(self).isElementFormDefaultQualified() def getAttribute(self, attribute): """return attribute. """ return XMLSchemaComponent.getAttribute(self, attribute) def getTypeDefinition(self, attribute): raise Warning, 'invalid operation for <%s>' % self.tag def fromDom(self, node): self.annotation = None self.setAttributes(node) for i in self.getContents(node): component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) ###################################################### # Model Groups ##################################################### class Sequence(XMLSchemaComponent,\ SequenceMarker): """ parents: complexType, extension, restriction, group, choice, sequence attributes: id -- ID minOccurs -- Whole Number, 1 maxOccurs -- (Whole Number | 'unbounded'), 1 contents: annotation?, (element | group | choice | sequence | any)* """ attributes = {'id':None, 'minOccurs':'1', 'maxOccurs':'1'} contents = {'xsd':['annotation', 'element', 'group', 'choice', 'sequence',\ 'any']} tag = 'sequence' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) continue elif component == 'element': if i.hasattr('ref'): content.append(ElementReference(self)) else: content.append(LocalElementDeclaration(self)) elif component == 'group': content.append(ModelGroupReference(self)) elif component == 'choice': content.append(Choice(self)) elif component == 'sequence': content.append(Sequence(self)) elif component == 'any': content.append(ElementWildCard(self)) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) content[-1].fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class All(XMLSchemaComponent,\ AllMarker): """ parents: complexType, extension, restriction, group attributes: id -- ID minOccurs -- '0' | '1', 1 maxOccurs -- '1', 1 contents: annotation?, element* """ attributes = {'id':None, 'minOccurs':'1', 'maxOccurs':'1'} contents = {'xsd':['annotation', 'element']} tag = 'all' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) continue elif component == 'element': if i.hasattr('ref'): content.append(ElementReference(self)) else: content.append(LocalElementDeclaration(self)) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) content[-1].fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class Choice(XMLSchemaComponent,\ ChoiceMarker): """ parents: complexType, extension, restriction, group, choice, sequence attributes: id -- ID minOccurs -- Whole Number, 1 maxOccurs -- (Whole Number | 'unbounded'), 1 contents: annotation?, (element | group | choice | sequence | any)* """ attributes = {'id':None, 'minOccurs':'1', 'maxOccurs':'1'} contents = {'xsd':['annotation', 'element', 'group', 'choice', 'sequence',\ 'any']} tag = 'choice' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) continue elif component == 'element': if i.hasattr('ref'): content.append(ElementReference(self)) else: content.append(LocalElementDeclaration(self)) elif component == 'group': content.append(ModelGroupReference(self)) elif component == 'choice': content.append(Choice(self)) elif component == 'sequence': content.append(Sequence(self)) elif component == 'any': content.append(ElementWildCard(self)) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) content[-1].fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class ModelGroupDefinition(XMLSchemaComponent,\ ModelGroupMarker,\ DefinitionMarker): """ parents: redefine, schema attributes: id -- ID name -- NCName, required contents: annotation?, (all | choice | sequence)? """ required = ['name'] attributes = {'id':None, 'name':None} contents = {'xsd':['annotation', 'all', 'choice', 'sequence']} tag = 'group' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) continue elif component == 'all' and not self.content: self.content = All(self) elif component == 'choice' and not self.content: self.content = Choice(self) elif component == 'sequence' and not self.content: self.content = Sequence(self) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class ModelGroupReference(XMLSchemaComponent,\ ModelGroupMarker,\ ReferenceMarker): """ parents: choice, complexType, extension, restriction, sequence attributes: id -- ID ref -- NCName, required minOccurs -- Whole Number, 1 maxOccurs -- (Whole Number | 'unbounded'), 1 contents: annotation? """ required = ['ref'] attributes = {'id':None, 'ref':None, 'minOccurs':'1', 'maxOccurs':'1'} contents = {'xsd':['annotation']} tag = 'group' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None def getModelGroupReference(self): return self.getModelGroup('ref') def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class ComplexType(XMLSchemaComponent,\ DefinitionMarker,\ ComplexMarker): """ parents: redefine, schema attributes: id -- ID name -- NCName, required mixed -- boolean, false abstract -- boolean, false block -- ('#all' | ('extension' | 'restriction')*), schema.blockDefault final -- ('#all' | ('extension' | 'restriction')*), schema.finalDefault contents: annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?)) """ required = ['name'] attributes = {'id':None, 'name':None, 'mixed':0, 'abstract':0, 'block':lambda self: self._parent().getBlockDefault(), 'final':lambda self: self._parent().getFinalDefault()} contents = {'xsd':['annotation', 'simpleContent', 'complexContent',\ 'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',\ 'anyAttribute', 'any']} tag = 'complexType' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None self.attr_content = None def isMixed(self): m = self.getAttribute('mixed') if m == 0 or m == False: return False if isinstance(m, basestring) is True: if m in ('false', '0'): return False if m in ('true', '1'): return True raise SchemaError, 'invalid value for attribute mixed(%s): %s'\ %(m, self.getItemTrace()) def getAttributeContent(self): return self.attr_content def getElementDeclaration(self, attribute): raise Warning, 'invalid operation for <%s>' %self.tag def getTypeDefinition(self, attribute): raise Warning, 'invalid operation for <%s>' %self.tag def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) indx = 0 num = len(contents) if not num: return component = SplitQName(contents[indx].getTagName())[1] if component == 'annotation': self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) indx += 1 component = SplitQName(contents[indx].getTagName())[1] self.content = None if component == 'simpleContent': self.content = self.__class__.SimpleContent(self) self.content.fromDom(contents[indx]) elif component == 'complexContent': self.content = self.__class__.ComplexContent(self) self.content.fromDom(contents[indx]) else: if component == 'all': self.content = All(self) elif component == 'choice': self.content = Choice(self) elif component == 'sequence': self.content = Sequence(self) elif component == 'group': self.content = ModelGroupReference(self) if self.content: self.content.fromDom(contents[indx]) indx += 1 self.attr_content = [] while indx < num: component = SplitQName(contents[indx].getTagName())[1] if component == 'attribute': if contents[indx].hasattr('ref'): self.attr_content.append(AttributeReference(self)) else: self.attr_content.append(LocalAttributeDeclaration(self)) elif component == 'attributeGroup': self.attr_content.append(AttributeGroupReference(self)) elif component == 'anyAttribute': self.attr_content.append(AttributeWildCard(self)) else: raise SchemaError, 'Unknown component (%s): %s' \ %(contents[indx].getTagName(),self.getItemTrace()) self.attr_content[-1].fromDom(contents[indx]) indx += 1 class _DerivedType(XMLSchemaComponent): def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None # XXX remove attribute derivation, inconsistent self.derivation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for i in contents: component = SplitQName(i.getTagName())[1] if component in self.__class__.contents['xsd']: if component == 'annotation' and not self.annotation: self.annotation = Annotation(self) self.annotation.fromDom(i) continue elif component == 'restriction' and not self.derivation: self.derivation = self.__class__.Restriction(self) elif component == 'extension' and not self.derivation: self.derivation = self.__class__.Extension(self) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.derivation.fromDom(i) self.content = self.derivation class ComplexContent(_DerivedType,\ ComplexMarker): """ parents: complexType attributes: id -- ID mixed -- boolean, false contents: annotation?, (restriction | extension) """ attributes = {'id':None, 'mixed':0} contents = {'xsd':['annotation', 'restriction', 'extension']} tag = 'complexContent' def isMixed(self): m = self.getAttribute('mixed') if m == 0 or m == False: return False if isinstance(m, basestring) is True: if m in ('false', '0'): return False if m in ('true', '1'): return True raise SchemaError, 'invalid value for attribute mixed(%s): %s'\ %(m, self.getItemTrace()) class _DerivationBase(XMLSchemaComponent): """, parents: complexContent attributes: id -- ID base -- QName, required contents: annotation?, (group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute? """ required = ['base'] attributes = {'id':None, 'base':None } contents = {'xsd':['annotation', 'group', 'all', 'choice',\ 'sequence', 'attribute', 'attributeGroup', 'anyAttribute']} def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None self.attr_content = None def getAttributeContent(self): return self.attr_content def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) indx = 0 num = len(contents) #XXX ugly if not num: return component = SplitQName(contents[indx].getTagName())[1] if component == 'annotation': self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) indx += 1 component = SplitQName(contents[indx].getTagName())[1] if component == 'all': self.content = All(self) self.content.fromDom(contents[indx]) indx += 1 elif component == 'choice': self.content = Choice(self) self.content.fromDom(contents[indx]) indx += 1 elif component == 'sequence': self.content = Sequence(self) self.content.fromDom(contents[indx]) indx += 1 elif component == 'group': self.content = ModelGroupReference(self) self.content.fromDom(contents[indx]) indx += 1 else: self.content = None self.attr_content = [] while indx < num: component = SplitQName(contents[indx].getTagName())[1] if component == 'attribute': if contents[indx].hasattr('ref'): self.attr_content.append(AttributeReference(self)) else: self.attr_content.append(LocalAttributeDeclaration(self)) elif component == 'attributeGroup': if contents[indx].hasattr('ref'): self.attr_content.append(AttributeGroupReference(self)) else: self.attr_content.append(AttributeGroupDefinition(self)) elif component == 'anyAttribute': self.attr_content.append(AttributeWildCard(self)) else: raise SchemaError, 'Unknown component (%s)' %(contents[indx].getTagName()) self.attr_content[-1].fromDom(contents[indx]) indx += 1 class Extension(_DerivationBase, ExtensionMarker): """ parents: complexContent attributes: id -- ID base -- QName, required contents: annotation?, (group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute? """ tag = 'extension' class Restriction(_DerivationBase,\ RestrictionMarker): """ parents: complexContent attributes: id -- ID base -- QName, required contents: annotation?, (group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute? """ tag = 'restriction' class SimpleContent(_DerivedType,\ SimpleMarker): """ parents: complexType attributes: id -- ID contents: annotation?, (restriction | extension) """ attributes = {'id':None} contents = {'xsd':['annotation', 'restriction', 'extension']} tag = 'simpleContent' class Extension(XMLSchemaComponent,\ ExtensionMarker): """ parents: simpleContent attributes: id -- ID base -- QName, required contents: annotation?, (attribute | attributeGroup)*, anyAttribute? """ required = ['base'] attributes = {'id':None, 'base':None } contents = {'xsd':['annotation', 'attribute', 'attributeGroup', 'anyAttribute']} tag = 'extension' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.attr_content = None def getAttributeContent(self): return self.attr_content def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) indx = 0 num = len(contents) if num: component = SplitQName(contents[indx].getTagName())[1] if component == 'annotation': self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) indx += 1 component = SplitQName(contents[indx].getTagName())[1] content = [] while indx < num: component = SplitQName(contents[indx].getTagName())[1] if component == 'attribute': if contents[indx].hasattr('ref'): content.append(AttributeReference(self)) else: content.append(LocalAttributeDeclaration(self)) elif component == 'attributeGroup': content.append(AttributeGroupReference(self)) elif component == 'anyAttribute': content.append(AttributeWildCard(self)) else: raise SchemaError, 'Unknown component (%s)'\ %(contents[indx].getTagName()) content[-1].fromDom(contents[indx]) indx += 1 self.attr_content = tuple(content) class Restriction(XMLSchemaComponent,\ RestrictionMarker): """ parents: simpleContent attributes: id -- ID base -- QName, required contents: annotation?, simpleType?, (enumeration | length | maxExclusive | maxInclusive | maxLength | minExclusive | minInclusive | minLength | pattern | fractionDigits | totalDigits | whiteSpace)*, (attribute | attributeGroup)*, anyAttribute? """ required = ['base'] attributes = {'id':None, 'base':None } contents = {'xsd':['annotation', 'simpleType', 'attribute',\ 'attributeGroup', 'anyAttribute'] + RestrictionMarker.facets} tag = 'restriction' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None self.attr_content = None def getAttributeContent(self): return self.attr_content def fromDom(self, node): self.content = [] self.setAttributes(node) contents = self.getContents(node) indx = 0 num = len(contents) component = SplitQName(contents[indx].getTagName())[1] if component == 'annotation': self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) indx += 1 component = SplitQName(contents[indx].getTagName())[1] content = [] while indx < num: component = SplitQName(contents[indx].getTagName())[1] if component == 'attribute': if contents[indx].hasattr('ref'): content.append(AttributeReference(self)) else: content.append(LocalAttributeDeclaration(self)) elif component == 'attributeGroup': content.append(AttributeGroupReference(self)) elif component == 'anyAttribute': content.append(AttributeWildCard(self)) elif component == 'simpleType': self.content.append(AnonymousSimpleType(self)) self.content[-1].fromDom(contents[indx]) else: raise SchemaError, 'Unknown component (%s)'\ %(contents[indx].getTagName()) content[-1].fromDom(contents[indx]) indx += 1 self.attr_content = tuple(content) class LocalComplexType(ComplexType,\ LocalMarker): """ parents: element attributes: id -- ID mixed -- boolean, false contents: annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, (attribute | attributeGroup)*, anyAttribute?)) """ required = [] attributes = {'id':None, 'mixed':0} tag = 'complexType' class SimpleType(XMLSchemaComponent,\ DefinitionMarker,\ SimpleMarker): """ parents: redefine, schema attributes: id -- ID name -- NCName, required final -- ('#all' | ('extension' | 'restriction' | 'list' | 'union')*), schema.finalDefault contents: annotation?, (restriction | list | union) """ required = ['name'] attributes = {'id':None, 'name':None, 'final':lambda self: self._parent().getFinalDefault()} contents = {'xsd':['annotation', 'restriction', 'list', 'union']} tag = 'simpleType' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def getElementDeclaration(self, attribute): raise Warning, 'invalid operation for <%s>' %self.tag def getTypeDefinition(self, attribute): raise Warning, 'invalid operation for <%s>' %self.tag def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) for child in contents: component = SplitQName(child.getTagName())[1] if component == 'annotation': self.annotation = Annotation(self) self.annotation.fromDom(child) continue break else: return if component == 'restriction': self.content = self.__class__.Restriction(self) elif component == 'list': self.content = self.__class__.List(self) elif component == 'union': self.content = self.__class__.Union(self) else: raise SchemaError, 'Unknown component (%s)' %(component) self.content.fromDom(child) class Restriction(XMLSchemaComponent,\ RestrictionMarker): """ parents: simpleType attributes: id -- ID base -- QName, required or simpleType child contents: annotation?, simpleType?, (enumeration | length | maxExclusive | maxInclusive | maxLength | minExclusive | minInclusive | minLength | pattern | fractionDigits | totalDigits | whiteSpace)* """ attributes = {'id':None, 'base':None } contents = {'xsd':['annotation', 'simpleType']+RestrictionMarker.facets} tag = 'restriction' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None self.facets = None def getAttributeBase(self): return XMLSchemaComponent.getAttribute(self, 'base') def getTypeDefinition(self, attribute='base'): return XMLSchemaComponent.getTypeDefinition(self, attribute) def getSimpleTypeContent(self): for el in self.content: if el.isSimple(): return el return None def fromDom(self, node): self.facets = [] self.setAttributes(node) contents = self.getContents(node) content = [] for indx in range(len(contents)): component = SplitQName(contents[indx].getTagName())[1] if (component == 'annotation') and (not indx): self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) continue elif (component == 'simpleType') and (not indx or indx == 1): content.append(AnonymousSimpleType(self)) content[-1].fromDom(contents[indx]) elif component in RestrictionMarker.facets: self.facets.append(contents[indx]) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class Union(XMLSchemaComponent, UnionMarker): """ parents: simpleType attributes: id -- ID memberTypes -- list of QNames, required or simpleType child. contents: annotation?, simpleType* """ attributes = {'id':None, 'memberTypes':None } contents = {'xsd':['annotation', 'simpleType']} tag = 'union' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def fromDom(self, node): self.setAttributes(node) contents = self.getContents(node) content = [] for indx in range(len(contents)): component = SplitQName(contents[indx].getTagName())[1] if (component == 'annotation') and (not indx): self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) elif (component == 'simpleType'): content.append(AnonymousSimpleType(self)) content[-1].fromDom(contents[indx]) else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) self.content = tuple(content) class List(XMLSchemaComponent, ListMarker): """ parents: simpleType attributes: id -- ID itemType -- QName, required or simpleType child. contents: annotation?, simpleType? """ attributes = {'id':None, 'itemType':None } contents = {'xsd':['annotation', 'simpleType']} tag = 'list' def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None self.content = None def getItemType(self): return self.attributes.get('itemType') def getTypeDefinition(self, attribute='itemType'): """ return the type refered to by itemType attribute or the simpleType content. If returns None, then the type refered to by itemType is primitive. """ tp = XMLSchemaComponent.getTypeDefinition(self, attribute) return tp or self.content def fromDom(self, node): self.annotation = None self.content = None self.setAttributes(node) contents = self.getContents(node) for indx in range(len(contents)): component = SplitQName(contents[indx].getTagName())[1] if (component == 'annotation') and (not indx): self.annotation = Annotation(self) self.annotation.fromDom(contents[indx]) elif (component == 'simpleType'): self.content = AnonymousSimpleType(self) self.content.fromDom(contents[indx]) break else: raise SchemaError, 'Unknown component (%s)' %(i.getTagName()) class AnonymousSimpleType(SimpleType,\ SimpleMarker,\ LocalMarker): """ parents: attribute, element, list, restriction, union attributes: id -- ID contents: annotation?, (restriction | list | union) """ required = [] attributes = {'id':None} tag = 'simpleType' class Redefine: """ parents: attributes: contents: """ tag = 'redefine' ########################### ########################### if sys.version_info[:2] >= (2, 2): tupleClass = tuple else: import UserTuple tupleClass = UserTuple.UserTuple class TypeDescriptionComponent(tupleClass): """Tuple of length 2, consisting of a namespace and unprefixed name. """ def __init__(self, args): """args -- (namespace, name) Remove the name's prefix, irrelevant. """ if len(args) != 2: raise TypeError, 'expecting tuple (namespace, name), got %s' %args elif args[1].find(':') >= 0: args = (args[0], SplitQName(args[1])[1]) tuple.__init__(self, args) return def getTargetNamespace(self): return self[0] def getName(self): return self[1] ZSI-2.1-a1/ZSI/wstools/__init__.py0000644000175100017510000000031010155351115014775 0ustar zsizsi#! /usr/bin/env python """WSDL parsing services package for Web Services for Python.""" ident = "$Id: __init__.py 840 2004-12-07 15:54:53Z blunck2 $" import WSDLTools import XMLname import logging ZSI-2.1-a1/ZSI/wstools/Utility.py0000755000175100017510000014323710644765510014737 0ustar zsizsi# Copyright (c) 2003, The Regents of the University of California, # through Lawrence Berkeley National Laboratory (subject to receipt of # any required approvals from the U.S. Dept. of Energy). All rights # reserved. # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ident = "$Id: Utility.py 1405 2007-07-10 20:25:44Z boverhof $" import sys, types, httplib, urllib, socket, weakref from os.path import isfile from string import join, strip, split from UserDict import UserDict from cStringIO import StringIO from TimeoutSocket import TimeoutSocket, TimeoutError from urlparse import urlparse from httplib import HTTPConnection, HTTPSConnection from exceptions import Exception try: from ZSI import _get_idstr except: def _get_idstr(pyobj): '''Python 2.3.x generates a FutureWarning for negative IDs, so we use a different prefix character to ensure uniqueness, and call abs() to avoid the warning.''' x = id(pyobj) if x < 0: return 'x%x' % abs(x) return 'o%x' % x import xml.dom.minidom from xml.dom import Node import logging from c14n import Canonicalize from Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI try: from xml.dom.ext import SplitQName except: def SplitQName(qname): '''SplitQName(qname) -> (string, string) Split Qualified Name into a tuple of len 2, consisting of the prefix and the local name. (prefix, localName) Special Cases: xmlns -- (localName, 'xmlns') None -- (None, localName) ''' l = qname.split(':') if len(l) == 1: l.insert(0, None) elif len(l) == 2: if l[0] == 'xmlns': l.reverse() else: return return tuple(l) # # python2.3 urllib.basejoin does not remove current directory ./ # from path and this causes problems on subsequent basejoins. # basejoin = urllib.basejoin if sys.version_info[0:2] < (2, 4, 0, 'final', 0)[0:2]: #basejoin = lambda base,url: urllib.basejoin(base,url.lstrip('./')) token = './' def basejoin(base, url): if url.startswith(token) is True: return urllib.basejoin(base,url[2:]) return urllib.basejoin(base,url) class NamespaceError(Exception): """Used to indicate a Namespace Error.""" class RecursionError(Exception): """Used to indicate a HTTP redirect recursion.""" class ParseError(Exception): """Used to indicate a XML parsing error.""" class DOMException(Exception): """Used to indicate a problem processing DOM.""" class Base: """Base class for instance level Logging""" def __init__(self, module=__name__): self.logger = logging.getLogger('%s-%s(%s)' %(module, self.__class__, _get_idstr(self))) class HTTPResponse: """Captures the information in an HTTP response message.""" def __init__(self, response): self.status = response.status self.reason = response.reason self.headers = response.msg self.body = response.read() or None response.close() class TimeoutHTTP(HTTPConnection): """A custom http connection object that supports socket timeout.""" def __init__(self, host, port=None, timeout=20): HTTPConnection.__init__(self, host, port) self.timeout = timeout def connect(self): self.sock = TimeoutSocket(self.timeout) self.sock.connect((self.host, self.port)) class TimeoutHTTPS(HTTPSConnection): """A custom https object that supports socket timeout. Note that this is not really complete. The builtin SSL support in the Python socket module requires a real socket (type) to be passed in to be hooked to SSL. That means our fake socket won't work and our timeout hacks are bypassed for send and recv calls. Since our hack _is_ in place at connect() time, it should at least provide some timeout protection.""" def __init__(self, host, port=None, timeout=20, **kwargs): HTTPSConnection.__init__(self, str(host), port, **kwargs) self.timeout = timeout def connect(self): sock = TimeoutSocket(self.timeout) sock.connect((self.host, self.port)) realsock = getattr(sock.sock, '_sock', sock.sock) ssl = socket.ssl(realsock, self.key_file, self.cert_file) self.sock = httplib.FakeSocket(sock, ssl) def urlopen(url, timeout=20, redirects=None): """A minimal urlopen replacement hack that supports timeouts for http. Note that this supports GET only.""" scheme, host, path, params, query, frag = urlparse(url) if not scheme in ('http', 'https'): return urllib.urlopen(url) if params: path = '%s;%s' % (path, params) if query: path = '%s?%s' % (path, query) if frag: path = '%s#%s' % (path, frag) if scheme == 'https': # If ssl is not compiled into Python, you will not get an exception # until a conn.endheaders() call. We need to know sooner, so use # getattr. try: import M2Crypto except ImportError: if not hasattr(socket, 'ssl'): raise RuntimeError, 'no built-in SSL Support' conn = TimeoutHTTPS(host, None, timeout) else: ctx = M2Crypto.SSL.Context() ctx.set_session_timeout(timeout) conn = M2Crypto.httpslib.HTTPSConnection(host, ssl_context=ctx) conn.set_debuglevel(1) else: conn = TimeoutHTTP(host, None, timeout) conn.putrequest('GET', path) conn.putheader('Connection', 'close') conn.endheaders() response = None while 1: response = conn.getresponse() if response.status != 100: break conn._HTTPConnection__state = httplib._CS_REQ_SENT conn._HTTPConnection__response = None status = response.status # If we get an HTTP redirect, we will follow it automatically. if status >= 300 and status < 400: location = response.msg.getheader('location') if location is not None: response.close() if redirects is not None and redirects.has_key(location): raise RecursionError( 'Circular HTTP redirection detected.' ) if redirects is None: redirects = {} redirects[location] = 1 return urlopen(location, timeout, redirects) raise HTTPResponse(response) if not (status >= 200 and status < 300): raise HTTPResponse(response) body = StringIO(response.read()) response.close() return body class DOM: """The DOM singleton defines a number of XML related constants and provides a number of utility methods for DOM related tasks. It also provides some basic abstractions so that the rest of the package need not care about actual DOM implementation in use.""" # Namespace stuff related to the SOAP specification. NS_SOAP_ENV_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/' NS_SOAP_ENC_1_1 = 'http://schemas.xmlsoap.org/soap/encoding/' NS_SOAP_ENV_1_2 = 'http://www.w3.org/2001/06/soap-envelope' NS_SOAP_ENC_1_2 = 'http://www.w3.org/2001/06/soap-encoding' NS_SOAP_ENV_ALL = (NS_SOAP_ENV_1_1, NS_SOAP_ENV_1_2) NS_SOAP_ENC_ALL = (NS_SOAP_ENC_1_1, NS_SOAP_ENC_1_2) NS_SOAP_ENV = NS_SOAP_ENV_1_1 NS_SOAP_ENC = NS_SOAP_ENC_1_1 _soap_uri_mapping = { NS_SOAP_ENV_1_1 : '1.1', NS_SOAP_ENV_1_2 : '1.2', } SOAP_ACTOR_NEXT_1_1 = 'http://schemas.xmlsoap.org/soap/actor/next' SOAP_ACTOR_NEXT_1_2 = 'http://www.w3.org/2001/06/soap-envelope/actor/next' SOAP_ACTOR_NEXT_ALL = (SOAP_ACTOR_NEXT_1_1, SOAP_ACTOR_NEXT_1_2) def SOAPUriToVersion(self, uri): """Return the SOAP version related to an envelope uri.""" value = self._soap_uri_mapping.get(uri) if value is not None: return value raise ValueError( 'Unsupported SOAP envelope uri: %s' % uri ) def GetSOAPEnvUri(self, version): """Return the appropriate SOAP envelope uri for a given human-friendly SOAP version string (e.g. '1.1').""" attrname = 'NS_SOAP_ENV_%s' % join(split(version, '.'), '_') value = getattr(self, attrname, None) if value is not None: return value raise ValueError( 'Unsupported SOAP version: %s' % version ) def GetSOAPEncUri(self, version): """Return the appropriate SOAP encoding uri for a given human-friendly SOAP version string (e.g. '1.1').""" attrname = 'NS_SOAP_ENC_%s' % join(split(version, '.'), '_') value = getattr(self, attrname, None) if value is not None: return value raise ValueError( 'Unsupported SOAP version: %s' % version ) def GetSOAPActorNextUri(self, version): """Return the right special next-actor uri for a given human-friendly SOAP version string (e.g. '1.1').""" attrname = 'SOAP_ACTOR_NEXT_%s' % join(split(version, '.'), '_') value = getattr(self, attrname, None) if value is not None: return value raise ValueError( 'Unsupported SOAP version: %s' % version ) # Namespace stuff related to XML Schema. NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema' NS_XSI_99 = 'http://www.w3.org/1999/XMLSchema-instance' NS_XSD_00 = 'http://www.w3.org/2000/10/XMLSchema' NS_XSI_00 = 'http://www.w3.org/2000/10/XMLSchema-instance' NS_XSD_01 = 'http://www.w3.org/2001/XMLSchema' NS_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance' NS_XSD_ALL = (NS_XSD_99, NS_XSD_00, NS_XSD_01) NS_XSI_ALL = (NS_XSI_99, NS_XSI_00, NS_XSI_01) NS_XSD = NS_XSD_01 NS_XSI = NS_XSI_01 _xsd_uri_mapping = { NS_XSD_99 : NS_XSI_99, NS_XSD_00 : NS_XSI_00, NS_XSD_01 : NS_XSI_01, } for key, value in _xsd_uri_mapping.items(): _xsd_uri_mapping[value] = key def InstanceUriForSchemaUri(self, uri): """Return the appropriate matching XML Schema instance uri for the given XML Schema namespace uri.""" return self._xsd_uri_mapping.get(uri) def SchemaUriForInstanceUri(self, uri): """Return the appropriate matching XML Schema namespace uri for the given XML Schema instance namespace uri.""" return self._xsd_uri_mapping.get(uri) # Namespace stuff related to WSDL. NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/' NS_WSDL_ALL = (NS_WSDL_1_1,) NS_WSDL = NS_WSDL_1_1 NS_SOAP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/' NS_HTTP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/http/' NS_MIME_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/mime/' NS_SOAP_BINDING_ALL = (NS_SOAP_BINDING_1_1,) NS_HTTP_BINDING_ALL = (NS_HTTP_BINDING_1_1,) NS_MIME_BINDING_ALL = (NS_MIME_BINDING_1_1,) NS_SOAP_BINDING = NS_SOAP_BINDING_1_1 NS_HTTP_BINDING = NS_HTTP_BINDING_1_1 NS_MIME_BINDING = NS_MIME_BINDING_1_1 NS_SOAP_HTTP_1_1 = 'http://schemas.xmlsoap.org/soap/http' NS_SOAP_HTTP_ALL = (NS_SOAP_HTTP_1_1,) NS_SOAP_HTTP = NS_SOAP_HTTP_1_1 _wsdl_uri_mapping = { NS_WSDL_1_1 : '1.1', } def WSDLUriToVersion(self, uri): """Return the WSDL version related to a WSDL namespace uri.""" value = self._wsdl_uri_mapping.get(uri) if value is not None: return value raise ValueError( 'Unsupported SOAP envelope uri: %s' % uri ) def GetWSDLUri(self, version): attr = 'NS_WSDL_%s' % join(split(version, '.'), '_') value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version ) def GetWSDLSoapBindingUri(self, version): attr = 'NS_SOAP_BINDING_%s' % join(split(version, '.'), '_') value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version ) def GetWSDLHttpBindingUri(self, version): attr = 'NS_HTTP_BINDING_%s' % join(split(version, '.'), '_') value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version ) def GetWSDLMimeBindingUri(self, version): attr = 'NS_MIME_BINDING_%s' % join(split(version, '.'), '_') value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version ) def GetWSDLHttpTransportUri(self, version): attr = 'NS_SOAP_HTTP_%s' % join(split(version, '.'), '_') value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version ) # Other xml namespace constants. NS_XMLNS = 'http://www.w3.org/2000/xmlns/' def isElement(self, node, name, nsuri=None): """Return true if the given node is an element with the given name and optional namespace uri.""" if node.nodeType != node.ELEMENT_NODE: return 0 return node.localName == name and \ (nsuri is None or self.nsUriMatch(node.namespaceURI, nsuri)) def getElement(self, node, name, nsuri=None, default=join): """Return the first child of node with a matching name and namespace uri, or the default if one is provided.""" nsmatch = self.nsUriMatch ELEMENT_NODE = node.ELEMENT_NODE for child in node.childNodes: if child.nodeType == ELEMENT_NODE: if ((child.localName == name or name is None) and (nsuri is None or nsmatch(child.namespaceURI, nsuri)) ): return child if default is not join: return default raise KeyError, name def getElementById(self, node, id, default=join): """Return the first child of node matching an id reference.""" attrget = self.getAttr ELEMENT_NODE = node.ELEMENT_NODE for child in node.childNodes: if child.nodeType == ELEMENT_NODE: if attrget(child, 'id') == id: return child if default is not join: return default raise KeyError, name def getMappingById(self, document, depth=None, element=None, mapping=None, level=1): """Create an id -> element mapping of those elements within a document that define an id attribute. The depth of the search may be controlled by using the (1-based) depth argument.""" if document is not None: element = document.documentElement mapping = {} attr = element._attrs.get('id', None) if attr is not None: mapping[attr.value] = element if depth is None or depth > level: level = level + 1 ELEMENT_NODE = element.ELEMENT_NODE for child in element.childNodes: if child.nodeType == ELEMENT_NODE: self.getMappingById(None, depth, child, mapping, level) return mapping def getElements(self, node, name, nsuri=None): """Return a sequence of the child elements of the given node that match the given name and optional namespace uri.""" nsmatch = self.nsUriMatch result = [] ELEMENT_NODE = node.ELEMENT_NODE for child in node.childNodes: if child.nodeType == ELEMENT_NODE: if ((child.localName == name or name is None) and ( (nsuri is None) or nsmatch(child.namespaceURI, nsuri))): result.append(child) return result def hasAttr(self, node, name, nsuri=None): """Return true if element has attribute with the given name and optional nsuri. If nsuri is not specified, returns true if an attribute exists with the given name with any namespace.""" if nsuri is None: if node.hasAttribute(name): return True return False return node.hasAttributeNS(nsuri, name) def getAttr(self, node, name, nsuri=None, default=join): """Return the value of the attribute named 'name' with the optional nsuri, or the default if one is specified. If nsuri is not specified, an attribute that matches the given name will be returned regardless of namespace.""" if nsuri is None: result = node._attrs.get(name, None) if result is None: for item in node._attrsNS.keys(): if item[1] == name: result = node._attrsNS[item] break else: result = node._attrsNS.get((nsuri, name), None) if result is not None: return result.value if default is not join: return default return '' def getAttrs(self, node): """Return a Collection of all attributes """ attrs = {} for k,v in node._attrs.items(): attrs[k] = v.value return attrs def getElementText(self, node, preserve_ws=None): """Return the text value of an xml element node. Leading and trailing whitespace is stripped from the value unless the preserve_ws flag is passed with a true value.""" result = [] for child in node.childNodes: nodetype = child.nodeType if nodetype == child.TEXT_NODE or \ nodetype == child.CDATA_SECTION_NODE: result.append(child.nodeValue) value = join(result, '') if preserve_ws is None: value = strip(value) return value def findNamespaceURI(self, prefix, node): """Find a namespace uri given a prefix and a context node.""" attrkey = (self.NS_XMLNS, prefix) DOCUMENT_NODE = node.DOCUMENT_NODE ELEMENT_NODE = node.ELEMENT_NODE while 1: if node is None: raise DOMException('Value for prefix %s not found.' % prefix) if node.nodeType != ELEMENT_NODE: node = node.parentNode continue result = node._attrsNS.get(attrkey, None) if result is not None: return result.value if hasattr(node, '__imported__'): raise DOMException('Value for prefix %s not found.' % prefix) node = node.parentNode if node.nodeType == DOCUMENT_NODE: raise DOMException('Value for prefix %s not found.' % prefix) def findDefaultNS(self, node): """Return the current default namespace uri for the given node.""" attrkey = (self.NS_XMLNS, 'xmlns') DOCUMENT_NODE = node.DOCUMENT_NODE ELEMENT_NODE = node.ELEMENT_NODE while 1: if node.nodeType != ELEMENT_NODE: node = node.parentNode continue result = node._attrsNS.get(attrkey, None) if result is not None: return result.value if hasattr(node, '__imported__'): raise DOMException('Cannot determine default namespace.') node = node.parentNode if node.nodeType == DOCUMENT_NODE: raise DOMException('Cannot determine default namespace.') def findTargetNS(self, node): """Return the defined target namespace uri for the given node.""" attrget = self.getAttr attrkey = (self.NS_XMLNS, 'xmlns') DOCUMENT_NODE = node.DOCUMENT_NODE ELEMENT_NODE = node.ELEMENT_NODE while 1: if node.nodeType != ELEMENT_NODE: node = node.parentNode continue result = attrget(node, 'targetNamespace', default=None) if result is not None: return result node = node.parentNode if node.nodeType == DOCUMENT_NODE: raise DOMException('Cannot determine target namespace.') def getTypeRef(self, element): """Return (namespaceURI, name) for a type attribue of the given element, or None if the element does not have a type attribute.""" typeattr = self.getAttr(element, 'type', default=None) if typeattr is None: return None parts = typeattr.split(':', 1) if len(parts) == 2: nsuri = self.findNamespaceURI(parts[0], element) else: nsuri = self.findDefaultNS(element) return (nsuri, parts[1]) def importNode(self, document, node, deep=0): """Implements (well enough for our purposes) DOM node import.""" nodetype = node.nodeType if nodetype in (node.DOCUMENT_NODE, node.DOCUMENT_TYPE_NODE): raise DOMException('Illegal node type for importNode') if nodetype == node.ENTITY_REFERENCE_NODE: deep = 0 clone = node.cloneNode(deep) self._setOwnerDoc(document, clone) clone.__imported__ = 1 return clone def _setOwnerDoc(self, document, node): node.ownerDocument = document for child in node.childNodes: self._setOwnerDoc(document, child) def nsUriMatch(self, value, wanted, strict=0, tt=type(())): """Return a true value if two namespace uri values match.""" if value == wanted or (type(wanted) is tt) and value in wanted: return 1 if not strict and value is not None: wanted = type(wanted) is tt and wanted or (wanted,) value = value[-1:] != '/' and value or value[:-1] for item in wanted: if item == value or item[:-1] == value: return 1 return 0 def createDocument(self, nsuri, qname, doctype=None): """Create a new writable DOM document object.""" impl = xml.dom.minidom.getDOMImplementation() return impl.createDocument(nsuri, qname, doctype) def loadDocument(self, data): """Load an xml file from a file-like object and return a DOM document instance.""" return xml.dom.minidom.parse(data) def loadFromURL(self, url): """Load an xml file from a URL and return a DOM document.""" if isfile(url) is True: file = open(url, 'r') else: file = urlopen(url) try: result = self.loadDocument(file) except Exception, ex: file.close() raise ParseError(('Failed to load document %s' %url,) + ex.args) else: file.close() return result DOM = DOM() class MessageInterface: '''Higher Level Interface, delegates to DOM singleton, must be subclassed and implement all methods that throw NotImplementedError. ''' def __init__(self, sw): '''Constructor, May be extended, do not override. sw -- soapWriter instance ''' self.sw = None if type(sw) != weakref.ReferenceType and sw is not None: self.sw = weakref.ref(sw) else: self.sw = sw def AddCallback(self, func, *arglist): self.sw().AddCallback(func, *arglist) def Known(self, obj): return self.sw().Known(obj) def Forget(self, obj): return self.sw().Forget(obj) def canonicalize(self): '''canonicalize the underlying DOM, and return as string. ''' raise NotImplementedError, '' def createDocument(self, namespaceURI=SOAP.ENV, localName='Envelope'): '''create Document ''' raise NotImplementedError, '' def createAppendElement(self, namespaceURI, localName): '''create and append element(namespaceURI,localName), and return the node. ''' raise NotImplementedError, '' def findNamespaceURI(self, qualifiedName): raise NotImplementedError, '' def resolvePrefix(self, prefix): raise NotImplementedError, '' def setAttributeNS(self, namespaceURI, localName, value): '''set attribute (namespaceURI, localName)=value ''' raise NotImplementedError, '' def setAttributeType(self, namespaceURI, localName): '''set attribute xsi:type=(namespaceURI, localName) ''' raise NotImplementedError, '' def setNamespaceAttribute(self, namespaceURI, prefix): '''set namespace attribute xmlns:prefix=namespaceURI ''' raise NotImplementedError, '' class ElementProxy(Base, MessageInterface): ''' ''' _soap_env_prefix = 'SOAP-ENV' _soap_enc_prefix = 'SOAP-ENC' _zsi_prefix = 'ZSI' _xsd_prefix = 'xsd' _xsi_prefix = 'xsi' _xml_prefix = 'xml' _xmlns_prefix = 'xmlns' _soap_env_nsuri = SOAP.ENV _soap_enc_nsuri = SOAP.ENC _zsi_nsuri = ZSI_SCHEMA_URI _xsd_nsuri = SCHEMA.XSD3 _xsi_nsuri = SCHEMA.XSI3 _xml_nsuri = XMLNS.XML _xmlns_nsuri = XMLNS.BASE standard_ns = {\ _xml_prefix:_xml_nsuri, _xmlns_prefix:_xmlns_nsuri } reserved_ns = {\ _soap_env_prefix:_soap_env_nsuri, _soap_enc_prefix:_soap_enc_nsuri, _zsi_prefix:_zsi_nsuri, _xsd_prefix:_xsd_nsuri, _xsi_prefix:_xsi_nsuri, } name = None namespaceURI = None def __init__(self, sw, message=None): '''Initialize. sw -- SoapWriter ''' self._indx = 0 MessageInterface.__init__(self, sw) Base.__init__(self) self._dom = DOM self.node = None if type(message) in (types.StringType,types.UnicodeType): self.loadFromString(message) elif isinstance(message, ElementProxy): self.node = message._getNode() else: self.node = message self.processorNss = self.standard_ns.copy() self.processorNss.update(self.reserved_ns) def __str__(self): return self.toString() def evaluate(self, expression, processorNss=None): '''expression -- XPath compiled expression ''' from Ft.Xml import XPath if not processorNss: context = XPath.Context.Context(self.node, processorNss=self.processorNss) else: context = XPath.Context.Context(self.node, processorNss=processorNss) nodes = expression.evaluate(context) return map(lambda node: ElementProxy(self.sw,node), nodes) ############################################# # Methods for checking/setting the # classes (namespaceURI,name) node. ############################################# def checkNode(self, namespaceURI=None, localName=None): ''' namespaceURI -- namespace of element localName -- local name of element ''' namespaceURI = namespaceURI or self.namespaceURI localName = localName or self.name check = False if localName and self.node: check = self._dom.isElement(self.node, localName, namespaceURI) if not check: raise NamespaceError, 'unexpected node type %s, expecting %s' %(self.node, localName) def setNode(self, node=None): if node: if isinstance(node, ElementProxy): self.node = node._getNode() else: self.node = node elif self.node: node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None) if not node: raise NamespaceError, 'cant find element (%s,%s)' %(self.namespaceURI,self.name) self.node = node else: #self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None) self.createDocument(self.namespaceURI, localName=self.name, doctype=None) self.checkNode() ############################################# # Wrapper Methods for direct DOM Element Node access ############################################# def _getNode(self): return self.node def _getElements(self): return self._dom.getElements(self.node, name=None) def _getOwnerDocument(self): return self.node.ownerDocument or self.node def _getUniquePrefix(self): '''I guess we need to resolve all potential prefixes because when the current node is attached it copies the namespaces into the parent node. ''' while 1: self._indx += 1 prefix = 'ns%d' %self._indx try: self._dom.findNamespaceURI(prefix, self._getNode()) except DOMException, ex: break return prefix def _getPrefix(self, node, nsuri): ''' Keyword arguments: node -- DOM Element Node nsuri -- namespace of attribute value ''' try: if node and (node.nodeType == node.ELEMENT_NODE) and \ (nsuri == self._dom.findDefaultNS(node)): return None except DOMException, ex: pass if nsuri == XMLNS.XML: return self._xml_prefix if node.nodeType == Node.ELEMENT_NODE: for attr in node.attributes.values(): if attr.namespaceURI == XMLNS.BASE \ and nsuri == attr.value: return attr.localName else: if node.parentNode: return self._getPrefix(node.parentNode, nsuri) raise NamespaceError, 'namespaceURI "%s" is not defined' %nsuri def _appendChild(self, node): ''' Keyword arguments: node -- DOM Element Node ''' if node is None: raise TypeError, 'node is None' self.node.appendChild(node) def _insertBefore(self, newChild, refChild): ''' Keyword arguments: child -- DOM Element Node to insert refChild -- DOM Element Node ''' self.node.insertBefore(newChild, refChild) def _setAttributeNS(self, namespaceURI, qualifiedName, value): ''' Keyword arguments: namespaceURI -- namespace of attribute qualifiedName -- qualified name of new attribute value value -- value of attribute ''' self.node.setAttributeNS(namespaceURI, qualifiedName, value) ############################################# #General Methods ############################################# def isFault(self): '''check to see if this is a soap:fault message. ''' return False def getPrefix(self, namespaceURI): try: prefix = self._getPrefix(node=self.node, nsuri=namespaceURI) except NamespaceError, ex: prefix = self._getUniquePrefix() self.setNamespaceAttribute(prefix, namespaceURI) return prefix def getDocument(self): return self._getOwnerDocument() def setDocument(self, document): self.node = document def importFromString(self, xmlString): doc = self._dom.loadDocument(StringIO(xmlString)) node = self._dom.getElement(doc, name=None) clone = self.importNode(node) self._appendChild(clone) def importNode(self, node): if isinstance(node, ElementProxy): node = node._getNode() return self._dom.importNode(self._getOwnerDocument(), node, deep=1) def loadFromString(self, data): self.node = self._dom.loadDocument(StringIO(data)) def canonicalize(self): return Canonicalize(self.node) def toString(self): return self.canonicalize() def createDocument(self, namespaceURI, localName, doctype=None): '''If specified must be a SOAP envelope, else may contruct an empty document. ''' prefix = self._soap_env_prefix if namespaceURI == self.reserved_ns[prefix]: qualifiedName = '%s:%s' %(prefix,localName) elif namespaceURI is localName is None: self.node = self._dom.createDocument(None,None,None) return else: raise KeyError, 'only support creation of document in %s' %self.reserved_ns[prefix] document = self._dom.createDocument(nsuri=namespaceURI, qname=qualifiedName, doctype=doctype) self.node = document.childNodes[0] #set up reserved namespace attributes for prefix,nsuri in self.reserved_ns.items(): self._setAttributeNS(namespaceURI=self._xmlns_nsuri, qualifiedName='%s:%s' %(self._xmlns_prefix,prefix), value=nsuri) ############################################# #Methods for attributes ############################################# def hasAttribute(self, namespaceURI, localName): return self._dom.hasAttr(self._getNode(), name=localName, nsuri=namespaceURI) def setAttributeType(self, namespaceURI, localName): '''set xsi:type Keyword arguments: namespaceURI -- namespace of attribute value localName -- name of new attribute value ''' self.logger.debug('setAttributeType: (%s,%s)', namespaceURI, localName) value = localName if namespaceURI: value = '%s:%s' %(self.getPrefix(namespaceURI),localName) xsi_prefix = self.getPrefix(self._xsi_nsuri) self._setAttributeNS(self._xsi_nsuri, '%s:type' %xsi_prefix, value) def createAttributeNS(self, namespace, name, value): document = self._getOwnerDocument() attrNode = document.createAttributeNS(namespace, name, value) def setAttributeNS(self, namespaceURI, localName, value): ''' Keyword arguments: namespaceURI -- namespace of attribute to create, None is for attributes in no namespace. localName -- local name of new attribute value -- value of new attribute ''' prefix = None if namespaceURI: try: prefix = self.getPrefix(namespaceURI) except KeyError, ex: prefix = 'ns2' self.setNamespaceAttribute(prefix, namespaceURI) qualifiedName = localName if prefix: qualifiedName = '%s:%s' %(prefix, localName) self._setAttributeNS(namespaceURI, qualifiedName, value) def setNamespaceAttribute(self, prefix, namespaceURI): ''' Keyword arguments: prefix -- xmlns prefix namespaceURI -- value of prefix ''' self._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI) ############################################# #Methods for elements ############################################# def createElementNS(self, namespace, qname): ''' Keyword arguments: namespace -- namespace of element to create qname -- qualified name of new element ''' document = self._getOwnerDocument() node = document.createElementNS(namespace, qname) return ElementProxy(self.sw, node) def createAppendSetElement(self, namespaceURI, localName, prefix=None): '''Create a new element (namespaceURI,name), append it to current node, then set it to be the current node. Keyword arguments: namespaceURI -- namespace of element to create localName -- local name of new element prefix -- if namespaceURI is not defined, declare prefix. defaults to 'ns1' if left unspecified. ''' node = self.createAppendElement(namespaceURI, localName, prefix=None) node=node._getNode() self._setNode(node._getNode()) def createAppendElement(self, namespaceURI, localName, prefix=None): '''Create a new element (namespaceURI,name), append it to current node, and return the newly created node. Keyword arguments: namespaceURI -- namespace of element to create localName -- local name of new element prefix -- if namespaceURI is not defined, declare prefix. defaults to 'ns1' if left unspecified. ''' declare = False qualifiedName = localName if namespaceURI: try: prefix = self.getPrefix(namespaceURI) except: declare = True prefix = prefix or self._getUniquePrefix() if prefix: qualifiedName = '%s:%s' %(prefix, localName) node = self.createElementNS(namespaceURI, qualifiedName) if declare: node._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI) self._appendChild(node=node._getNode()) return node def createInsertBefore(self, namespaceURI, localName, refChild): qualifiedName = localName prefix = self.getPrefix(namespaceURI) if prefix: qualifiedName = '%s:%s' %(prefix, localName) node = self.createElementNS(namespaceURI, qualifiedName) self._insertBefore(newChild=node._getNode(), refChild=refChild._getNode()) return node def getElement(self, namespaceURI, localName): ''' Keyword arguments: namespaceURI -- namespace of element localName -- local name of element ''' node = self._dom.getElement(self.node, localName, namespaceURI, default=None) if node: return ElementProxy(self.sw, node) return None def getAttributeValue(self, namespaceURI, localName): ''' Keyword arguments: namespaceURI -- namespace of attribute localName -- local name of attribute ''' if self.hasAttribute(namespaceURI, localName): attr = self.node.getAttributeNodeNS(namespaceURI,localName) return attr.value return None def getValue(self): return self._dom.getElementText(self.node, preserve_ws=True) ############################################# #Methods for text nodes ############################################# def createAppendTextNode(self, pyobj): node = self.createTextNode(pyobj) self._appendChild(node=node._getNode()) return node def createTextNode(self, pyobj): document = self._getOwnerDocument() node = document.createTextNode(pyobj) return ElementProxy(self.sw, node) ############################################# #Methods for retrieving namespaceURI's ############################################# def findNamespaceURI(self, qualifiedName): parts = SplitQName(qualifiedName) element = self._getNode() if len(parts) == 1: return (self._dom.findTargetNS(element), value) return self._dom.findNamespaceURI(parts[0], element) def resolvePrefix(self, prefix): element = self._getNode() return self._dom.findNamespaceURI(prefix, element) def getSOAPEnvURI(self): return self._soap_env_nsuri def isEmpty(self): return not self.node class Collection(UserDict): """Helper class for maintaining ordered named collections.""" default = lambda self,k: k.name def __init__(self, parent, key=None): UserDict.__init__(self) self.parent = weakref.ref(parent) self.list = [] self._func = key or self.default def __getitem__(self, key): if type(key) is type(1): return self.list[key] return self.data[key] def __setitem__(self, key, item): item.parent = weakref.ref(self) self.list.append(item) self.data[key] = item def keys(self): return map(lambda i: self._func(i), self.list) def items(self): return map(lambda i: (self._func(i), i), self.list) def values(self): return self.list class CollectionNS(UserDict): """Helper class for maintaining ordered named collections.""" default = lambda self,k: k.name def __init__(self, parent, key=None): UserDict.__init__(self) self.parent = weakref.ref(parent) self.targetNamespace = None self.list = [] self._func = key or self.default def __getitem__(self, key): self.targetNamespace = self.parent().targetNamespace if type(key) is types.IntType: return self.list[key] elif self.__isSequence(key): nsuri,name = key return self.data[nsuri][name] return self.data[self.parent().targetNamespace][key] def __setitem__(self, key, item): item.parent = weakref.ref(self) self.list.append(item) targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace) if not self.data.has_key(targetNamespace): self.data[targetNamespace] = {} self.data[targetNamespace][key] = item def __isSequence(self, key): return (type(key) in (types.TupleType,types.ListType) and len(key) == 2) def keys(self): keys = [] for tns in self.data.keys(): keys.append(map(lambda i: (tns,self._func(i)), self.data[tns].values())) return keys def items(self): return map(lambda i: (self._func(i), i), self.list) def values(self): return self.list # This is a runtime guerilla patch for pulldom (used by minidom) so # that xml namespace declaration attributes are not lost in parsing. # We need them to do correct QName linking for XML Schema and WSDL. # The patch has been submitted to SF for the next Python version. from xml.dom.pulldom import PullDOM, START_ELEMENT if 1: def startPrefixMapping(self, prefix, uri): if not hasattr(self, '_xmlns_attrs'): self._xmlns_attrs = [] self._xmlns_attrs.append((prefix or 'xmlns', uri)) self._ns_contexts.append(self._current_context.copy()) self._current_context[uri] = prefix or '' PullDOM.startPrefixMapping = startPrefixMapping def startElementNS(self, name, tagName , attrs): # Retrieve xml namespace declaration attributes. xmlns_uri = 'http://www.w3.org/2000/xmlns/' xmlns_attrs = getattr(self, '_xmlns_attrs', None) if xmlns_attrs is not None: for aname, value in xmlns_attrs: attrs._attrs[(xmlns_uri, aname)] = value self._xmlns_attrs = [] uri, localname = name if uri: # When using namespaces, the reader may or may not # provide us with the original name. If not, create # *a* valid tagName from the current context. if tagName is None: prefix = self._current_context[uri] if prefix: tagName = prefix + ":" + localname else: tagName = localname if self.document: node = self.document.createElementNS(uri, tagName) else: node = self.buildDocument(uri, tagName) else: # When the tagname is not prefixed, it just appears as # localname if self.document: node = self.document.createElement(localname) else: node = self.buildDocument(None, localname) for aname,value in attrs.items(): a_uri, a_localname = aname if a_uri == xmlns_uri: if a_localname == 'xmlns': qname = a_localname else: qname = 'xmlns:' + a_localname attr = self.document.createAttributeNS(a_uri, qname) node.setAttributeNodeNS(attr) elif a_uri: prefix = self._current_context[a_uri] if prefix: qname = prefix + ":" + a_localname else: qname = a_localname attr = self.document.createAttributeNS(a_uri, qname) node.setAttributeNodeNS(attr) else: attr = self.document.createAttribute(a_localname) node.setAttributeNode(attr) attr.value = value self.lastEvent[1] = [(START_ELEMENT, node), None] self.lastEvent = self.lastEvent[1] self.push(node) PullDOM.startElementNS = startElementNS # # This is a runtime guerilla patch for minidom so # that xmlns prefixed attributes dont raise AttributeErrors # during cloning. # # Namespace declarations can appear in any start-tag, must look for xmlns # prefixed attribute names during cloning. # # key (attr.namespaceURI, tag) # ('http://www.w3.org/2000/xmlns/', u'xsd') # ('http://www.w3.org/2000/xmlns/', 'xmlns') # # xml.dom.minidom.Attr.nodeName = xmlns:xsd # xml.dom.minidom.Attr.value = = http://www.w3.org/2001/XMLSchema if 1: def _clone_node(node, deep, newOwnerDocument): """ Clone a node and give it the new owner document. Called by Node.cloneNode and Document.importNode """ if node.ownerDocument.isSameNode(newOwnerDocument): operation = xml.dom.UserDataHandler.NODE_CLONED else: operation = xml.dom.UserDataHandler.NODE_IMPORTED if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE: clone = newOwnerDocument.createElementNS(node.namespaceURI, node.nodeName) for attr in node.attributes.values(): clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) prefix, tag = xml.dom.minidom._nssplit(attr.nodeName) if prefix == 'xmlns': a = clone.getAttributeNodeNS(attr.namespaceURI, tag) elif prefix: a = clone.getAttributeNodeNS(attr.namespaceURI, tag) else: a = clone.getAttributeNodeNS(attr.namespaceURI, attr.nodeName) a.specified = attr.specified if deep: for child in node.childNodes: c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument) clone.appendChild(c) elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_FRAGMENT_NODE: clone = newOwnerDocument.createDocumentFragment() if deep: for child in node.childNodes: c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument) clone.appendChild(c) elif node.nodeType == xml.dom.minidom.Node.TEXT_NODE: clone = newOwnerDocument.createTextNode(node.data) elif node.nodeType == xml.dom.minidom.Node.CDATA_SECTION_NODE: clone = newOwnerDocument.createCDATASection(node.data) elif node.nodeType == xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE: clone = newOwnerDocument.createProcessingInstruction(node.target, node.data) elif node.nodeType == xml.dom.minidom.Node.COMMENT_NODE: clone = newOwnerDocument.createComment(node.data) elif node.nodeType == xml.dom.minidom.Node.ATTRIBUTE_NODE: clone = newOwnerDocument.createAttributeNS(node.namespaceURI, node.nodeName) clone.specified = True clone.value = node.value elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_TYPE_NODE: assert node.ownerDocument is not newOwnerDocument operation = xml.dom.UserDataHandler.NODE_IMPORTED clone = newOwnerDocument.implementation.createDocumentType( node.name, node.publicId, node.systemId) clone.ownerDocument = newOwnerDocument if deep: clone.entities._seq = [] clone.notations._seq = [] for n in node.notations._seq: notation = xml.dom.minidom.Notation(n.nodeName, n.publicId, n.systemId) notation.ownerDocument = newOwnerDocument clone.notations._seq.append(notation) if hasattr(n, '_call_user_data_handler'): n._call_user_data_handler(operation, n, notation) for e in node.entities._seq: entity = xml.dom.minidom.Entity(e.nodeName, e.publicId, e.systemId, e.notationName) entity.actualEncoding = e.actualEncoding entity.encoding = e.encoding entity.version = e.version entity.ownerDocument = newOwnerDocument clone.entities._seq.append(entity) if hasattr(e, '_call_user_data_handler'): e._call_user_data_handler(operation, n, entity) else: # Note the cloning of Document and DocumentType nodes is # implemenetation specific. minidom handles those cases # directly in the cloneNode() methods. raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node)) # Check for _call_user_data_handler() since this could conceivably # used with other DOM implementations (one of the FourThought # DOMs, perhaps?). if hasattr(node, '_call_user_data_handler'): node._call_user_data_handler(operation, node, clone) return clone xml.dom.minidom._clone_node = _clone_node ZSI-2.1-a1/ZSI/wstools/test/0000755000175100017510000000000010712455110013650 5ustar zsizsiZSI-2.1-a1/ZSI/wstools/test/.cvsignore0000644000175100017510000000000610271502250015642 0ustar zsizsi*.pyc ZSI-2.1-a1/ZSI/wstools/test/README0000644000175100017510000000334610005132753014536 0ustar zsizsiTwo top level modules have been provided to run the tests. "test_wstools.py" is used to run all of the local tests. "test_wstools_net.py" is used to run all of the tests that require network access. Add the -v option for more informative feedback. ADDING TESTS: 1. For Stand-Alone tests add WSDL FILE to appropriate archive file Need to add a NEW Archive?: config.txt [files] "archive" -- tuple of all archive files, if you need to create a new archive append the archive name to the 'archive' tuple. 2. Edit config.txt section(s): option -- name by which service will be referenced in test case. Need an entry under appropriate section(s), this name must be unique within each section it appears but it may appear in multiple sections. config.txt "test" sections: Stand-Alone -- add "option" under [services_by_file] eg. amazon = exports/AmazonWebServices.wsdl Network -- add "option" under [services_by_http] eg. amazon = http://soap.amazon.com/schemas/AmazonWebServices.wsdl Broken -- add "option" under [broken] 3. Done CONTENTS OF SAMPLE WSDL/XSD: schema -- Taken from globus-3.0.1(http://www.globus.org) xmethods -- Taken from XMethods(http://www.xmethods.com) airport.wsdl AmazonWebServices.wsdl books.wsdl Distance.wsdl freedb.wsdl globalweather.wsdl IHaddock.wsdl ip2geo.wsdl magic.wsdl query.wsdl RateInfo.wsdl SHA1Encrypt.wsdl siteInspect.wsdl TemperatureService.wsdl usweather.wsdl rtf2html.xml SolveSystem.wsdl.xml zip2geo.wsdl ZSI-2.1-a1/ZSI/wstools/test/test_wstools_net.py0000644000175100017510000000102710005132753017641 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, David W. Robertson, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import unittest import test_wsdl def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(test_wsdl.makeTestSuite("services_by_http")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/ZSI/wstools/test/test_t1.py0000644000175100017510000000114007730733464015622 0ustar zsizsi############################################################################ # Joshua R. Boverhof, David W. Robertson, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import unittest import test_wsdl import utils def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(test_wsdl.makeTestSuite("services_by_file")) return suite def main(): loader = utils.MatchTestLoader(True, None, "makeTestSuite") unittest.main(defaultTest="makeTestSuite", testLoader=loader) if __name__ == "__main__" : main() ZSI-2.1-a1/ZSI/wstools/test/test_wstools.py0000644000175100017510000000176010005132753016777 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, David W. Robertson, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import unittest, tarfile, os, ConfigParser import test_wsdl SECTION='files' CONFIG_FILE = 'config.txt' def extractFiles(section, option): config = ConfigParser.ConfigParser() config.read(CONFIG_FILE) archives = config.get(section, option) archives = eval(archives) for file in archives: tar = tarfile.open(file) if not os.access(tar.membernames[0], os.R_OK): for i in tar.getnames(): tar.extract(i) def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(test_wsdl.makeTestSuite("services_by_file")) return suite def main(): extractFiles(SECTION, 'archives') unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/ZSI/wstools/test/config.txt0000644000175100017510000005622510005132503015661 0ustar zsizsi############################################################################ # Joshua R. Boverhof, David W. Robertson, LBNL # See Copyright for copyright notice! ########################################################################### ########################################################################### # Config file for the unit test framework. # Sections below. ########################################################################### ########################################################################## # SECTION [files] - archives of wsdl/xsd files. # ########################################################################## [files] archives = ('xmethods.tar.gz', 'schema.tar.gz') ########################################################################## # SECTION [services_by_file] - all services locally available for # testing. ########################################################################## [services_by_file] ogsi = schema/ogsi/ogsi_service.wsdl airport = xmethods/airport.wsdl distance = xmethods/Distance.wsdl freedb = xmethods/freedb.wsdl globalweather = xmethods/globalweather.wsdl IHaddock = xmethods/IHaddock.wsdl ip2geo = xmethods/ip2geo.wsdl magic = xmethods/magic.wsdl query = xmethods/query.wsdl RateInfo = xmethods/RateInfo.wsdl SHA1Encrypt = xmethods/SHA1Encrypt.wsdl siteInsepct = xmethods/siteInspect.wsdl TemperatureService = xmethods/TemperatureService.wsdl usweather = xmethods/usweather.wsdl zip2geo = xmethods/zip2geo.wsdl SolveSystem = xmethods/SolveSystem.wsdl.xml ########################################################################## # SECTION [services_by_http] - ########################################################################## [services_by_http] # no schemas AbysalSendEmail = http://www.abysal.com/soap/AbysalEmail.wsdl BNQuoteService = http://www.xmethods.net/sd/2001/BNQuoteService.wsdl BabelFishService = http://www.xmethods.net/sd/2001/BabelFishService.wsdl Bible = http://www.stgregorioschurchdc.org/wsdl/Bible.wsdl Blast = http://xml.nig.ac.jp/wsdl/Blast.wsdl CATrafficService = http://www.xmethods.net/sd/2001/CATrafficService.wsdl Calendar = http://www.stgregorioschurchdc.org/wsdl/Calendar.wsdl ClustalW = http://xml.nig.ac.jp/wsdl/ClustalW.wsdl CountryInfoLookupService = http://www.cs.uga.edu/~sent/xmethods/CountryInfoLookup.wsdl CurrencyExchangeService = http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl DDBJ = http://xml.nig.ac.jp/wsdl/DDBJ.wsdl DiscordianService = http://www.compkarori.com/wsdl/discordian.wsdl DistanceService = http://webservices.imacination.com/distance/Distance.jws?wsdl DocServService = http://docserv.aurigalogic.com/docserv.wsdl EMWebFunctionWS = http://www.eyemaginations.com/cgi-bin/getWSDL.pl?wsdl=WebFunction.wsdl Fasta = http://xml.nig.ac.jp/wsdl/Fasta.wsdl FaxService = http://oneoutbox.com/wsdl/FaxService.wsdl FreeFaxService = http://www.OneOutBox.com/wsdl/FreeFaxService.wsdl GetEntry = http://xml.nig.ac.jp/wsdl/GetEntry.wsdl IBorlandBabelservice = http://ww6.borland.com/webservices/BorlandBabel/BorlandBabel.exe/wsdl/IBorlandBabel IBorlandChessservice = http://www.danmarinescu.com/WebServices/ChessCGIServer.exe/wsdl/IBorlandChess IDutchservice = http://www.ebob42.com/cgi-bin/NumberToWordsInDutch.exe/wsdl/IDutch IEmailServiceservice = http://webservices.matlus.com/scripts/emailwebservice.dll/wsdl/IEmailService IHeadLineservice = http://www.ebob42.com/cgi-bin/DrBobsClinic.exe/wsdl/IHeadline IMapQuestservice = http://ww6.borland.com/webservices/MapQuest/MapQuest.exe/wsdl/IMapQuest IMsSessionBrokerServiceservice = http://webservices.matlus.com/scripts/sessionservice.dll/wsdl/IMsSessionBrokerService IODCODESPOSTAUXservice = http://www.e-naxos.com/scripts/enwscp.dll/wsdl/IODCODESPOSTAUX IPGPKeyServerservice = http://www.marotz.se/PGPKeyServer/PGPKeyServiceX.exe/wsdl/IPGPKeyServer IPrimeGeneratorservice = http://www.jusufdarmawan.com/wsprimegenerator.exe/wsdl/IPrimeGenerator IRomanservice = http://www.ebob42.com/cgi-bin/Romulan.exe/wsdl/IRoman ISMSServiceservice = http://sms.idws.com/soap/smsservice.dll/wsdl/ISMSService ISlashdotHeadlineProviderservice = http://www.marotz.se/scripts/SlashdotHeadlines.exe/wsdl/ISlashdotHeadlineProvider ISwedishZipInfoservice = http://www.marotz.se/scripts/zipinfo.exe/wsdl/ISwedishZipInfo ITempConverterservice = http://developerdays.com/cgi-bin/tempconverter.exe/wsdl/ITempConverter IWSMazeServerservice = http://www.culand.net/WebServices/bin/WSMaze_Server.dll/wsdl/IWSMazeServer IWagAddressServerSingleservice = http://62.212.78.36/cgi-bin/WagAddressServerSingle.exe/wsdl/IWagAddressServerSingle IWhoIsservice = http://webservices.matlus.com/scripts/whoiswebservice.dll/wsdl/IWhoIs Ieconomicservice = http://www.suiyi.com/soap/economic.dll/wsdl/Ieconomic IgetNumbersservice = http://reto.checkit.ch/Scripts/Lotto.dll/wsdl/IgetNumbers Iws_Verify_NRICservice = http://www.rightsecurity.biz/NRICWebServices/NRICWebServices.dll/wsdl/Iws_Verify_NRIC KRSS_DAML_Service = http://digilander.libero.it/mamo78/KRSS_DAML_Service.wsdl MBWSSoapService = http://www.extensio.com:8080/ExtensioInfoServer/mbsoap/MBWSSoapServices.wsdl SRS = http://xml.nig.ac.jp/wsdl/SRS.wsdl ServiceSMS = http://smsserver.dotnetisp.com/servicesms.asmx?WSDL TemperatureService = http://www.xmethods.net/sd/2001/TemperatureService.wsdl TxSearch = http://xml.nig.ac.jp/wsdl/TxSearch.wsdl UrduSOAP = http://www.apniurdu.com/SOAP/Urdu2.wsdl WSFindMP3 = http://xmlrad.com/WSFindMP3Bin/WSFindMP3.dll/WSDL WSGenerator = http://xmlrad.com/WSGeneratorBin/WSGenerator.dll/WSDL WorldTimeService = http://ws.digiposs.com/WorldTime.jws?wsdl XEMBL = http://www.ebi.ac.uk/xembl/XEMBL.wsdl XMethodsFilesystemService = http://www.xmethods.net/sd/2001/XMethodsFilesystemService.wsdl YIM Service = http://www.scdi.org/~avernet/webservice/yim.wsdl YahooUserPingService = http://www.allesta.net:51110/webservices/wsdl/YahooUserPingService.xml convert = http://www.cosme.nu/services/convert.php?wsdl dns = http://www.cosme.nu/services/dns.php?wsdl eBayWatcherService = http://www.xmethods.net/sd/2001/EBayWatcherService.wsdl finnwords = http://www.nickhodge.com/nhodge/finnwords/finnwords.wsdl pop = http://www.cosme.nu/services/pop.php?wsdl #simple types ABA = http://www.webservicex.net/aba.asmx?WSDL AmazonBox = http://www.xmlme.com/WSAmazonBox.asmx?WSDL AustralianPostCode = http://www.webservicex.net/AustralianPostCode.asmx?WSDL Autoloan = http://upload.eraserver.net/circle24/autoloan.asmx?wsdl BNPrice = http://www.abundanttech.com/webservices/bnprice/bnprice.wsdl BankCode = http://appserver.pepperzak.net/bankcode/BankCodeEJBHome/wsdl.jsp BarCode = http://www.webservicex.net/barcode.asmx?WSDL BibleWebservice = http://www.webservicex.net/BibleWebservice.asmx?wsdl Braille = http://www.webservicex.net/braille.asmx?WSDL CEqImage = http://www.quisque.com/fr/techno/eqimage/eqimage.asmx?WSDL CFRSearch = http://www.oakleaf.ws/cfrsearchws/cfrsearchws.asmx?wsdl CFRSect = http://www.oakleaf.ws/cfrsectws/cfrsectws.asmx?wsdl CFRToc = http://www.oakleaf.ws/cfrtocws/cfrtocws.asmx?wsdl CodeGenerator = http://www.esynaps.com/webservices/codegenerator.asmx?WSDL CreditCardValidator = http://www.richsolutions.com/RichPayments/RichCardValidator.asmx?WSDL CurrencyConvertor = http://www.webservicex.net/CurrencyConvertor.asmx?wsdl Currencyws = http://glkev.webs.innerhost.com/glkev_ws/Currencyws.asmx?WSDL DailyDilbert = http://www.esynaps.com/WebServices/DailyDiblert.asmx?WSDL DotnetDailyFact = http://www.xmlme.com/WSDailyNet.asmx?WSDL EMBLNucleotideSequenceWebService = http://www.webservicex.net/EMBLNucleotideSequenceWebService.asmx?wsdl ElectronicProductsFinder = http://www.xmlme.com/WSElectronics.asmx?WSDL EncryptionWS = http://test.mapfrepr.net/Encryption/Encryption.asmx?WSDL Fax = http://ws.acrosscommunications.com/Fax.asmx?WSDL FinanceService = http://www.webservicex.net/FinanceService.asmx?WSDL Fortune = http://adrianr.dyndns.org/Fortune/Fortune.wsdl GetCustomNews = http://www.xmlme.com/WSCustNews.asmx?WSDL GetLocalTime = http://services.develop.co.za/GetLocalTime.asmx?WSDL GlobalWeather = http://www.webservicex.net/globalweather.asmx?WSDL HCPCS = http://www.webservicex.net/hcpcs.asmx?WSDL IBANFunctions = http://www.bitounis.com/IBAN/IBANFuncs.asmx?WSDL ICD10 = http://www.webservicex.net/icd10.asmx?WSDL ICD9 = http://www.webservicex.net/icd9.asmx?WSDL ICD9Drug = http://www.webservicex.net/icd9drug.asmx?WSDL ICD9ToICD10 = http://www.webservicex.net/icd9toicd10.asmx?WSDL ICQ = http://ws.acrosscommunications.com/ICQ.asmx?WSDL ISearchSwedishPersonservice = http://www.marotz.se/scripts/searchperson.exe/wsdl/ISearchSwedishPerson InstantMessageAlert = http://www.bindingpoint.com/ws/imalert/imalert.asmx?wsdl LocalTime = http://www.ripedev.com/webservices/LocalTime.asmx?WSDL MSProxy = http://www.esynaps.com/WebServices/MsProxy.asmx?WSDL MXChecker = http://beta2.eraserver.net/webservices/mxchecker/mxchecker.asmx?WSDL NAICS = http://www.webservicex.net/NAICS.asmx?wsdl NFLNews = http://www.esynaps.com/WebServices/NFLNews.asmx?WSDL NumPager = http://ws.acrosscommunications.com/NumPager.asmx?WSDL OTNNews = http://otn.oracle.com/ws/otnnews?WSDL Paracite = http://paracite.ecs.soton.ac.uk/paracite.wsdl Phone = http://ws.acrosscommunications.com/Phone.asmx?WSDL Puki = http://www.barnaland.is/dev/puki.asmx?WSDL QueryIP = http://ws.cdyne.com/whoisforip/queryip.asmx?wsdl Quotes = http://www.seshakiran.com/QuoteService/QuotesService.asmx?wsdl QuranVerse = http://aspnet.lamaan.com/webservices/QuranVerse.asmx?WSDL RSAFuncs = http://www.bitounis.com/RSAFunctions/RSAFuncs.asmx?WSDL RSStoHTML = http://www.webservicex.net/RssToHTML.asmx?WSDL #SMS = http://ws.acrosscommunications.com/SMS.asmx?WSDL #SMS_1 = http://www.barnaland.is/dev/sms.asmx?WSDL SQLDataSoap = http://www.SoapClient.com/xml/SQLDataSoap.wsdl SecureXML = http://www.securexml.net/securexml/securexml.wsdl SendSMSWorld = http://www.webservicex.net/sendsmsworld.asmx?WSDL Shakespeare = http://www.xmlme.com/WSShakespeare.asmx?WSDL SportingGoodsFinder = http://www.xmlme.com/WSSportingGoods.asmx?WSDL StockQuote = http://www.webservicex.net/stockquote.asmx?WSDL StockQuotes = http://www.gama-system.com/webservices/stockquotes.asmx?wsdl TAP = http://ws.acrosscommunications.com/TAP.asmx?WSDL UDDIBusinessFinder = http://www.webservicex.net/UDDIBusinessFinder.asmx?WSDL UKLocation = http://www.webservicex.net/uklocation.asmx?WSDL UNSPSCConvert = http://www.codemechanisms.co.uk/WebServices/UNSPSC.asmx?WSDL USWeather = http://www.webservicex.net/usweather.asmx?WSDL ValidateEmail = http://www.webservicex.net/ValidateEmail.asmx?WSDL VideoGamesFinder = http://www.xmlme.com/WSVideoGames.asmx?WSDL WebChart = http://www.gxchart.com/webchart.wsdl WebSearchWS = http://www.esynaps.com/WebServices/SearchWS.asmx?WSDL WhoIS = http://ws.cdyne.com/whoisquery/whois.asmx?wsdl WhoIsService = http://www.esynaps.com/WebServices/WhoIsService.asmx?WSDL XmlDailyFact = http://www.xmlme.com/WSDailyXml.asmx?WSDL XmlTracking = http://www.baxglobal.com/xmltracking/xmltracking.asmx?wsdl XreOnline = http://www.codecube.net/services/xreonline.asmx?WSDL ZipCodesService = http://webservices.instantlogic.com/zipcodes.ils?wsdl airport = http://www.webservicex.net/airport.asmx?wsdl bork = http://www.x-ws.de/cgi-bin/bork/service.wsdl chat = http://www.x-ws.de/cgi-bin/eliza/chat.wsdl country = http://www.webservicex.net/country.asmx?wsdl eSynapsFeed = http://www.esynaps.com/WebServices/eSynapsFeed.asmx?WSDL eSynapsSerach = http://www.esynaps.com/WebServices/eSynapsSearch.asmx?WSDL engtoarabic = http://www.dl-me.com/etoaservice/engtoarabic.asmx?WSDL fWArticleService = http://www.framewerks.com/WebServices/fWArticleService/fwArticles.asmx?WSDL fax = http://www.webservicex.net/fax.asmx?wsdl foxcentral = http://www.foxcentral.net/foxcentral.wsdl iifws = http://www.inkostar.com/wsdl/iifws/iifws.wsdl imstatus = http://www.x-ws.de/cgi-bin/msn/imstatus.wsdl periodictable = http://www.webservicex.net/periodictable.asmx?wsdl piglatin = http://www.aspxpressway.com/maincontent/webservices/piglatin.asmx?wsdl unitext = http://www.dl-me.com/webservices/unitext.asmx?wsdl wwhelpservice = http://www.west-wind.com/wconnect/soap/wwhelpservice.wsdl xmlserver = http://xml.redcoal.net/SMSSOAP/xmlserver.wsdl # complex types AddFinderService = http://www.lixusnet.com/lixusnet/AddFinder.jws?wsdl AddressFinder = http://arcweb.esri.com/services/v2/AddressFinder.wsdl AddressLookup = http://ws.cdyne.com/psaddress/addresslookup.asmx?wsdl AmazonQuery = http://majordojo.com/amazon_query/amazon_query.wsdl AmazonSearch = http://soap.amazon.com/schemas/AmazonWebServices.wsdl BondService = http://www.financialwebservices.ltd.uk/axis/services/bond?wsdl BusinessNews = http://glkev.webs.innerhost.com/glkev_ws/businessnews.asmx?WSDL CarRentalQuotesService = http://wavendon.dsdata.co.uk/axis/services/CarRentalQuotes?wsdl CupScores = http://scores.serviceobjects.com/CupScores.asmx?WSDL DOTSAddressValidate = http://ws2.serviceobjects.net/av/AddressValidate.asmx?WSDL DOTSDomainSpy = http://ws2.serviceobjects.net/ds/domainspy.asmx?WSDL DOTSEmailValidate = http://ws2.serviceobjects.net/ev/EmailValidate.asmx?WSDL DOTSFastQuote = http://ws2.serviceobjects.net/sq/FastQuote.asmx?WSDL DOTSFastTax = http://ws2.serviceobjects.net/ft/FastTax.asmx?WSDL DOTSFastWeather = http://ws2.serviceobjects.net/fw/FastWeather.asmx?WSDL DOTSGeoCash = http://ws2.serviceobjects.net/gc/GeoCash.asmx?WSDL DOTSGeoPhone = http://ws2.serviceobjects.net/gp/GeoPhone.asmx?WSDL DOTSGeoPinPoint = http://ws2.serviceobjects.net/gpp/GeoPinPoint.asmx?WSDL DOTSLotteryNumbers = http://ws2.serviceobjects.net/ln/lotterynumbers.asmx?WSDL DOTSPackageTracking = http://ws2.serviceobjects.net/pt/PackTrack.asmx?WSDL DOTSPatentOffice = http://ws2.serviceobjects.net/uspo/USPatentOffice.asmx?WSDL DOTSPhoneAppend = http://ws2.serviceobjects.net/pa/phoneappend.asmx?wsdl DOTSShippingComparison = http://ws2.serviceobjects.net/pc/packcost.asmx?WSDL DOTSUPC = http://ws2.serviceobjects.net/upc/UPC.asmx?WSDL DOTSYellowPages = http://ws2.serviceobjects.net/yp/YellowPages.asmx?WSDL Dispenser = http://www.blackstoneonline.com/webservices/dispenser.xml DocConverterService = http://telecommerce.danet.de/axis/services/DocConverterServicePort?wsdl FOPService = http://live.capescience.com/wsdl/FOPService.wsdl FedRoutingDirectoryService = http://demo.soapam.com/services/FedEpayDirectory/FedEpayDirectoryService.wsdl GMChart = http://service.graphmagic.com/GMService/GraphMagic.asmx?wsdl GeoPlaces = http://www.codebump.com/services/placelookup.asmx?wsdl GlobalWeather = http://live.capescience.com/wsdl/GlobalWeather.wsdl GoogleSearch = http://api.google.com/GoogleSearch.wsdl HPcatalogService = http://www.lixusnet.com/lixusnet/HPcatalog.jws?wsdl HTMLeMail = http://www.framewerks.com/WebServices/HTMLeMail/HTMLeMail.asmx?WSDL HelpfulFunctions = http://www.framewerks.com/WebServices/helpfulfunctions/helpfulfunctions.asmx?WSDL HistoricalStockQuotes = http://glkev.webs.innerhost.com/glkev_ws/HistoricalStockQuotes.asmx?WSDL Horoscope = http://www.swanandmokashi.com/HomePage/WebServices/Horoscope.asmx?WSDL IACHSOAPservice = http://soap.achchex.com/exec/achsoap.dll/wsdl/IACHSOAP IP2Geo = http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl ISoapFindMP3service = http://www.agnisoft.com/soap/mssoapmp3search.xml ITeeChartservice = http://www.berneda.com/scripts/TeeChartSOAP.exe/wsdl/ITeeChart IZPOP3service = http://www.zanetti-dev.com/scripts/zpop3ws.exe/wsdl/IZPOP3 LookyBookService = http://www.winisp.net/cheeso/books/books.asmx?WSDL MailLocate = http://www.maillocate.com/soap/index.php?wsdl NavBarServer = http://ws.xara.com/navbar/navbar.wsdl Online Messenger Service = http://www.nims.nl/soap/oms.wsdl OnlineMessengerService = http://www.nims.nl/soap/oms2.wsdl Option_x0020_Pricing_x0020_Calculator = http://www.indobiz.com/OptionPricing.asmx?WSDL PersonLookup = http://www.barnaland.is/dev/personlookup.asmx?WSDL Phonebook = http://www.barnaland.is/dev/phonebook.asmx?WSDL PopulationWS = http://www.abundanttech.com/webservices/population/population.wsdl QueryInterfaceService = http://www.transactionalweb.com/SOAP/globalskilocator.wsdl QuizService = http://java.rus.uni-stuttgart.de/quiz/quiz.wsdl QuoteOfTheDay = http://www.swanandmokashi.com/HomePage/WebServices/QuoteOfTheDay.asmx?WSDL RateInfoClass = http://www.xeeinc.com/RateInformation/RateInfo.asmx?WSDL RateInfoClass_1 = http://www.xeeinc.com/RateInformation/Rateinfo.asmx?WSDL RecipeService = http://icuisine.net/webservices/RecipeService.asmx?WSDL RenderServer3D = http://ws.xara.com/graphicrender/render3d.wsdl RichPayments = http://www.richsolutions.com/richpayments/richpay.asmx?WSDL SBGGetAirFareQuoteService = http://wavendon.dsdata.co.uk:8080/axis/services/SBGGetAirFareQuote?wsdl SMS = http://www.abctext.com/webservices/SMS.asmx?WSDL SalesRankNPrice = http://www.PerfectXML.NET/WebServices/SalesRankNPrice/BookService.asmx?WSDL SendSMS = http://www.webservicex.net/SendSMS.asmx?WSDL Server = http://addison.ra.cwru.edu/orc/calendar_copy/server.php?wsdl Service = http://www.ejse.com/WeatherService/Service.asmx?WSDL SpamKillerService = http://wavendon.dsdata.co.uk/axis/services/SpamKiller?wsdl StockQuotes = http://www.swanandmokashi.com/HomePage/WebServices/StockQuotes.asmx?WSDL TWSFissionDotNet = http://www.sidespace.com/ws/fission/fissiondotnet.php?wsdl TerraService = http://terraservice.net/TerraService.asmx?WSDL Transform = http://transform.dataconcert.com/transform.wsdl UPSTracking = http://glkev.webs.innerhost.com/glkev_ws/UPSTracking.asmx?WSDL URLjr_Library = http://urljr.com/soap WeatherFetcher = http://glkev.webs.innerhost.com/glkev_ws/WeatherFetcher.asmx?WSDL WeatherService = http://www.hkwizard.com/WeatherService.asmx?wsdl WebServiceOfTheDay = http://www.webserviceoftheday.com/ws/soap/wsotd.asmx?wsdl WeblogsSubscriber = http://soap.4s4c.com/weblogs/subscribe.wsdl WhoIs = http://ws2.serviceobjects.net/whi/WhoIs.asmx?WSDL WhoisDataService = http://wavendon.dsdata.co.uk/axis/services/WhoisData?wsdl WolframSearchService = http://webservices.wolfram.com/services/SearchServices/WolframSearch.wsdl XMethodsQuery = http://www.xmethods.net/wsdl/query.wsdl XigniteEdgar = http://www.xignite.com/xEdgar.asmx?WSDL XigniteNews = http://www.xignite.com/xnews.asmx?WSDL XigniteOptions = http://www.xignite.com/xoptions.asmx?WSDL XigniteQuotes = http://www.xignite.com/xquotes.asmx?WSDL XigniteRealTime = http://www.xignite.com/xrealtime.asmx?WSDL XigniteRetirement = http://www.xignite.com/xretirement.asmx?WSDL XigniteSecurity = http://www.xignite.com/xsecurity.asmx?WSDL XigniteSimulation = http://www.xignite.com/xsimulation.asmx?WSDL XigniteStatistics = http://www.xignite.com/xstatistics.asmx?WSDL XigniteSurvey = http://www.xignite.com/xSurvey.asmx?WSDL XigniteWorldNews = http://www.xignite.com/xworldnews.asmx?WSDL YourHost = http://www.esynaps.com/webservices/YourHostInfo.asmx?WSDL Zip2Geo = http://ws.cdyne.com/ziptogeo/zip2geo.asmx?wsdl ZipCode = http://www.ripedev.com/webservices/ZipCode.asmx?WSDL ZipCodeResolver = http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL ZipCodes = http://www.codebump.com/services/zipcodelookup.asmx?wsdl ZipcodeLookupService = http://www.winisp.net/cheeso/zips/ZipService.asmx?WSDL certServices = http://soapclient.com/xml/certService.wsdl check = http://ws.cdyne.com/SpellChecker/check.asmx?wsdl com.systinet.demo.freedb.FreeDBService = http://soap.systinet.net/demos/FreeDB/wsdl com.systinet.demo.ftp.FTPService = http://soap.systinet.net/demos/FTPService/wsdl com.systinet.demo.newsfeed.version1.NewsfeedService = http://soap.systinet.net/demos/Newsfeed/wsdl com.systinet.demo.rpmfind.RpmService = http://soap.systinet.net/demos/RpmFinder/wsdl com.systinet.demo.search.w3c.W3CSearchService = http://soap.systinet.net/demos/W3CSearch/wsdl com.systinet.demo.search.zvon.ZVONSearchService = http://soap.systinet.net/demos/ZVONSearch/wsdl dic2 = http://www.dl-me.com/webservices/dic2.asmx?WSDL eSynapsMonitor = http://www.esynaps.com/WebServices/eSynapsMonitor.wsdl ev = http://ws.cdyne.com/emailverify/ev.asmx?wsdl getQuakeDataService = http://webservices.tei.or.th/getQuakeData.cfc?wsdl getSessionReport = http://sandbox.grandcentral.com/services/reports?WSDL pwspNoCentrbankCurRates = http://server1.pointwsp.net/ws/finance/currency.asmx?WSDL sekeywordService = http://www.aspiringgeek.com/cfc/keyword/sekeyword.cfc?wsdl threatService = http://www.boyzoid.com/threat.cfc?wsdl xmethods_gcd = http://samples.bowstreet.com/bowstreet5/webengine/xmethods/gcd/Action!getWSDL ########################################################################## # SECTION [reader_errors] - # unable to load file ########################################################################## [reader_errors] BusinessFinder(UDDI)-WebService = http://www.esynaps.com/WebServices/BusinessList.asmx?WSDL ColdFusionTip-of-the-Day = http://www.forta.com/cf/tips/syndicate.cfc?wsdl ComputerDictionarySearch = http://dotnet.cyberthink.net/computerdictionary/computerdictionary.asmx?wsdl DynamicChartingofXMLData = http://webservices.isitedesign.com/ws/chartWS.cfc?wsdl EmailServices = http://soap.einsteinware.com/email/emailservices.asmx?WSDL ExpressionEvaluator = http://www.onepercentsoftware.com/axis/services/EvaluationService?wsdl FonttoGraphic = http://ws.cdyne.com/FontToGraphic/ftg.asmx?wsdl HolidayInformation = http://wsdl.wsdlfeeds.com/holidays.cfc?wsdl Html2Xml = http://www.dev1.eraserver.net/REFLECTIONIT/Html2xml.asmx?WSDL HuZip = http://www.c6.hu/ws/huzip.wsdl HuarananetPresstechnologynews = http://www22.brinkster.com/horaciovallejo/netpress1.asmx?wsdl InfosVille = http://www.dotnetisp.com/webservices/dotnetisp/ville.asmx?WSDL ItalianFiscalCode = http://www.pinellus.com/cfc/Cod_fiscale.cfc?wsdl LinearSystemsSolver = http://www.cs.fsu.edu/~engelen/lu.wsdl LiveScoreService = http://www.freshscore.com/service/FreshScoreLiveScores.asmx?WSDL LogFileParser = http://www.bitounis.com/W3CParser/LogFileParser.asmx?WSDL MP3.comMusicCharts = http://webservices.mp3.com/MP3Charts.wsdl MachNumberWebService = http://www.cgi101.com/~msmithso/wsdl/mach.wsdl MagicSquares = http://www.cs.fsu.edu/~engelen/magic.wsdl MysicSearchEngine = http://mysic.com/Webservices/MysicSearchEngine.asmx?WSDL NASCARWinstonCupStatistics = http://soap.einsteinware.com/nascar/nascardataservice.asmx?WSDL OpenDirectoryProject = http://wsdl.wsdlfeeds.com/odp.cfc?wsdl SchemaWebWebService = http://www.schemaweb.info/webservices/soap/SchemaWebSoap.asmx?wsdl SlashdotNewsFeed = http://webservices.isitedesign.com/ws/slashdotnews.cfc?wsdl SpamKiller = http://soap.prowizorka.com/spam/wsdl/ISpamCheck SpellCheck = http://www.worldwidedesktop.com/spellcheck/spellcheckservice.asmx?wsdl SpellChecker = http://wsdl.wsdlfeeds.com/spell.cfc?wsdl USAZipcodeInformation = http://www.webservicex.net/uszip.asmx?WSDL WebEvents = http://www.bitounis.com/WebEvents/events.asmx?WSDL WebRTF2HTML = http://www.infoaccelerator.net/cfc/rtf2html.cfc?WSDL cp2ville = http://www.dotnetisp.com/webservices/dotnetisp/codepostal.asmx?WSDL src2html = http://www.dotnetisp.com/webservices/dotnetisp/src2html.asmx?WSDL ZSI-2.1-a1/ZSI/wstools/test/schema.tar.gz0000644000175100017510000020641207723230141016247 0ustar zsizsi‹üK?schema.tarìýÛ’I²(ŠñÈd2cÝ’L2½I¦\ÕÇNÏ,ÈÄ­ˆSÍÙl6»‡ÚÍËb±gÖÖ^ÛhY…¬*ìF5H€ÍZgé;ô2éô$ÓOÈôÇô$ÓƒLŠˆ¼ÅÅ="223gØ$€È¿¦×ÉMÜ{ÔæÓïû“шüÝïOÆCáïüyÔŸL¢h2‡“ñ£~Æ£GÁ¨U¨òg›nâu<:_}NÖ׫K¬é÷}Òlý/Vë¤5"¨·þ¤]8…Ãnýwñðë/ã«ä&Ynü’B½õ'߇£q4éÖ²þÕ??ݮ֛O›»ÛäéÕïélá0F?ì÷ÇÃ!²þQN"qý£A}ﳞ¯|ýOÿüåf©¥óÕòûãðiÿ8H–«Ù|yõýñ¯zrrüççGG§tí§³är¾œoHÓ4XÆ7É÷Çï®Òù›’XŽå!è½J6oIëô6¾ ¯\o6·Ó^ou•ÆO¯«ómútµ¾’IꊀºL§›ejÝIþ"ÚUÙY¶Ò§ä§tß²iƒÞ1ÞÁ—tV¾ÿûï¿?ý}À^‹úý°÷Ïo~9c]jÞ§™ ŸtP4Ì0®ÖóÙåj½½a}, ä§°AüÿÝÏg¯q_ x±ê6øÛÙ¿¼ú²I–”˜R¼{:BdÚy³)”¨›{Là¸N<’žf_³®ÈÇ'ôwÝ2ÌêÍ6MÖŸçÉñ&F§iAWdc‘·OÿáÉ“àý>Á“'Ï‹®5ÏÏd¢ÁY6™àõ åõ©®={¸®[‚zÎ «‹xÃøÒÓ§=òJæì?ÙQÄc~©ðûmÐ{^utÏëAŸä¬5/ÂN׃ÿi†%öŸSÂö¦Yûãïþ¸{ÖüؾE ¥ß7|r–ýqÏÛíÍy²V—ÅLƒ‹ÕÍí"ùPŒk—»øè²æP*ÌÏø ÌÄW †|ú;‡¼Œ"’¿o ËNxœ²’켿%ëïÅçx¾ˆÏIÑñ1›ô÷Çô…9YÝžU7?&·‹Õ]2kÖË‹‹ÍüscHbÛ^N{º²o9üs;®}büÛ:¾½MfÁ›$MÉ òu6p¢–‰QÄó|ù9^Ìgg›x“üo›ÆÓ„wL_Ëm¡ö $¿%‘wþÚËÕ’ˆ8•& É'8SÒ'=¨¦ÒBKÝAD€c$Y„¬À£’ô;´[¡1â¿ÄËÙ")̦•}%Ï‹ŸÈ `/~ȇ}~d3ßä¸!B¦~Þ½ü´Z?,¬Úι%Ì2æH¶×¤WÛ9˜mŽ×Yò5bV™µªmùˆ ØiPWÀßé»]þ¶\ý¾ÌV;cUY²Èkûrʲç¨ú5»ßÐè¨WÞŽîûÒNž\H«ME-B¡é&—Õãš0t“/öém¼.(Žü“ü½IÖD`Îi1£2N¶a«zÚË;gûU3’ÀjU¾-©Ÿ^~p6˜c&n¨£š†l2Y± 3’–ËÏ×rtù°2ÎXÏç]Ƭ1cà˜q˜³zDgm:ßÜÆÕͼàÍŽ‰w]²ïÆ’[q]4„BD¦zðäü\F³„IüX4®¤rµ¬;6zëXÔýL¢!( úÛ¸k—íé‹§%Píê}þ#Á>1fi.[¼]mæ—óL}¶Úްïó-õózµ½­Öru›¬YSÃ}¾¼Ý–C=„2&è9*ª¤VÛ¶»|×ãg¥Ø]¶k±½S¨]…Ñð-Ö{`}ç[C×7CµÚ΢ó|Šdù~$[Sa>„Ø9Ö®¢”ËŵXn@} ]sA‚^ø½Îꋇ¼AŒ8|:°Y%í…X%D(W ùݼJØñl}•°Î«C®è[=Lë€Ag*–D€¶0“.§¥ÁŽê‘Bñ ÓK•6|ÁŽSÚo$mVñTzÜ0†¼z3_¾»¸Ø®‰l¢mâ/æ6ÛM|>_Ì7wß³/ð!W3"¾ÐTº\¤hÃå|±à›)Ú¼âÁ¿>í‰rV¡X;:íÉîCÏîÛó©{ècöÿË·ÉSGç¿G&ÿ¿~È|þÿ¿h0wþ»x,ýÿNž®~ …+Õ±µÓçóVus>_f [Žš·Oüðž«þIÜ~)zfæpL²­÷ü4GˆòRt9eÀ”3•Þ}÷âýÙ/Çèm˜ôL'²-Ÿ_ÄÑ€VV½£úà.ýfý¬¢Um¸„t °žÉfyÐ;¤irYø4)äe³á…Y‰]>˜eÈëeLN˜¾ø×ùjÁ–mk5Ò›REg mk7ÕðÙ…·¶ãùáæQ€V–LÐì:¹Øü5^lu\AmfÕÿûx½™Ç‹Ÿâùb»Æû‡šÝÛ™Eï™oÞ%÷Ù1¯`^‡,ny–´ÁšÅ¿‡ºXcàî.„¥˜o=P—ê£×‘ؽ“˜j Æ;ç-Æ.Dxx +Èù³#¬¯Š°Ö™'ÈÇd}Cnô‡’K‚q/ô…vþ`ÈŒ›ÚÇùMòëòâ:^^iÎý ÷& ͲƒÏWÉúz0‹Ü®,ÑöÒª›ðÅ%é ¥ žõý`–þP÷waº:d³vü_®`½ýw0Іrþ¯h2ìì¿;ylí¿v鿜“ÁÔµýÖIúä3¥U³|[’M¹¤ sOºå’§^^µz™zºdYԖɲ€ã»K‘åê6Rd¹ï¿.÷UmøºÜW]î«.÷UùÖ¾dåÀ1Òå¾êr_u¹¯ö³]î«.÷ÿ°Ó Ë}Õå¾Òߣ¾’ÜWX¦«üe.¥OãÜW¦LWæ!s_i3]ÙŒêûÊ*Ó• ’­ò@i3]9ÌØ&”U¦+—[æ¾2dºr˜µ]î+ËLWV3/¸C³cå s_Y¦»*|R™•ÌWî+»tW†¡»ÜWÔ´w»¬WÚЮlÛIiQ–iølzV4zM,–7×BÒîÊf%UÊ2úÕ€ïØ¯ÊˆQ¿ÁˆÂ–e†S½p9¾3q eèÊh ûë ãœK¨"¯P ¦ª/²ä¬\B3ð Íp  9t³^Ø/Ù+Ûj„¦ÓŠ^å$F5Oy@Ôý6vÍ#VÂ2v„EY¿‰&S‘ÆÑ°€cR 3ȉ&«‘Æ'±äĉÀ ŒFÆ7„k Z¬{Ü„‘¤J£"ü{ì•3Ž£vø÷ØS˜? |ìÆ2Q°†Ó—ñŽ‚“ ÃåJØÜXk€7šbqslxx] ÛÈ+ѧoò¬[ÀiâñJðÆ^Á›LÕð<ù\â÷Jh&^¡¡üT‰æS*ïWÂãÆR1xžMè? 0>°„§‰Ì«ž{}¹eâ̬ë…"GʈWbSøL9‹Wà™2ÉÃ"‡ÊÈëþÛ9TF^·ùhâçLyÝf—‚‘×Í>zf³¹FÎÚ:8R{èC©¡1%s ußÛ- ¬—Kººüû’ý£f²äMö4“ý›HgHCckcÐD^æl õ:Ùv—é34á²V_Îã™?Êﻦh®6ë>TV: ›mƒ°Î~Ô]5Ûa“ë ÔÏ ŒÇó• °S7œTKöáP“eÚ`’©¦1ôGü£&‰©+ˆ\ÕQên€:Ê(­Mn7¡ÊÔI£ pâäñŽÈ­aòlšEðmaâ×xpÒ/†Cn '^M'¡¿“ùÄM)–­_d#ûž8›#¢1ZM? ï ÄÓäʧÏdŒŽPÓÄëmn2™j£å+”>B²„± €<±ÒU8_áÜBp1Š e¯ ÕD1 T„ Ñ“WãÜdÐ =9Þpp.5±2ÛMü˜ízeá¹`”CI(ƒ¹÷¹Óÿ%ת Dˆ%%€j`­!v£ŠÙK@X•ºèêDòS'þûK:sÃPÿa<ê+ñߣI¿‹ÿÞÅcÿÝE3vÑŒ]4cÍèLŒ]4cÍØE3úÁªíœ»hFo˜í¢»hFþé¢#šï+<„Éû¾Á5{øûÿ’Skõ<ŽÑïû“Ñ»ÿÓG¼ÿ‡ã¨> Fa@Ÿ¯üþ®?ÿ¡AíOúô?ýá`"éÂÑxÐévñ¸Ô³U±¨q‘ªX&2@Oc›þðj¾3T g¶)Á¦ÂÆìZGb*χ¯|¶Ûÿ®šßì1ÕÿÊü? “I·ÿwñØîÿšº_`{ {]«†Þ~,²\ \Žo6ëùùvCïÂ7?&Ì´øýñß·ñ‚t›.Q¶Ì…D¤Ýó2²8à ¹ðŸ‡ðJr¦b ü¸º_”8Ï9‘SÿVf¯”ºú×JAY½½ÙA}lQº4ôø¡N{’pn?îRqZ®fþJn#fMrÿ‰Òežº™zÌ×dõz „Ë Nî{ÿÝ÷ƒòÿÿr“~Šgñí&Ys&À+IÐÀÿ'ýq(ñÿÁxuü{ýßÿÝ›³}d,·–YP=,ƒÈ‹¢#7Šcúf®?Ù¤¹mMœ€øÛNºß£*£­³ñ>ÿm¥Ë.ê‡uÖ«›Û,ô©8êÆâ Iyw¢¢Ù:6TÂhÙa÷S|±Y­ï²3¬²7¦äØ[^¹˜«‰¨šXln•ûvuæ×ÀÎêVû"òŽqPìe†ºw„lZZóZ€¯SBnò~9­—«%á̄þ\Äizo”QÂã¼PFȉáy¡h¿™¼øëzq–áãžÖ«¹äØÙ“õ.WËŠä‹yË”GRF(Æe[v°4PY .S—˜*c¾=ÚùM‘ö ê]ôŸ­×}9cquœÕ­ë$4Ìauë<Ž™êgPîi·iTœW;—²™ã„TΣŸUI¹n³ªØ”vVe3ÇY©ûKž•ä}, Ü¥±Ñ/9JIÉ1²c|¹b~ìekŠk5 Ù : ¤=¦‡AÞ4V ȼStÀ To‘|RBÁT®ƒ¡X"À3ûkÓˆ]OMý“!P¯ÿ‰Âq8õ?ÃI§ÿÙÉãEÿÓ@+P·ðוñª§»øjô<»Àtƒìt9.§ÓåtºœN—³º@s£^‹Ýu9Íi˜ºUsS{¸.×ÜÔI—ƒhnjÎŨË1hnêÎʤËA475geÔå47æY™µ8@&_‚†æƒSwžmÚ7Éã VДoÀö³M즎¡MÜ`RyÐ4Ô01Øf™¶œôÓ“Øf‘®9q“ö‰&wƒ÷6²­ÉÄG˜ÊÊ6¥x͉›+ œ˜ 4I©"à™±¬€×œ®a¿¢¡×Faè'hè5£w5K ê˜zƒf`“ž$t®dà#ß{d—ï½Qá  T‡e¾÷v+ax«×á7ß{ä)ß»c‰ ,ŸùÞKi ™€"ùÞ#¯ù #ßùÞ#¯©Ã¢†ùÞ#¯  £ÆùÞ#¯) £ÆùÞ#¯²ÁÀ*ßûà~󽇖ùÞC¿ùÞCÛ|ï¡×ý¶”ï=ôºÍCOùÞS“bP5Ì÷zÝì¡U¾w÷¢ezq ÷w )Î=”mþrËKÞp’2“û¸ß™¿ ‰_~¿M‰_‡^ïMC‰_‡-$~Z%~îIâ×AÝį¿‰_µ¿¼²õA+‰_~¿¬¿ö#ñë fâ×ßįƒº‰_^5ƒV¿¼'~X%~Üwâ×.H­Ä&—ÿO=ë¬ü¿òì³®i LñßáHñÿ ûÿ×Nž{öÿê¥E™ðš~`„›J±~i¥E¢Ð<×Ðû>¼º§ñƒÊWéüÿŧÜië6ûPG#`ºÿG9ÿÛx2uòß.;ùïH@ui‚BŒ#\%`­¦sV PM¬°Õ³r@ Ú2+ UÚ•‘uº¦ØK€îkjÖ$\5W%|Ó…!{zjðÿùò77M°‘ÿäü¿£°‹ÿÝÍã“ÿùJùþ7æp]™óSJ՞΀oކs€¬¦:FúŽý“&Û?ÌÇJÿ+ný1ôü? é¿Eýo4ìò?ïä¹oûŸÄv] €õuÉ ~bj'‹å{9TCÏy3íL5ñ)KÈXpÑ_º¹£ÕMf«‹m^úe/S ´vþlêôw œ˜ TýH?Òâ{œÁÐ8õo‹œn™—Nüjvç„È,õóbN/Øq’w›yáøï¾è×2¼Ñ Êø$emœÒß ÚøŒum\h¥Ÿ ZöwðhË\̬\ôs j¼¡Ë^ÖŒZ¹Þ›FãœômFÜé §{›ÞÑ }Ô dôC¹b§ùù¢‘…À8x¢ÍHhœ 0Sh5ô¥ ´bj0Ä€?›Þ¡Ø< {0„Ϧ(Öè É»/¦ÄÍyá`r¯ ;v€'0‹Mót¥c®œTÝb˜¼ íþà‘*P¿6°Ú.úH”ûÚ9e¬£—µ/z{PK†9+‡DÞ×£áe-mö¬÷E‡º× íôdàí?YÙEÿcÔ«ÿLÚ…Ãñ¸ßÕÞÅ£®?ïç×°ðsþÔ«ÿLÖ?êItö¿<í׿é©úÏÅ~©Sÿ™󸫝ÿœáävMOÀÍpaÿÇý,ÿ‡á¸Ûÿ»x€ýO·{ÍTŠ(}$ìomÆûIÊòøæŸV뛦ϥ<"^Ì/çÉì˜Å­Ÿªi!Þ—CÿÈèýUÖK™Ã‹¼¤Ä^‹‘Ô·R| µÜ»(¡Çw|Úå퀭å’ 4σ̃›ùòÝÅÅvMÐLÿMü¥øVqßR7›ùM²ÚnŠžˆ”P½S_E2´¢³Ê‚áz"»x#°ŸÑ/²¾]+ÑüËü2¹¸»XÓ/_Ò/˜%·‹Õý¢¥²ü>Þ\{Xóøb3ÿLðùnyF¶·eþóÕj‘ÄK§N“åìv5_n<Àw/g Ä=Kò©2ãVÖÝbåØÙ:¹šXî<Àu™eáI$O$ñ‹Ž'Ó/8†#RbÞËšÚfçÌÖœÇi5· üåö¦0Œ~¦`„u½úpöúìã«·ùiªí>~xñöì5×ì´Ç—Á]‰€]mÿ& ¿xùñõ__éÁ}ýVle­ÊÖÕÅ´ãéó%a|äç÷ÞiÑã™OþQtZ“_^Wtÿ£ÏÝ[túÁyk7Ûi¯¨¯w¯òŸ*ÿÓóÌüæÖ›ÀxÿÆÒý2uú¿<;Ñÿ_Τ»vt¹ÖUûgP}åºÝþozï/Sþ‡ÉXÖÿM†ýîþ¿“Çóý?ßSòõ¿ ©'¬¡c7>5ìxVŰ œŠa ÄPN³”nÄyOËîÅìnbç’œ`‚´6”,ä6»±sROûNü™ˆ¥ñù"y“Üp׋77×ë$ž½þQ’žô/åià_®–›äËæ/q*Ë ú×s»Ê¯~©õZéøWï­õüj¾äeoz¥µš_½—ÈuY·j2ÂÄMƒÿ——#ÀÄÿ‡¡bÿ »ü¿»y|òÁ›ª¶Xó¶_°´¯Êʯ?ÜqÁVÿÌn¾*û-/‹*¯•¹¦_^O)ýÆçR{õå–&Ò¡^ÐB&Nã‘qÚã’‡ãÖW/gêìfýåVÕ*`m+³¹õý{»<_m—3²ÚVJ¯=¹ˆßÓ£÷ÿñs0ñÿÁ`$ËÿãIÇÿwòxåÿœ/M}ö¿,e~¯åWÓî‚>ˆŽb4Ý8F«å¦ñRÁùö[ò…;—£n§<ßn ƒà¦7e´{Éug\õÝü4Â^ÎkáVZÞÒJ4+y/ÒÊ ª@ÊBŒ¬{ØOÍêa<˜ÿ—/Ý}ŒõŸ²þw<:þ¿‹Ç'ÿÏ|«js~è5¿ŒZ’)Ù€õ¤ò¢¯@⸅d ½û EêŽÎÃóÿxF`Oâ?ûÃ.þsºþì¿\^Ë«Æf`Ãù?•ø°?ìâ¿vò¸ç}A鄞µ’¿ÆÅ[–¥ÀÄöFâ²k«áPöÈÓ­3ë„mžzýÐ;ûñ—<AxÕ]¶7õF4ÍvÅÓª©×É 奙Œ‡T›c¼LQ¼WÃËSÓP|ѾY'L¨q)wWâ½®4pï”×aD¤åšZÙ9%½ôõv3[ý¾¬ßàú\`m.Ùír=“oè“lÛäUÕ(°e‰*èГ*õ§É†fgùL•ŒàäQ€hˆ‹nõvC&|àÐ!!ƒëBEÃ-ïóhÆ#ø~íÕ¨n§½|ƒæVPe¥YBœ¢ì7{û6^—ÃÇkò÷†œWÇñg7¶’¬ò¾Ÿã£d3p¦D~8~É”yÙÉ®ýhêüê‡LR7# ·e»Íw >+žàœºGg!•zçÄšü _yÕŠeà&'UYGƒ‚¢¤Óyl–Ê©ªn/’€¸b÷di”°WDl(õìAöB…¬0œðÎ9È Ð8–Á—ˆ^T öÄÕ§:/Zc±”á~LJshAúFî)éJ¦¿þåUñ:#(}‚3±¡i¥²16-õòQë­ˆRÝŸÛ”Ø 'ÇÐôüëõ¢<ÜÇ|ÿon 0éÿG²ý7ê¢.þ{'íý?¿ ™®&† ‰ËeÊú ÕÝvºÛÎ~Ývî{s[<ÿw*ôˆ<&þß—ýÿiþ¿Îþ»“§©þ×£;xdoË5ãx.å›m c_€”нü­S)ÍÈÏ{šµT 2²ïÍU›a¼oŠíŸÆÿ–|CýÇñ|‘ÿ‡]ü×NžûàÿÎ5Ùëöw? ß±ÂcaQ’J;ªì;“¢Yó)¨|ÜEIGO¸Ø,êÁkèE³`¡$ªìz±5µBDjD{ì ÊÃCtGçÐÔ94uM;߀ƒ5Tÿý†áú`ºÃY…o ÁMFÃÃ7ŒÁ¦ak…o¨Á5g¥ßÀƒ5̳° Ü0›:Á°ƒeFÓ3¡åkÚ¢˜@~fÒfn‡TŽ^ Ý ¤Qß±&ê°ƒÃfw8~ÔáT¯ä(Ç·Óˆ”P  00GSX;¢S¡”`ü‚5ž¾$)h• ÃM¨%lc7ØPà&SÌš*Á†]KØ&^‰îdú&H±Nc¥-Á;ñ Þ³©j´• ‚¬º%4Ï|Bõ§€W´ðD}¯ð„SÀ&,ÁZKxB¯ðDSyLgfmgFŽ’A8Íí­ð2h‚ õ DÅpÈá1hrf)¨ ¦˜]YZ Üü\Bæv¬eB,ßІ4nG•‰4 q Ë´Å–õ-¯¶˜DFV¬Êz7[52õh0ý¿o“¨‰Ì£"&bÃ#Û&r&c¦Zݼ|Ôèõø%ŒŽ¢ ¾}¢±gu[L$¥ ^¦C(0¸„hØlÛŒÀ0â²÷Q[[¦0a{fmö²išÈlÀ¦9AÇÇvW©,zÖÊ®q“ÕЧouâ8 dõ¬ÿ%‘m-¶„éÇy_ƒä3‘EˆÆëEã¤Ë­Wº~æçfëõÎö§ª«€¼Á_‚R¬ðzãC›M:‹ÒöŽGkÖäΨ8M³Si Ë´Qq[cˆ`¡/aÈiQðÔ'ZÅ[¦Ä§ìz¹6¬Ògˆ2Ä$jž 0•E|µ®_ej Ìþ_YÙšaŠÿËù?ÉöìwõÿvòØÚÿÙÖ$”ŸfYóЧn’Høý«:ŽQ/ì3G€œ£¥x¿‚ƒ®la†½Üræ#¯ u†@½õú¨œ‹µ5Úçs@é³e^ŸŸ††TÙz#®6]µ÷iñæRaå{ò.ºÿƒ„çÿ‹ÕÕ­Óé{ŒúùŸGá0êò?ïâÖ?ÿÛ[(ƒÿßh…rþçaØùÿíä±=ÿ¿PÙØáàÊi©®—Yy@EbÜÓxò$ø¾áŠqŃè—ÕÕÛËËd}6ÿ×D8’Y{͹–­ ê… I‡ÉTú+P¦’½ÙÃzÏ~ èõ¸ÑžÍìg¯x1AXèÁÃñô¶Xųª„Ó‹BÜJw:X«3LãÏÉGš9`îk‚åÖ³Õyf*ߟ׫í-€ãl¡«EÌW–aB®@hc?Y/‰=V¦*qø] C^7;YurC$ŸûÙ:ô¿üé{æú\<ìdÈá×úÃÆüNÈ#~·@?ßë~ñ´ÃrlÿvÉ=±*²øm£ÿvIMµ´4ªbO=Z•1ÔCç6íí8XÎ ÞÔcÞ@_Ôƒ/÷péê“ÏÉ¢no0  Ëo‡wˆü¬1|ÑÝ[Æz>¡¿w9`¸WÈrš3ƒknŸ=F²ì[:ÃÕÍ6“ßþÑï“_”‹‹ôPgç ÷ ^³t4æ ×uKPï(OæÀ}¯ @Ÿš×È,í½L$TH-ÕÞ9È(‹Ñ | ~»sédü Ú9Èt2ƒÌ-Oç ³¦ÿÎA¦sA†îd:™½Ø%5Ô9ÈìkFç ³«ôÖ9Èt2ƒŒ%Õt2ƒLç Ó9Èt2ƒŒƒƒ ï.’}Y¦å߃]áñbhÆ=í[LÅ”ôuUº@ªzË.Š<–B{º\U{:{=—ùeÏ ±h#ÝžÓ”âçxA8=+íªZT9à®êEµRÁ±våÐOE÷ºR T£f%nå0h¬J Ú) dãï§ò× zQ«¡P±G=±¼¿šZ¥ñÐgØUBZrĆ VC´ä£È9ßWï0,Õï` ÄfP„àC9ZÔ&`ýC/'‹]UÛ¡\_>c†~K­ ‡vUm‡^™åpÔÎA3ô[>v8ösÒ +Çb`Mv“§Q’²ª‰D]þ÷]<~ò¿»Ü) 2ÐOÝläÂѨvd›¦íà‹U‚füýZIÜÑ^sÑ£ýùI”¯tÝ4ôhguÊà5HÇujAW]F{jËŒöâ— cérÛû€šöî=·½²aº\÷5áSUîC®ûà’Ý=x<ñ>í+Û½÷ÑÚ£K¾{Ã`å:Ö´Ý™îÆûVv•õ¢xHyߘ0ö<çýÞ,cºâÆë³‡YïÛ\Dìf(ïýýï=m–ýÉ|Ÿ;å¾Ö!徿ŸõqO~ï°8û’ý^EuãÄëàêR¾eæu±»šßg{´@w~sà7Ywi¯wIð»$øÖ¬¢K‚o’ºÄøXâ¸r+¬u¹òíQÖ¥ÏGÓç›×eÔwCY—d¿K²/C %ŽJdŸIöƒ=Ì²ß &¿iö-`i;Ͼ»I´oÈ®3í7ÂM©ömèe¹öíȶ…dûv·œmß}ÓúO·ß|Ó´—oߚѶp߉\½fÜo@·-¤Üo´0­äܯGÆ;Jºß„Ù¶‘u_§K»_¢6{å2 ?ª“ƒßWÚ}#ˆÅOÚ}|t2Ã_Ú}Ýøš›½¿´ûF4÷ä.í>1í] ¾ÃãçÅå•ëé%Ð]/_× tׇ–Ö‘äÍí øP\?x,‚¡ã`h9†r·”ÚS­VJ 3Æ}åˆØ|7¿¶Qϸ„_›— xêxÖhC•®5gÀl±Ú5sZÜÆêRÔZjoe&t ½ÓåpKÂgÐ>ÖÌÁg^Ÿ)õîqÖ³áR:Ô"Ð] ë”"°8²¼TÀ×M¡)@a¸UiVH‹ õ¬^”´Tá‰Þì7ºËõUÊv—û¨ëdd¯­ïDD7O«kµ gÉ=èMh¹|öé@a]¨]6P«õrLàôœ³#ë ºôwå1æJÑ¿.%ý€ƒ:’‚ÞP2‹èÛ[æ`É^Ô; ÖÀ ¸ïô‹ Žx ?eªµ[Cêõ'ò±C‰ º\=Ý“=ºü?çó%ÍÅ‘>m”ýÇ”ÿ' Ãa$çÿ F]þŸ]<~òÿ8¥…èôul>…Ë~“wb™¨~îçjR5/ËJÂðQ#Fïùi>s“gï^¼ÿ!û±pîç&;…kS€§E—éæŽòõÙêb›Ç9Pá’‚lξC§àÙ_a³±«öôã‹‹ ]¸øí™@Áäýbv«Ù]]<[êJŽKÜ‚vØË{Ìä}¯=]jo¼ùˆú[±Ò5kþ¼IÍᦋ¤ïþᬔ¤úÅ—KÖ»¬¦4lºXH¿`•0%°N¨>[)½²׈Øô jABƒ4”NtVÕœnLZeW€š •Ù€51Õr³Y¤âši4®6›Í(@5`¨ÖšMïh‡Í¸¡PlÐäûëèu¯é­ ŒƒW›µ ­ Œ„׎µ /î ¥)kµãÕ¢­ÐŽJ»Úˆj VðLJµÚôÕTúK¯ÞÇRê£6eYr‡ÏÚkžugl·C¸Û@½‡zßp,ýéG•ó@ïžíÜÛîG[¤ZÙ=°±Ç]q·ÂgM±‡ö| X¼g}æDÞ˜È‘Ž»Ur:‡°‚¤Í!¤ç°Nú*qø©/+w_’hY©¸éb=€µE«¨Ç+ß׊¢Å!ýoç¬ã°âe7›Âˆ<š»ÛE³ÛE«Οã¹èvß.Ý£{tþ_¹dS÷/ƒÿW? cÙÿ+ê‡ÿ×.žûôÿJ‹Ú¨îî_9Ëqò7óå&¸IÖõ«€"\5GàVD«Ÿ2ÊY«˜à]Äg2¥Oê@Vœñl¶NÒ”›\:ýbq½J7Ó“þIŸÍ¤X¶´Ç ù+ÿ²ãýöðüÿv½úr×ó?F¿?ìOF#ŒÿÓGäÿápLþ FþAQŸ¯œÿ«ëÏþûé2¾Ø¬Öw^dÃù?'ÒùEƒawþïâ±;ÿ¿9:eñ¼€ùŒ~žR‚z*|µOú:¥>³7È)½¨ `º¬ÓÞ¥’i½Ê³UëZ¥bk•TüæèÈJÁöžb¢Ìn–7/ßàr1!OÞÇ›k0%}1\OÄÅ:‰7ER³f½ø ô~¶!^-g·«yU`Àöíl}¡0ü4_äu3jvA Ølo_.â45½oE j¬…”¹‰uðSvªT± òlÝRµ„ÇA™”îÝz–¬Õ Ä” Ž8J(¤HcÊ#¦1ádÖƒz•ÃŒÕn¥Œ&ÀOÂú÷D”‘É­¤™ÖˆÎJ쑆"m“_1 ä*†äðÔš#åŒðY)4‡jEØPˆÎúöÂ%:§Î–°­QÆÂ«“­¹ GUæK¦Å9x–MºÆ±©^¤³ó™&|WÎg~ru%ë*™)³êUÓÒP£ù :´çšgO Ä7ié厃B´iéÎÕC›±5iåß–‹Ú/ˆ­–j0E´b [†88ÊçQÊ6+É$ýÔ9pN1 šˆŸB›F¿Í¿âÕjßø ·Wïÿ³íÍÍݧL àÇ`¸ÿGÃI_ÖÿOúÝý'õýŸ&{¥$ú"`P’.‰Xl®ãMp±Znâ95¬ˆ ·¹^ÍÒ§AðzÌSÊ@fÁåjMZ&i³‰—d32Âcb{)ŠÒþW—¬°wÈ«ì'J”Éú ñr~EIsÆà Ãý%¾øíîOÁ9á±›kªTfóÙò;rH’›`³ ~_­ æ— d:ØïqüBÁ"¹$ d/{úÍÑ“'ÙÆó¡ò`ÈÚ#½µòCxéj@¤«êtºŒy¾Æ¢êÅpÐ ´v}°?ˆUðêÃz, ˜òw«]ïÛ|Ïþç:ï úöŸQ8töŸ]<Ðú_¥ó]ÚÂp2í?aÜÉ»x¬å?Àäç³×å%è|µžÏˆø·½a‡QyMé¡<è‘ÿÓžyƒÈn ö£zö yú´GþOAbÿ1û†8@ª:ŠT ¡s)’ÊìõÒ?”Ô2îIvñÅo’gw¯ý! '‡wyðá®sHr·×Ä|¨ìÐ’ Ùé›Mö¿h,× Â.ÿÏNž=Òÿ61šÎ}°âFÿ¦Ah- !Žª©vY;`g><´GëÿQ0®ZôÿB9þ+ £IÇÿwñxóÿ‹;žR/#Þp‡ËûWBÜ‘•Ã-mð·³ɯ,dÒ`ÏR¨‘±[®¬4ØŸ]ìô&|}Ÿb¨+‹s÷¹øÚ‘Ñ :cÕh Ü ÉùpttJyRJÁ8Í ôDo4ácY¥ð¼ìw‘ÿ…ÜÈÞ݆%zN/Vt¤/,PŒ«®MÎnr{[’ƒ]ê‹…D¦Ü2wKÕEOîã´Ç–×ËûÔA[…žP÷ °mºŠüOœ¦ÑicÖ‘Û¬¹6å¥3å ]™½œ10_^%/xÕ•4ueâ§ù~%¬º—S1‘ÏÇlÅ_Ó«|^ žÍÿ”K!T†â1X(j_wPäûAFxÇîó®Cp)]ŒCEM&YÐh22™£Ó+(ð”IŽÔÒ%#Hèù3K3Á}ú3ácE,4ûâ/ñr¶HÈ«9Á³ïòŽìƒ ¢¯¶ëâEáûùò7àÛ̹â–i¨Ø¯ùÈ,3´úͫ妔ÿúCr5'ÔœÛÎ)òd=™È5O¥ C•Ýæ\áTNĵ®—m’JSƒÃa‰jÂYÀBstUœ@åòQEŸŒ[ãÈŒxáf¾|wq±]Šzþ)~ß.ÏWÛ%Mùµ+­²ß³/ VJçQø •“Ëž‚tgt~tfO 6 ½Ã¾å0R"‰6¹àæÊìœi>z±õòß‹Á?®nÚ6h• ‡õ}Ú÷+ÝÁÂ¥ô`ƒ™Ðû_ŽúOWt7Sšõ²ÿÿ`Ôïw÷¿]<Íî<«¿Wý_þ.#Ö=Òÿ‰›¨e ´ÇÕéQ-;à=vöŸfŠ@ÿErý‡aÔñÿ<þí?"°SîLˆ^£Áé>íçvœr¨·Kù_ e©9†!þk4ËöŸa¿‹ÿÝͳ?òm¹ß;oÆ7=ð‡Ã­^ª;G&Ýœ9l™'.ò N4Œèá–éIž\PÃåH!¿ºÁˆ’uxËôY>–¨Â+{Ö`°ÌÅŒ+ìOõ.™åðvþ›aß+”ávåÔAÇù{–P…^¡Š¦oâÍÅ5 L€±%ÿÌAy…d0ýÀHEùƒeà–á_sè:f­À2d7úÓ3¡%¼­GMˆXÝ×£PÙà#¯T:ŠÚÙá#7 00~¶øÈ˜Q°†Ó—ñ=“ Ã#ÔJØÜˆ>@M±`5™¡1m%l#¯D7ž²Ð¶¹p𠏼±Wð&S5&N‚ š+¡™x…æd „ÐIà€Av%ýé‹Ù ¦¿rjHBh«hÚ’dê•l=‰¥^¯XD&]-Éx›—´VO°kÞ°‚Í™”Aáaúë2-æMrsN¹á1—¤@CkN¦ðÊŒ(‰H.i*éWnß{=]­¯]E¬(vx€Ó#{9½š,pzÑñ±ãËëZ'­_n«‹ž]'Vg—óm¡^äeƒ³hPÆ<ŸwéŠ=!†‘X–-í¿€쿃PñÿŒ]ý<ûcÿm–ÿpj¼üŸ:¯ o @MšUP+S¶õ …]×K ÖÕƒIxò³÷(–W(ùžbµéY5¤]ÖÖûÊ ÔåÚì6„Î:ÙåÚìrmê›u¹6÷‘Yv®Mfèð°¬´Ÿ³¤úüÁ Ð ¤1[ØŒf²*C 6ãÊv`Å´°?é"»t·>Yd—î¶ãÏ]ºÛ.Ýíár°CKwÛ=ÒS7þ» ûϸ¯Ø&ý.þo'Ïþäÿíâÿ¾‚ø?¤òœUå-ăe0šþ¨6‡½XÎÞ$z­~U×u=+ÚìÆi´®sÝg×Ñf5~]E¡á¥[Ú>vq‚ÃÈ*NpØ„lOµ]œàÐ/e [rTs zÃÀyòTs#,¬±Ç8AGß>4¤a8ñ'èÝÃÏoœ w—¿Fq‚î΀ ¿ì7Žô6 Ç úŽt¶9PÚ 3Æ ††8AïÁ^ú8AïÁ]Þâ„tígPWÝ8ÁÑ ^œ cÈ;š¦`X3NÐ1¬jo!ÐÂ1¼]CR£±·qvÓ÷¾3šÔ ßiâÕIÝðï1ímP•ÛùŽr©û t· ߌíÂwMTTL,Ãw^ÔÁI;·¢Wê<ó¤jð*¯û • ^¥Õah¾ã,†9…ïxÊiRwîU¾HËú__Ò™ûÆü¿Jþ÷pÜÕÜÍckÿiXg©«¬t••´²Ú1áôóÅ‚?ùþøØPŒ…úOäšî{Ë Oíü¿ àMü8™Èù£agÿßÉã?þS47wùß»üï÷‘ÿŒpm®¿W‚»§G+ÿ7Šú¯=ÿ'Âþ`$Ëÿ£.þ7·ú¿÷öO¨ô£ýÅ;²×ÿ ³Hh5ó©\6rü ƒ–—À@µß–¼-»|Dj—½=¿õ.cŸ‚0.h„^RÕ~kN²bÙÙæ‹õbA–nv÷ê kSt ¼q—"£#ã.EF—"£K‘Q'²Koõ²ª.½UÀÞm‰¿;•¦V$[ôuФjÚç?Üý%^Î~Ž;¡ÃƒF›(ü0ÊΦ¥‘”VV»àíêÅlÆT²ñâCr™¬©;}ñ™Ô&Žgõž%õÆm:ÚÙöâ:? 4£(­ê÷~¶‰µŒo\çŠþ—8-\[Í逯vœ8¡ªëx=_ÜýºŒ‹¤kn)²ÌæTÞ×Ý9”6÷ÌõC\?'ë컟â‹Íj}T=q®‘¢fXFr.«_ó‰šùR+‚»æ;˜ úlÊyÝ7ñ—wÛ5AÀvy¾Ú.gÉì8 §Sñí3ò©4¹}Ìþ½(—KHþ¯OøŸS¿H¼š­Mé{\à}Fá¢?-Üœ¡wØ·ÜLž“£M.¸Á™})ÍG/œaóß‹Á?®nÚ6h• ‡õ}Ú©êæÅþZ)þ‹­kÏóýþ°?°úôã¿ÂÑ`ÔŒ<Ã>_yü¸þ›Õ­¯ÚOô1Õÿ «.Çÿ‘o»ø¿]<¶ñ_èy`εXoSA XÒ”KXŠÒYÝ q]´âÄÀ†ÂœÔn…P'öçõ—} D>qc&£@I]rAPÖ½Fí£H‰k?@€X]üÁb«[Ef«¼`¬À!cýpacj· v¤¸´ T¨äT.R9r LІœW»WŽ)Gù¿§Úô1ðÿ!ùŸÄÿû“pÔñÿ]<îñßv*%`þÎUsŠŸ$ Á\öÕ$²DòT4Yì±²ÿï þŽÐï—$Ôð”4ú=RçÃâ~ۺû£ÒPïù`\ Áû({¹aºÿ GŠÿ×8w÷¿]<î÷¿‘ø¼¢÷û ÚÅW¤<EÃ}Íë5 €ËÏ=ª0+?ˆ{T6ß÷¨ÂUáðïQÙL|ã§ð}i?—‹UÜ6†²¹4Àå¥í £T·»N鼡¹ëdý;Þu¤md(j0‘Èb"Q“‰D¶ù­¼ÛDJ‡-cÿŽ‘ÈÒêöIÔ_(… ÝãœèîqÐÕ{t-'Àß‘¹ûs1’~n¹Í غ¹AªÙÜ¢&s‹Ls“7¥anʳ›Û!^çj?ö¿Æ †ûß$)ö¿p4ìî»xîÙÿ£¶ßG]CWEÃ<”ýr³µ9™D=W ƒírûcë,p®³ÀíÈÙÛTq¿NgosÈ®BYFÙNýÛO¤Iy2!þ§–½LO ºÌ@rR“ƒr÷2}ÊÝå(Ïj¢uî×Þõh1è²Çó3ç0/‰\ *¿³ÖÞ—éºV™+ýÌyÞËQF~g¬µÍ²ìÒêG“Kë#ó° @ƒ.š]Ú8ˆUÐ 2ß>dG³€ºÍ7-éhÐzóµHSdãPqÅ£–2 ·ó{gØ ”$ýÏÙDñ›È!ÿϤ?éòÿìâAÖ½ÊØÞ§ü‹Fê@½þ/”üÃhÜùìäq×ÿ}ÈIäeF!õ•€2­ÕÖæX´ä‹5·¡´QÌ!³¶VX*¹§O{äÿ4S"û®’«•RRG嵕ypÿüúŒÇu0qÝý鱕ÜÀz"ÊÊ6¼RSÐ^)ª«Çº~$}˜mˆZIR–°B6º˜lJ5U1¬w+MŒ8Sã0’FbŒ°2ÀENÅG{œBLºë€›·9x¨†…çSÝùFÉxKü‰±ê¼÷z5­dÄö^¹ÆK>lÿ5kšTXó^¡Æ¦.L;u ÉÙ…ÝIãéÏyxëÐÈæ™”c`åë â£Bðð™UàFµÿågß®<°ß£–Š;–ÄJ/Œ<Õw¬éŒ‚5ðXرì3Z®b4ôWرÔ3ÙÈsQ`Ç‚Ïxãf% {P½n÷ᤡ€êu³­ ¸Wg6Ýõ6ëø¿ééÅ‹5q5K›ÔQ9†³UÚ^@5˜ŸèëË5* ¨Î}üÌP]α¼Bl“¾¿ÚrŽ3&ŸU5l÷~ËZ‚uÝtU-•uˆgT·¦¥cÅ6dµÆã6ÊÊ9ÖvÃHj<±!)÷r£^kŽûõJŽ›ÜT‚ k*{ÕÕŒ£VèÉñBŠs©±U­a÷*’î5 5 =ÔMMB³#~F[¸å/ Êd-¾IÉOý‹T·—ózAìÿªõí‹{ Sþ×ñp,Ùÿ£(œtöÿ]<;¨ÿSlÔúæQç`ÕŸiY8‡¼:î÷Ÿ™Î I°v¸Gaûl¶ëe×UÞàG ÇWñ°¶§{¥²¬V¯Ê³Å;(o“5.Þk6ºdlÁ,à–1&EoÖ0éŠöx|êûÕ? ü¿?îËüö;þ¿“gwü¿ó“Áýdîoý‘ýºb¹–3øF“‰¼ÿ']þ¯Ý<îþŸÀÕÉÝ”§7÷š`|/>œCë ü=¹3J5Ä€eЉ˜ÒÞ…wPeŒókP¤BÒ·U×ÍJöÀ´ÒFõË‘Š!2•’•i.‡§Æê°ìeͨ•ÉÍ4gœ³0£#@Æ6›ÞÑ }عlù&ê²çJÓuܼ3 ±ÿŠá¯…k Ž\À8¸Ó—ÍH¨[0îÂe5îc¥ñȲ⻪ïÄw+›Þ!W( {Ðcʦȵ èô€º¯sCqSòÍâä:wÐ<îð$£ÊW¨q?ëùÒ´›Ó‰o,£#=P¬ ûHë*m<½oÁ}íÁÒ{Í7q´€z¶K…{ÁÝ Eí³‹l ¯€B ·`®B¾é‚vú@iàÊkÛÚ]m?ô1؆ýñ@¶ÿô]þß<{”ÿÃÝîSôP׿#[•Ú{ Is\l=\œ½dç‘ÐØx$¬LñlíÛv2ƒ»‡³£˜Ô·Y—~NŽŠÚ<54£Xé¼½ÚÇ*ØkéWZxÕ!?÷×ZüU)¥©O>æPSrd¬)Ù¤vÌ|l®)éµìÌ`ÒRMI¯åh'~Jöx¯ÇÙ¨d÷º›Ò˜îU5›Õ”jJú)Ùc¨)é³dmMɉ]MI¿¥i‡'v5%Ý 8ØR}ZÇ‚›h}DOj r¢`…>kJ:–áÔÔáôWSÒ¹¬-RŠÓsMÉ&¥øTð† kJú.ÀÙ´¦¤ïŠ›MkJú®¹iq†º×ÕôSS2´¬)Ù¤ p¦D¶5%½îïá ¥CÅë6=Õ”ô]³YMIßu7mTç ݬ¦dd¨)é§T•¡¦d“zUÍ Fu 6Ùè@·AíÂ^÷ðxØJ¡7·VyYUysÞ¸ÍÊ”Ž eJ›ÖÁLLeJ½*!Æ'þÊ”:lÍJaðYÄv/Ý굦äè¤^MÉFµÃUÁ³š5%Ý눃KÕo…ո׾Åà´ª|ë^oÓ¹¦d¯)Ù÷pP‡šš’aƒ3ºFMII}Pµ¼P\ãlµ]_”K¢Ó|3My«%­ë?61ØÿFãI_ŽÿLºüo;yî/þ£¶™oìu-Ö°Ü™‰ïè”îë”qº®ºgWݳ«îy_Õ=ÉŸoÅ£Ó\”Éû•E%öêmL¸C>~6[¾ì ò#ù›ì®”™ñ{yÏžE) ﺚT½!@­ 2LE ncXÍE¥œzƒvPd¬’¾ǰšJv†Á· ³«EgFæFVöáЯª-ØÙ‡C¯ ¶pØŽ*?ô«b G~tù¡›kìÑ>ºiâPEA8ñg½jíÂÏöáЫÏDø¬™}8ôª—ŠúMíѳOØÔ>51‚ªðD6ú°È™Y7Ò¾B½ö}à×<ˆ Ú÷W;ð`àOû>p;Ö´Ú÷ÁІ4Îö]¯Ú÷2µi´ïQ9@%hXSûy5‹G£6´ï‘ãq“Tde0:ƒ¹‰ýÚûD“š>‘_GÖ2j}"¯âYô¬Váסu`åù=hÇóÛÖkmlç´æ×C`b鲿õÆqÒÎ-×+]?ósÅõzùûͼÕB¯WÐÊôú1}[Ø…™ý÷gÒNÍǘîíˆÉôÿ§=±³öÌÀÖöß+w°ÞþÛ…ÑH¶ÿŽ£Îþ»‹§¹ý·´\±ÇÕ|(öRß–¼oaY>zÌ çh† ÷cª†z~èfdqÎ ¡31w&æÎÄìfbVl‰ªÑÙÕÄlf³a.UW³å v2˜˜ cqYV˜˜-A&t$ËÁ°°«$ö* “LÄØ½2o+Î\ê¡ñ J5Ú1HŒ:H`ʲÇ`•§½ƒ¤¤¦ œÝ]Nº§õ¹ÿ±+@2+Sÿ¤ÙÞtó6øÿú“Hºÿ †ã¨»ÿíâ±»ÿ}#^1á>§¢§²Œ.QÕqð$¥—’º70ú²pOhK‘Wè “œêvœÉ[ºîé¼Hcí”Y†öb=´s§È©“á^Ó•ŸÛ+Þ¿ãEïÐòz'uðõ9{±ÙEù›#ÚK~Yþ¦’ò ÷åzÔVN¹(¾X¯ã»w—¹0öC¼¹¸Î.Œjø7_®H3r'áÇ~_SóüœeF Îcš|/'æ)AAuöV¼!/o7I°N.«WbúJ&–ÿ,£i²Í7•!þOÿ™¡” 'ÁÅO©§™“zƒ5àЈ¼ò†¬ M¼Ñ•"ã¦ð/¯äÉ*õ¢.OY¤ÑdÏ6ñf›6šò9³ÿ!jû1õ20¾ZsâÂ%™mÐ^±CvÈ—©êzÇlfø›ºTÕ­)gb×ìì½Wå> ô]µ¡z§aª["7› ãP±Ÿ=„Pµq† îf¾aûE³xçôw©ÆKÎé0­Ž®[»ºU3~¢8Ëå¶>‚ðÒÿ*;œjÜýóÞíú)æ†_ŽËíÜe ­¸x;Ô ©îÆ@Ly¡ƒ…Ûê0DÕ˜5•úB†ÌÌ °ª­:Dh„IÞPf°”m€AÆÙosB+3‰”—Sé\¤:Mt\•º\´i}{áR¯©8 l¨¿NmÍ#4K'ͧØ4©tq9Ë`¯qsQ¥gëËî\|â`í‰À9°xZ‘.­ØH·¨{|ýE8s·²{¼ÓÊG\·¸{¼aq«Úùç\®*É›j˜ò÷!A*0±¢#r*¬‰øÃ)±r´Ð/׫tÃ|&z9Ìi·’(À¹p”¿Ã¦-Úx¾éŒ<â©SÿÁÕdðÿ á@²ÿ GÃÎþ³“gë?\§v‚¾“¼ã’ïºÀ!(nZ@ÜSBm‡b ĽçÒ¬VyPIGŽÆ)Ô _´+;¼N-¬éIÿ¤/ZtJÙÑTK]%ŸÆÂÿ¯Ò¹Û?}Œü¿/óÿhÜùïæéøÿÎø?¿§:¶Ÿ³ý«ŽïßëcˆÿiÌûécâÿa8‘øHþÕñÿ]<÷—ÿÑ™Í;²vÏÜÜ'Ç™·aKLgÌ Þ=؃ðÿõŠ&{Z$@íÏú þ?ˆ"¹þçpuòÿNwþÿ!'¯q %á5 Õvd _³Î¨XÔêðÂD7 ­QRË"…Š¥ÊÍÇpâÚzƒå¨÷±Ò¯ E’¹lÙ,¬H d|¬ë§òO«ÕÓ(GìÑCÙ$õñ€´‰k0 0wiÐ…NⲕÝÑc¥ð€¶†îd¡æ—ŠhS© gSc<ÖÅŽÝçc¡ÿn8.c˜â¿Fùþ?è‡ýo'Ï>꥛z#°ÛÞ¢ÁO¬¨ÒTõKoä¢ÇªIW›ù«˜Ò§ëêlu±¥‡›‹ÿª®¦û©ÆAÊIßV]“q3G¥ÓÊ©á d^E‹9ù!^0 I>BîTÔæHÅY, ó—š•,‡§Æê°ìeͨU¾1Óh\f2›Q€$bÀPª1›ÞÑ }Ø•W÷MÔ\²‡IÓuRô{gbÿÃ_ ×@“êãà ømFBSä#áéô­FÂóÝCci²ã[ñ]5=Äwl÷6½CiéîÁìõ6ýCiæþÁlô÷un(ÉY}³8y€ŽÇ4;<ɨ |iAÜ/òz=HšvËîËèHëÂ>Òf ‡6ž>½ø}íÁ²0‰oâ(:þ h-Z,^àä¾(­?Ò>»Èú (ä¡p ì›.²4¢’„<ñEážùKÙúÿ4q5ùFCÙÿ0ž :ûÏ.þ?}œB‹CËñ={ˆ*{¨±«¨ ©â3*­ æ; £l*¿­ú’þOé?uâ]}@Mü8–ëŒýÎÿ'_ûÿQ×O£»dM“~Wä¾j‚ÔpõtrôD|åt â-'µX.:¾‹³ÕvÍc<äüæÿª.¡²§éï·c0þßï#ü@ÿ£ø&ÿßÅsÞÿëë7ÁøiH?üÏ=úþOÿ›??ùÿü×þ·ÿcû)—òÝSö¯Ùê&ž/v½ä %§Þ6]g2a/ÛæOOûOÞu)2B‰ÞñÐ=Ýó5<ƒ(ì{üÁÿòñë}ƒÒ=ÝÓ=ÝÓ=ÝÓ=ÝÓ=ÝÓ=;~6·ÿÕ£ÿùûDþü¯ÈŸÿ*ÿÓ=ÝÓ=ÝÓ=ÝÓ=ÝÓ=ÝÓ=ÝÓ=ÝÓ=ç‰gý¿þëGþã¿{ÄìÿTðÿøŸ=z4 þùóÿþŸ>zô'þÏäÏÿ‘üù/äϯäÏÿšüùŸ?ÿÃ7ý_ÉŸÿžüyIþüI?ÿOòçÿFþü_ÈŸù¿Ëúþçwß3ížîéžîéžîéžîéžîéžÖ)Yï£2ͯ˜ X)«ÎÔΪӳŸóÒóY/BZàGY$„šAØ4â1ÚB©knÞ ÿ¶Í{|…w§iDµvÌž„«‡Ù‚Ñ@ýåEù-8ƺ‚¦‹6š/7Å(El¡7y•Š Binþàüì B6ù½ë'´?®ìcØ%Ç䘳x÷¼±‚~ØŸŒFXüŸÿŽGQô(yƒ@ó|åñšõÏÿý‰~h}aŒÿœDrýòmÿ³‹Ç6þ³Ïãhªß^«QÀ9…”zGÜ)À3GÂRž\è%Ôùçx¾ ‘ñ¿.7óEqä° B¾9KfdÔ„æsÉc}W«ÕÌcW?­W7Í{Z­çW41Íj-ôõ—x9[Øõ ÈéfMÓ pïIÇûÿ­²L¢0h·òRñ ¬ü„Ú·(Ñ>ˆÇ–ÿ7)`ÈÿßÇrü礫ÿ´›Ç=þŸg¥MÎ÷tÿ\'.§IÃô.ˆxT7¬LIæÏáHâϽ:åZî4i¿¿DÜÜlüæß–¾´`ú¾¶L´]¶í.Ûö¡eÛö‘•ç_~ÒŸî!ã:ìd§òÐÓjKÝ>ˆEßuÎXŸí¤ŠÝÄ>Äİ>‹ð„à·FÁÀC–¯"A+¹óõŒÍKÊü=$ìCålû𦹵ÇVÿ×fþçp¢ä»úŸ;yö@ÿçšö™ëÃ6å³FíèUèœéPIòÌ«‘Ï*rx!ØYR vI¿Ž§¾ý¿þ `°ÿ ûÃP¶ÿ‡£~ÇÿwñÜ?ÿ¯Í÷ý$Rn–ày7~ ;KØ|tJ·vÊlܧGçéÑyzðžG§½|{’­ÆW… öBí5½i¿É°Ooc²yón3o\‰2ó~H;ò7¹™¦,}z/å¹~¼wìâ]kÀʳØ0ðÑ©”\60›ìÁv™ "Èûþþx™žatƒa.g¤•3cCfJ ~ÌgÒ˜"öÊAŸ54S:pc†ý©^aWo§Ý+€ ûNP˜áÖôéÀãÔ%X¡_°¢éËx [ˆ%ÈpCr [ä Ü`ŠÙ”%ØpÓs ÛÀ+Ñ §Ì=·Nc«.Ázo4UM×Tm»„fäšñ°tKà€¶ðž±Wx&SÀ2.ÁÚÎKx&^á9™BÈc:³j;³zV¨lº´¸¥½„ÌíXË„&¾A߆4nG•‰4@ _¥þT#¢•0ök]Qp §:­Ú-õ‡s³Ç#H ŸM?À¯Àè ›ÈDÀ6êcÃcÛÊ™„ÀmNµÆ&ù(Ò¦JE|{E‘ÍöŠÜÄšú$U˜B1V<5{áÍMd€¨†èøUy•j¢Q+Tå&ë $5¶")g¦ž“FIÓŸÄ–ýx%Ÿ<(B4^õa;—C¯t=òs3ô*³§ª×ˆ¼¿·’¯òúÄfG9‹¡¢oB¡‘y.—¿+kÛ1ÝϤÿÂ,¨SÞþN{bWºÖ]÷¨O}û_½Ú¯ô1ø Æ}9þk8ˆ†ýoûŸX•´‰ÙªoZ׆ÔÕ}}8fDqÞ^¢31v&ÆfbTŒyZ££c­KÉ&F°Š3$«j$\““vªÁ.vYT_‘¤î{-d«òßœ\™þ•Aî+Pýü?“°?êòÿìâÑ®¿ðÉÝÜäÿ…Eþwõ¿wò4’ÿ+âpò)Íռꥆ87´?pnÏ4q‡`„\Á«vgpKSñMÐ!¼ú½s  O þïì®çÿQØþOÅ…ŽÿïàÙþÿø€+“}Èêu²ícéº|—\›ëu|W>ì27ñ—wÛ5»<_m©šã8¸™/‹oÃâÀœ/7¯²—Ô„³‚ÞAÓEÀ39cŽö'“iR€ùÈ*–æSzIXðêÆa6ÖhGÞÜùÛ_¶ 6Ž4%ª±à\wZ˜,¹¸^‘•zÖ}Îi—äÂÞmW³WÌȨÓsŸY–êúç—1ß‹–æ½ró’9ÕΦÖÒê¥Eïòî~¢Ùfö½†y¯ ׸‡©µ´†Eïò¶6QLË/«Ý_å¬Ç&†¨d¼5£‡Š1¬â†^Xz2ÜÊ7£í| ¶ä0¥üUëYÉl¢æÄr µX±W&–¿j=1yïè&Åw‰êžf^adâ啃:`삼¼Ü´ååæÉ‡F,yòås ÀAÁûŒòrsîã¼&£¼|æxŽòò¼>kåå53ê7òòƒÐ0ÊË1Þ`c Ô[ äŽÉ€C¸~Iç ŽŠ€#xÑ» B}°Û  EHˆ Ánƒ&G·L6ðì6p;Ý3Áƒohìæì{oÜ!âO%áNÀ€¦;d4EåSÀåßשçÆ$iâÜv’¤s{ÀIøÎº× ¤úqn“ºqnÞcëÆ¹ùJnƒªÓ1f}Ÿ‘ɶqnc»8·&ÑJ*ùL,ãܼ^UNÚ¹{¥ëg~îÆ¾³Ç4 ts̃AZe‚p–Bgk‚ýA j½+Ù'œÂzÔzáýZÁ§Y¤¤Æ;bÇïQñ×=âãäÿU³¨Áÿw8¢>_¢ÿù»óÿÚų›úŸ?PçÔùuþ@Âl: ÎhSëü: ýïËè¾…¿GŽòÍ ¦úÏ‘’ÿcvõŸwóøŠÿàöYà”íËõ¾ôÒe9Ø0q枈bO®”¦{‹$ÙƒÒÿÞ\)í®R;žRw¥¬#鯋m,]w¥ì®”Ý•²»RvWÊû 1Qâ “F!&BD‚!à¤aˆ‰Å| FÕ4ÄÄ0+™i4 1±˜X±{›†˜&&ï$Ûü^€…ºn†/ƒC…¤w]V/˜xÕ|^8zæbˆhM@äg —Þs´¢9\ õVþ³¯ý©¡ÿrÕàÿ 'Åþ?Œ;ýß.žýÈÿ"'árLææQà5á—˜$É9ãÍ–•ãLôŧëÊDLáõ)â–%ð*:N7w òælu±Íïûëx™ÒhÑÁ0A§@jÂl¸ª ýøâ¢þJ}+ kÙVLf5»sÆr°MÉ+‹9£âËP–wxí Qô­ów”£l½aRêøÁ 3sWµr Ωñ†:,{Y3jåls"¶ ÆÁÃemFBZ‘ðàW«‘ðèTh,M,«Íh@Ô)0 ›jÓ;D tÆšÚô…ýƒ±£6ý£=ú°ŠlôÆÅŠ$ûBUÁƒ!ïk±…§W RjeCÕ²qà®Âää‡Ñ&U:)][°óºÎBôLAøn~ð˜¨lö«ÏàËÅT›Vð®(L@™8qK¹Aº¡>MÅÛ7ñ2¾¢6£8(+X]?§Á|I~ù<_o¶ñ" PÆË\ð"‰Ð÷ó-ªÓ€ûvúû–7w Èúþ˜o–©É\Ü+Õ ¬V .È x‡ ´\«Ý«c1Ó·Ügì7 èjã6fPÕê|DvòHò_RÄšø¼8Èÿ;ùºþ«í’Ü9?‰'ŒÓMÀ(ÿúrüùØÉÿ»xÜåÿ—ðç‚ÝE §µ§ò…@O{NW‚¼#UªÆ`È_(!hé2ô+œÔ>nÀžn³Àe”jkc¿%îpîä¦òIw¶­æ*­T/HÀO¾¼Ì’˜ N.lî›2WYjw7ê4S#æ-îAŽÞgú î+´ïQþ»Ù.6óÛÅ{ùO“ü7¢ÉÞäüo“~'ÿíâi,ÿ½ÉéC”ý¸§¹¨’ 1E„ïÎí„N$ûÜ µR&xœ]»¸«‰v¸ÀÑíÌOÒ&®ÉüLßm1_ëÙBr2[¯'ÅÎÉAÍÇ¡Vpöt¯TU¤ªWå‰â¤Ûs"^lê\¼×lt²iX34´·ÇãÐ3\ôÖ ¦b¯ÔÅHñžõè¶áÀ/f3·SJOÚÀRÒ³> T×µ]”ìYN'n3(©Ój ǹ(¤¬ìçœÈÜ&T¼ÕŽRöv°B.p›P¹[¬Æpœ²µ %ò$‰GÈ®­øfÑ]‚GÜÊ›Oi«l'«Èß’Æq ÀM¤ƒÞVàH,Ü:p`z¶§¤/€uàÀÔ…CïQ ´ýýÏÝ Èpÿ‹†ô7ñþM:ÿŸ<-ÝÿüÝ\v£÷×ÐýîLžÕósrÖÔÛàëp”á Û+‹ÙÚ+Áƒ?‰€þVži°Y„û,gñzVö\¾úÇjórBFõ9/Ìtºè¯Omþ;§ÿ0Öÿˆ"Ùþ?vùwó”þ—?2%cÁ év~’éHöK¼»ã]JBâ÷|¯PÃT1K‰æüÉõVÊ2Ég–x­ö°ÄpU7‡M|¾ÍµcÕ­²ÔAVALBHO}ÿˆ²ÿ7@+ÕâhÕu•ÍÑÊ«ì¾nÜÊš”æ¸åµ‡_7neµ;nú-¯ÒlËÊ;·f\óU¼âW%kïã#Éÿ¿'ñæ:Y{ ÿtðÿÇ“Îÿ{²þùßC?Ùc¸ÿ…¡âÿNºü»yÜïËH¤~æÇ‚ÆÒ¢rmÝ”5îQù+ù¥ÊÂò¾ ¤},vˆ¨¯¬‘Ÿ@¤÷\ÒNæ.µ’’2MœÔ´hÍ_¹„~2­Y…Y¥`ê²J[V;ã@÷ìÓcàÿîJ?î1Ùÿ¢~(ñÿ¨‹ÿßÑsüß=ç¯ó` ›Žá»gø-:WrûB¬;Ó–å¯L9¾«L¾i²ùßÏo_®fÍÒ å3ø–ë®Yê ‹­$ Â;·I.F¶ÁÇäæÖ ¾Š¾ ²ÜsuO{áüwúà“ýoØ—óÿGƒ¨;ÿwò4?ÿí¬}&b èpxßÑL×^¥NåDëDT”uPÁеh£R ð"7¦’jYbf‰Ôúp±­…·Ð£Þ1vdC¥.rär±Š½ÅŽ”§@ ÚÉPÎ_ÂÉ£4ž,+¶ýkÞ«¦:'ŒF‘Vè¨&dÆÔ¡zøÓ÷dŸ{[÷þ\àÔ‡ÐFŠÃ},#Àælq6¼ÌÍCݽº»qO,÷ÿÆ>À&ÿŸþXñÿ%Ÿºûÿ.ž{Öÿ:û—]Ô¸ŸúVøº{W0)¾À°Ú6€ËצÀ©Û¾G°ÀḸ–ÓøV”Ïš8ºr«Ü†««®{¨hÕ^EÊ#þËKN·ˆÌV~-B—ÅÌå /«X\|ùÌ´_ ̉¿ºÿ8úö§¦p÷Î#ÉÿB©_c8øÿLÂÎÿg'nýÓùò·O V ´Q(ˆþþNÂ|ÿŽÆ]ý·<î÷¿3B¿äÄQÿ (”v«{ùó¢ÑÌ>\Ã> ÌÕ¾2ˆuÐFSs°k°8W,Þ áÎÑ0ùáXÝÎ/²Â^®‘´CFÀ†4Z2×áöze“欭(Rtà×8¼NngnœØ‡3|–FÏ*àй$F59Åp#gБèl¨*"¥æTZÌO^¿FãÙÌYlóÀ’á‹?ÿ8-\²œlNX¦ý)FEqд_ËaƈeNQª( Ó^ßgÉbþY,:‰"cðlú£ÚÆÊà™ÛYg7Ýž§ëù9¬²L‡´FÖ†lè ¸h£j8dÉF ÆËÜpãi.&ÏóÍY‡³í-%ÿd&XÒJ•µ®qãØ'ŒFºûŒ°•*˜&>a:™~dâÒëåçx1q¥6¨`9ñ ˳)4¼4b;ÛGbéØЦšÃ¢1òÅøSÝYQ±ß¼/M6¹Ïþñ&F±Ži0×FGØd§ÁD;¼î“ð¤ºí ó™ºm3 ¬¨?}¯É=¦ãýu¾Z0rƒ {Ã͸íÕwƒ .œ¾Ùnâ Zذfl¡O¢‹¢é›ÕŒì\+àhKx‘WðSJ:Z¨Ô4¯Ð §¯—«õ:¹ÈrCCà-8xšH@*<£é{"ÉÏãÅOñ|±]ƒð-8x¼JHÑØæxœ™µöD¹œ/gVGJú“Ø9SÜxz¦„ò°Ø¡âu‡QK‡Š×m<)^·{8l&¹†^7{8²Ù\¡ó†6¯ß&éæc²¾!G'ýᇄô‹_!,áwKk²äÚq½Rô€\ÕÀç7ɯˋëxyo;m[F7úÆÄ’ÁІ¤ÎdlÐ~¤›õ «5I†MÌš Óäèf\ ‡Ñ‡×‹ú€^1ØQ@˜l>0LX32·kH¦ÆÅà;±" çËyMnóâr£»3O€ÍÎ^AnÏMîm*éD'Øð)E^uѳ6XMäx=ÓTߊ¤œÅ.ÑO§ô—3 ‰)…xmjf ÔïçËßÊÝê·Ø¤N{âX]N}\ü?¾¤³Zc˜ò¿ 'cµþ_Øùìâ±õÿðæpNÑ·³òwV~V&–·ñß÷îmþ¸ðÿ«š€ÆüÏ*ÿŸ »ü/;y<ùÿ‰NUN±+G†tR;ôCÌmïNX޲n…~}ú&v>…´±ß>…ŠwîeØÔ§Ð~(4Ç„8¤O¡aPiE=øÖ°^nhPóâªÍ³˜é0¢Òe:@ÉÃ*ë‚•çFC:èt+ %dxøJ.{ùß= „!þgЧÿåÿÁ°ßÉÿ»xö!þ§A%8CA N¡†¹ truòAH.…RJÓ@V SÄ+½õÜÂ‰Ò <›ÇÄ·¢TÒ$>[\û6B´ #عƒ^ò¾p u¾ œZúÙûšfÕå!>zßà²Äû›œœlÒ` ®H¦Ñ8§%«dª{”upB²é½|,²°ê‹„•»Êƒ ã:.òÞ˜ØïÁä×ÂPçu`ÜÑÝf$Ô w[· ÷+‡ÆÒx¡[ñTÕ_â©€W¹Mïû7Ð=è%nÓ?äÎ ôz}ß×™ ¸fûberÇ/;(^vˆÒ æíOÎAFx€´­wEÓËi}ï‹*JWf×Ҭøæ¨;3°$¸ëóþìÿÜ3¹½íŸ ð)áPw—ðÁ?öö÷2&ÿßhÉöúWgÿÙÁ³ö×*¼åö¤ÎðTÏùRiL¦®ö ¾(ä‘TR° …!3ó·XÀÔ5+Á^¥ëJа\dîèÂjFUE#žmý‰ÿ9cã³ô3{êç…ÃI—ÿu´þô? ܽ•Çàÿ†‘´þQEÝù¿“ÇýüI¨¤¡ß÷…Ú…½3/örm?ï‡èæùÍÕôô¦OCoïlàÒå›óuutüVÙ #ü›Ãs²y±˜Ç©Ô²l Ö›TZAµ'f’3Wë¡-ôÖ£”Gá -Т¸/ãèé5ïÊ~¼ŒSc^_ײ/gœÃóŽ1sSDÍï;nvµ+’/ÉÅv“¼\ÝÜÄËÙ=¬ÈE>ò~®ˆˆž{ÜÒ%Ûªhí®‘¥bK +Êw—<¬& @£äK97bˆ:Œi°%ÆÒdßñ4ì“R~JÖ¼7›0R®(Õeð‡fDµn«Ã|̉yè+“½ª5Ù+“UrK<—<¼ÙâVÇdÝq.±zY ²Ê&s—Î$‡Ñaáù*Ùg0ÌŠ]`¥°ªŸÉE'W¤¢œ_y€,~N€Ç#$èB¡N ’å (Ø æ&Bi{! ‘É!PA&b*Ì jƒŠË­0ba.`‡[d'׆Y+ÜA`kö° äºM¨Þ G÷Z§µ?°ÇBÿÛTýkÐÿFƒáD®ÿö»úÏ»yêÝôy¼Þ7Çv4¶û©¥í4²F¶ñ8F¶ÓÈvY Y§‘í4²FÖBI ë_U…’G¬^ÿê8´•FÖ¿6±Æd•cÛÏvYTÿÚ|ÜZK¬ž8ŽÔÐÈêô¯^F¯„ÃÛ€‘}†t±jŠ¥î‘Ö’·K*rì cR Ñ*rð.©Q?N©a)JZ_A_‹Ò±j†‚c5J÷j ”NÿY;•}Ü«‡BPû~*û ›TcR¡ ›Uöz­Ñ4Œl # ëÓh·R-M;-‚ªáÍ@MÓ†Œe¢ÕÌõJý°»â”ÃgVÅ)‡M6Põ¶oWœräuÇŒÂv¸ÍÈm'a5FF‘v3rÛl(XÅ)GŽE Pà†þŠS޼–<<§y-w87+N9òZQj4iZœr䵜íè¤iqÊ‘WyidUûyÔNñgÛâ”Ã]qÊa“B‡ê™2Z§zÝßÃQ;‡ÊÐë6Ž=‰°^·ûpÒP„õºÙ‡Våâ†í”‹³wp!  .”¾„×îSñ¿’«©¨âøD_TqÜ„åª?3U{½lNúþŠ*N\K€Óƒ/´Ù%ç˥߮ãaÍ®ã&‡@<£º%\Ç^ùþxÜF]űÛ)€‘ÔxbCRcgfïµNç¸_¯NçØo î1T“XW§sìUÍ3ŽZ¡'Ç›*Î¥Æ+’r–@Mª;Ývv.áëû:ÅCÄe¸*¹Ýì·­TÊ9aÖæ„-J¸LÿøJ?°ÇÂÿóKÍrŸÊcªÿäøÿþ$ìêîäÙAýÏÎ9°s육ß;çÀÎ9°s윱wÎ¥sà}ËIõAå÷roÊcªÿ*õŸIóA'ÿïâ¹ø/÷zoôíZ÷†õÝ€HÈ:i¨ýǽܛò˜ê¿õÇrþ¿þp2ìì?»xîÅþãZï¾l[ç 24y19u!"œR¬åÆÌBE 7©|7ñ©b>ª^ÏÊ´5,Ï–Wf« ³u,û?2ÿÏ1ü–€s¨ÿ6žtõßvò ëÿ–Ü2’BAØT0œÿ“Ñ`(çÿtþ»ylÏ Á µþœ²–Œ²jý1ä:ÎoòÃÓìkÖœ||B/“¯ç³â\#_Ërƒu((D™/ <–“°J ái*$@6"‹~¨#ê88çgaÊWl––zfÃóŒO]£´ti@C!"ªó² ŠÌSòTõ÷|½\&ë—‹8-ëO%ßÉSÑsλaΗU–ÔŽ&œ/ñ9u'Ú¬·Ÿm*ýqCžödMìwÛM-°_gm˜h–9È”.çÉb†Lß4‡Ó^™xò´ÇÓÓQIß7B¶<"7/ò°ÊãÒs7kÈÕ,™/ûü8¬ä™·óÁnø„xøp¥{t­W×I¼IDXë¾+ M´h¸Ù®—®3–ÒæÇûü[ypY×–ApÌ{Qç|I-›!¢ÄSOíª !!F[ÕW>y®œ†~NdÕƒ2ƒâ»õ,YgDe7MŽF²µ"Oz9š¦—Ë…O–ã‰Î‚ yF¤äI¡ÑSä+¹¾½pq“t£6šÂw¶hø> €Þ™b¶89β9Ö>jè(¤Ó)wYOÉLšL¯š JTzŽr@ÓÌuÚMö´WºN¢B§Õ¨ÇßaMÒŠfòo óÇ'Eí À'•CYPR–‰³UmwfÍDIy(vªL­¨¾±ñé½'ük® õ7aå” )Í ß#E€Vÿób½Žïš+ ñ?ý¨?ô?Ñ uúŸ]<;×ÿÄ”¦YýSG‰ÃO¶Þ¨Óþ´­ý©ò^”?Œç¨ˆÁî¦J´Š ¬ãËO2rZÐ áóR‡Ï{Ì_x¹ZnªøÓ5uF›3>8©°˜3€l6e$÷i¼!íÎ Ö‚urYµb$Éî»#÷ò3‡’ –ÿôŸ+dô¸¡‹I0Þ“BL&’¯D+V{Ú’jŒ—Å:ýØW£ã—QYPF§#kAË \Ef;ËNC¶sšÙS™WŠ©§ãY¡YI†òVs—†k+—„>[O&M塪Éì#éÿ6É ÛÛuâϰ¾ÿßx4uþ»x4ëÿ…Ø×«Yú‰ûÒ),Ààÿ7E²ÿÿh8wúß]<€þv÷ÿXAÁîQmUœÔót™lz鬧¾Ÿkµj½÷ké/ …² …µÒ\Ò;ûñ—<ò{µe3Ö(é—ùRUp‰*¤8Pï ”Rß )5g×ç•Q}áÛ{ä eÂŽN{…Ϻd3 -GÑË÷%tÕJ†Je§›9aYÉìãj/²)¦/W[j@¾M]½N_}‰/6Ç`¶óÌèèUNFà<3¶7ýÀ·Ì"ŸíøOÛd}'õì‚Dz¾o^/gɵ³ºH\ΰŽêv•ÍñãüVFžÓË]ü²ÜÄÇRoùrü(µ¼«³$´Î†ÜÙj{¾îöÜ>®õú].Pý žnonâõ©R9ðæ¯~qx+]Îoocmu¨$û|³Ð$d@ß» 9Pfgóuy™He”Á¼®¤£÷dogvÆÚ\ú—Pæî‡LÁå‚atkßãG3^m¨ÔtŒN"V0ODõ³mÂþëçŽØ2—<‚›½’EBAŒ4“Ú[aF{Œ6â½A]}Îx¹],þ:O~§)Wwmz›\ÌãÅ«üFÐ|“q*Þ2IPètƒR²ÍUf™p+_:ŸG nI“?å²/ùû6Y,HÙíO  Ú­¨­~N6/Y7ï ¨¨ý-…4÷Îv½°x‡×˜š“Ô÷PŒ:Ý%ãáóe\°QÃg9êζWWT\-=!äöz§ c „¨Ð9a¥Î¨7–¦˜ø»å]‡I¶ÇÐ;|¾#î…›øK~‰8¶{á’ÝŠ@EÅó;®3•ø²À§ý@‹5vÁš'õßYY½SƒfjÓg~úÞÞs0 Ê,©‰b” „ôqÎáh8¾e„£ …cö"C·Wêa‚¼0»dH‘›—'Žjx_àU쵞œ´€åˆ0w,`Õp·:ƒJ£|k„BÄ€'µ Í]"‘óüÃû— ¨çd@•ðÁ_>~|_ê¨DK9~QÝC92(±FE‡8'M²§tß¡¬1˾ç)8,€Å yɱ‡euö4 CÌ¡ë à–!’‡=ocÆÑ­ú@_{ÕaîÛ­÷@®7ýȧ¦bgÙ«åìvEjø0Ëd,1ŒŸD[ÍFã U¬ŠƒV϶*šÇ±S|Xu’Wyø”N‡ÿüµ?¹ÿ³E¶5F}ÿŸÁ(wþ?»xøõg9»/c¦VôhÊÿ?¢>ÿ‚ÿùÔÕÜÉãîÿÿSF(ùyõózµ½5&†Ê¼GçhÀœPóƒèŠŽŸÿ[3œ§Ø@~§èBåÑ•ˆ@‰@  >ã)ÐÏ.â³´µUðºU¼œ„”oÅN¬£å”•m$gî¯èè2¦>4Çö·«ÍÙö–¢4™ý3”lÔo¨Ã²—5£RUŠÝhUK«Qò%y± 4»{õežnRt ¼±ÕXh¿†>taœiRTÿ1ÞÄ®ä)õÒÑçÞÐç˘0¶˜¾ø×ùjÁÖmk5Ò›í&Î@4„¶µ‰œ¼—öcá­­F£7´²êý5‘#ÖÔLý×x±ÅIjfÕÿûx½™Ç‹Ÿâùb»Æû‡šÝOšQãØÊ:¶\fFÅëÆ…rJ¸ÉÙ4üm{ok¶Î².~LÖ7„‡Ð^\R³¨ãbÝØšrðS¿À_—™Ó>¾°úîmuɽfæAL»9°Õ|ÈrÂGv}½üLÎ yª­öˆãüu¾b¡ý•*ÏÙß *Šþ/×(|š&æ'ý£)ÿG(äÿbú¿þdØéÿvñ¸èÿtißQJiuFö2Í™hµ«e…W`¬ ʱ¬Ü¶Á—t–…²?ã¬Ym~¸ „‡>ë„ÓæÆY>Rö•{Êÿ´Zßü˜0™àûã¿o‰py9OfÞÙÇD³¥úÅÌϨ֩#PŠ·Ê¥VK!ç8 ‚Ö»‹‹íš`œÑMü¥ø´]ž¯¶KêÐñ¼‚óÌ1 ˜/IòÛo³ ‹Bè…úªZÞ•})äÆQæ$ ÖbV¹y&M¹ `žä&@† ™î/¸æL÷•ª!³Uí…3äù `å×ja žˆ9 g0™`Ð`T.Ÿ rÁ²½2ˆUåÚû槇öÈò¿·CŸ{ôçÿpÑ3_ÌÿEü¿“§æù_Î!ÇšáÔk&?@õŒ•ž•Yª—ØŽ:ÿÑÐÿÕ2O½ðäIÁ`Ó9eWÿdò áo„u&T3Á¹¤ùvIu;7ÉÍy²f]åQ¯—ìþÁ`Á,•c‘å(…+ª2.ßC5C™E¶p'i²ÜÞZ§Ï”ÙÓªËYg¼¯$P{\«Š¿Ì ºZ­f?­W7jÎ8EÅ\¡~]næ ÷.âÏñœÕŸ·ïGêˆù]ä½ý2¿dM߯©ˆ´™'iî•Qžˆb *§ÂÓ*­XÚ¦V2½•Ã\ç5y¾à»§=qvÅœå(òËdMgkŠo´ó²D|Nˆ%¾ ÉãÖÛ²’¶øÞ= L/‚£j{Ó$GYèn– iž²o~=ûœ“rÓ‚%fœà÷ùæš4JÉæZ$PÈöâz¾˜•­‹ U@ö¢÷GX¬ôiRÜòý ,­.ˆ¼B^P?®ÛõŠðÝ4–t°ˆ¿Øˆôå\*®Í^E)cA¼œ-Dªý ûJ Y…‹rm4<” ëׯaöäé$x˜jµú%ûÝD9¿áZU>ßP¶ÎbDø.#ŠäÕžÉ1ÕóÐUÅ-Ü{Ë£9‹4bÂþ‰Šüq$b@!‰jgÓÆ ¿ÏTÇ7†m5Ÿ©熻«Höfñ7½™a~W\Õ5ÀËg"3ê¹WÛpÎ# É,£‡!fÖqãqlqdýg¦/nÈäqs[ôYJfuŽ‘üf?úᎻ`3¡Y€š-D*Ê"Ròq“4î&M6†>Àü¾ØêsúãTY×ËøÆ`œ Ï4!ï.)“†ìB Ç¢ŽK?Wnù_}¹¥Á:L¹fÀ5§WSŽL€ŸH0ýtÔÑÎÓÊÒ†ÕÉ Ýx2²hã9loéö®±6íÍæ°Wwr°œM€Og#0Ö—Bijï¹Õ^1Íó«5S…ÎÙÖgš;Ç=ÄEdS{xkX:¥êÕè@‹µ#äÈe~5†7–™{ÉpEªÚè„õúB—"¹´©Ù¯€~Áë3™Ðz~EWÜ|¬Ù1.¨ú3 €-ÇE¼MtM‚ðJýr%â«n_’oëc¢ì¹T!Øžx—4ŒâJP+ªcг’FQ—†#¦d)±”ë²ËebóueHË÷ ªB€’.*ì¥Ìe›C.æ×mØ´Ú×õ^ʸv*$hê â—ª£*›ik^Ú³I®¿Øä•¦u¿|ÿÈØ~Ãüñ­ü,pDH9¿±Û™‚ûü"^cQTÜŒ_b­ «­o¦ƒFvq³Ç¿ŠU瘨ŠíË÷Oê74Üln¼LoÞ?è45Sÿ¨ül˜1òÂûŠË㦠Äí™XöÊÌöŠäf Dšf‹½Òx¶‚@ˆXêä Ó|‘:J\ÌuâÓüí%}t~ [TãË;¦?òp—ß̘ËójAÓZ«œ¸Ë^õ þˬ{gÉÆæÆYë¦u•®_}¹Xl)î,û÷¤Â.ÐãEKZY/ m€ñµ·Ð}Ì3Á0{âÊòφyaXòrõb6›g¶³ÒU!}Q¸­¨skñ‚Ö]ì~,±âŒ‹}ÇÀ:ɪ<€¢ØéGÃlÁæ;=ªµ<¦ýÓx¹:Û–ù!2’6’ø‚#Jí¨Ø×ôÏhjuHy‹µªƒ å½}ÅI®ØûKœ2”F³§¶²Sí!ïí+N6 Ú‰×óÅݯËg»ñv¦+¡áÍv0SÿRQ‚¦3'xæ[•èôvµ™_γ §àlµ]¢ä²PçÔhsnrŽ9«ÚÑM ´v\-ÀI†5–õÿdß¼¦^pDˆ+—a[„d!LpGñ¹£L™S}¯ êN«ˆù¦Ë#•}ڹóָÃctcuå*I¾Hp.‹ WÞÙmæWß—Díp¾ü­æå­PæßÎ×쮵©Õ-­*´å|å±ûz™nbÒü;×Z°?¯fúšWD‘^É*ÛQë,YÌÉ’Ûƒž /ýОŸP5ï<¥eM'×—|2I£k=flá:‹bÖ–ÀõÒRŸåÄL_ü›a 7eÌ<ö­hMJÚ€ÊÌú$Saև͉tô>^“ÏdT ‡WW¢7¡Ô£ŸŸe€øns.Xk+ó;– h—|ÇB—â9OÕë‘ÚÊîz„¼·SÍD± ZJ¡LólCC­°§âPÈ"îêo˜™^Ïoó±>låX;·0ÄË*“SͬÛÁÑ*=sópGÐñj¹Yßå˜0bAŠÿÒ‚kŒvaŸ1H«ß=®XÊ¥Íf}—²âr¾`7Ü"@¥x`'rÉIØ,¤:!ÑMÆ>åuç’UX¬º?$WsՙɫÖò›xsqýCùWßÎÉ5P )}ƒµ2ðRý{5©È°I­Xëˆ ‚­ä³x6ó :¤¶$ª‘ :´¼æ¶*úð¢&Xö(¨ùÀöÎo­ëäfõÙBƒ¸§°›lÎîíšýk!eæ›æe~!ù‰¹rnwh³òˆB/ÍúW‹š®¶Ë´pý|#JW*~Õ·5"ÃæýûÇc6—Û¢„âoÆCíï†l¿cÄþFúÑ8Gð…ûŸdÆX°Y~5N~cçóT\VÊ»P%P_Æ‹*^„Sæn3xB6ÖÆª—#ÅŽÝëë‹öR?WU¥ãÜý GM'wõ¡Ê ¢ëMN©¢ÜŽE}Ç §2Š„ÚÒ Š0§ëc@·ÂÕê,™É€RR™¾C§š«1{ƒjZgÉT÷´·3úÇì,mÑbÏÒ@Jð‹ô5_þlS@í>…ïÕÎÝ•W]À„JR>é;ÅõUJï ßDøm"S´DÙ1ç­ó.Û£·­ÿ˜Ÿ¹>RÀò?‡ƒ(’ó¿»ü»yÚ©ÿȤÂE SáEëBUkM5ȲH²M J®ÇZ%"‰´©-)–SåÒò.mÐSÂÇÄZ±v´f˜$Í€*q`DTIªH)L@«T])X‹P繋Ô\ꇘ–gZÿƒÑƧ5§«r. l¨ÿ;˜Drýß!ùÔñÿ]<îüŸßë¼Js§E€yFÆÓên+ã{¦Qq`† ÁtL±E/±öëF×jVìí«]õ+¬ÉÚU°V©¢ÏµéYQhB]«î¯æpå$ìXn¸ì £ï½¡ïë ØÕ¾~ØÙÕ¾îj_wµ¯ víkæ:æ¶^ôÕ[«}bànDЙ¡q:²ÍàE izÅj\É—Gn²GUž»ºò‡[㹫+ÿµqÔûvuåÏi^Wž·ÿÈ5b}Ù öÿÁ@©ÿ8žô»úÏ;yvYÿ.Xì³æ²umÈòÜO «WY¶ƒ _n—|Egjžk®X¤JQ&Èà‘…²`Õ—«åÛäŠlùÏ ‰¯h5$¹¥˜éCùyV@–AR@þw<œŸ¡ƒs’qŠÑ¥@?ìµfÚÛ7ßý‡WoŸK3€ÊO*E‚ËÆjÊâpJ=6'.,KjÄAÌ|䚈ºøÝ²tÞWË¥‘•]ÆUÔÏÛ—¹(Ü”6£KÕNsï=ŒhÏW«E/Ý)5s T†ÏöK•–ΦùÎBiºÔGʹpªq˜ëûŒMEOøERa:ÍŠ}Ë¡Zj»‹KU²1·ä`6¶e8‚ûÃHö~ótÍU ¨rÙ±u\Þ½:)©~µ¹¦Œ / iŠ2ބܕd徭sâÿ³ä\DÇgWPƒÿû&’ÿÏ€|ìä¿]<îþ?¼ÏïWRÇñ§¶¿ÏýTOR¤ hÅÜWEˆSÚ°4¸$š žŸO¯0×û‘ÊŠ´N²@Q¯õGȺb×é ÏãDŽñ´_å¸{M{S¤xÊD¸AÎFË.Ûüpa5\–ÓE/l0^v憋 HÊÑí”OŒ‘OH‰lœªª€ià¦!P¸D‚Rl° }Â2šBÃK#Ž\G¬åFì¡!¡j¡%¼“†MH[ÝJÃHÙPC¯Ô:´³¥†nô``ý쪡)£`ðú8d¸ÛF ›Ñ(pc´|îèQÂ6öJt]Q8gH ÞÄ+x'@á™]ž$%4'^¡yÕf‘À=OJxžyåß}¨zŠè©R2÷&2ˆ Ohu 83k;'ä(÷§¹ï|†ŒýŠcã°9<Æ^űq„Ö”Vw…)!s;Ör©o`CcgQËÍ!•Q4ý¿“Ψ‰ ’Îh€ ÒÈ«„:ê«ÉìWo±+at<îq’Ù‰¯íȯ†ÛMEÍÞAˆªÉ9Õ£*¯'ù褪r;ßQ’zfER·x=¿„’„îŦ0 œ)$ ÁX¡›Wu0içV4ðJ݃Oª¯òêàY3eÃÀ«´:ìÛl®¡³&:pš½ç§L_8-5}™‰§¨t hü²š|ná\ñjвèq)XºNü¯kJcþ‡0”ãÇQØéÿwñìGüo™ÿÁoøo­Ô»–Ó@ظ°ñ٤ܦ%x.e°C% Å[’å€h˜ü!ÏüP%~pöyëžê©ÁÿÛ²ÿN¡œÿœÿßNž½àÿØÉ l™ÍK¾€ÜÛN¦Yø¶ÖDðW/kÏò±+šW¹>ì·sC ½ê¦ÃÐÏ -ôª¶ #%ã®lsQ²;”xµ>†5+® ¢„Å«2ÚÜCg[¸m¢ Ì(=4yv8Ú6Q{ôÈèÛáh±Äí•혢}Û.ýX¢½›,yxø6YÚ(]ÚÑhZ:yŒÆVNþâVNÞÕà­ì,ÿŠp/[ËQUŽZû< ¾¸‰3ôçäáÝ8ì×ÉÃÑBŒÛ†9y¸[Ah†M<Æ^ôÆ£¦Nc¯²ÁxleÉwfÖœ<&#½“ÇįMl268yL¼ <“‰?'‰Û±¦uò˜œØÆÄYÀñêä1† â'q9ð:©éä1ö*ŽŸµaŽ;÷’²2Nü Á=¨wÿ‹Ùl7~ýd Î£Ÿ=úñœ>²PªIþÓ’‡¿!ù 1UPã¨É•µ$¨”ÄB%¿ñzºZqšýð&›„5½É&~#$&‡¤Ö›lâ•Lm_¿‘+5æ¤5¦­7Ù¨oçMÖÈSо„–ÞdîÞâ ?lékä¬Béé˜óïÜD±éè¼Þ¿¶Þd˜á0@|ÍLn‚Áò2ëž}} ñÿóåoÍ+A™üÿ¢h ùDãqÿ¿“ÇÎÿãÈ„2!WbÁ½>¬ùš³3 %_ÙãÏ~Ô6Þ~à)N€Ð2`€ЦÊ;ª[ŸÜd~|ßt§Å.™ÿgþJ~ÇÐòÿ0EcÉÿ/†ýŽÿïâq÷ÿc2¨èט÷Ký5òσºòã7õÜ$!Ôß©C8!ð¦Åy©x.ÒdY)»MøHó(cß6)£üЇ…wÄ%œì±JõÈ5ÕçÌo…ÿðäIðrusCnX,cbðäI¡©r®ñ—åY2#”‘”µ¬Ëm@òEvg{½dÛ“Ý®ƒYþ*— Ë소Ë÷Pg‘óÊ97Ï;«’Î)ç °äsW«Õì§õêF,a ¡KH{øu¹™/Ü»ˆ?Çs–ë0ï§œºE‡R|VÐ_æ—¬éû5½ÂoæIš'q*PVÁÁÒ²q*„ˆù {Æ·ràë¼&O|W͆™}-W€.ëÛkÊÙgoª©4ÅvA|N5›¼fû= LÌEUûüãuäµÂƒÕe°¹ž§lÆÁ›_Ï>çIL5èªX/¿Ï7פ¹z_-’¬m!ð_\ϳ²5a"¾è%⬜mÞ87ñðÛ¸8àò,jRÎcZ`s eæ6ñ.÷i(ä> uù!Kz*h§½rzG‚P/¬HË×ñr¶ ù/ì+Š˵ÑðW‚¿_?¼†YwPØŸExEq{´–=F'|«&haË«-R`ALT+­¦.o-Ú3Ç+|užMw^X Å·MFQ’ïÊôSq†Ÿ‰ôä7óJÀ–F-|¯Y 8‡°%ì+Ìâo*§ša~W¨¢5Àˇ+³ô¼Ê–IZ Î{„"™Òô0ÄÌÇxœ‹”a>N²ÎÏ3iK½oÈëä{s[ P u.q›RYßýpǽØM@˜[¢T”rÄ^fäã&iÜMšl >PL ºN ÜÈvœ/{mßìŒ{`¼#·%ÉûQ6¬Š¨àˆÅÔY¼úrKÕ~ÔУžÜ†µ¨^Ph€%‘3;ßf~ë£ÌæIæÇŒs&Êò80¡É¶·”4Y¬ö¦wØKeð1Ï&À§³-‹EC®°Ò\ß“­½„šIæH„½ÍÇ:s‡N÷Ö§Îûé>ôefsý VYtÔgØ«ÑUjGÈÁμB Çz,3<ö’ážWµÑ]"”™]¬çL|„.é¹6ø]+æË›Íj=¿¢´°jߨÅWVh+ԀÉÝ4• ÞŒ.b"èR­¿¿• ôP­fV@½$í<¦ÃR©ù1À£JÞ`²¸€c»¶DPµs™FȬÀƒªÓÈ×G¶VL9WÞjrTv}¤'Ã|-íLH—%]5ÙK‡XtÉÃB† Pûš£rT×N©á A\$­®¹6ó×¼´g³ÜWXPÞ©ƒ øåûÇÊpR…0¡:³ ÷mH9¿±Û)ƒ¼à ›†§ŽFYÖ_ÿÞàá ½†Ð€jtÀ Ú—ïÜàá2ð Tazóþ‘A§iƒƒJ;ÃÔ‘ö`'Ì¡vhÎ@¬»‰b¯ìÁ´o¡HyhÚ@H½iÚØ+§-ˆšˆ}X¾+ÐÐB^÷‰[¸N|Zx¡m¦Ãwœîãyl|yÇING‘®ƒIºZ|NÖöö‡î²W=hz3kóY²1Y¹Á·¯Òõ«/‹mÊòâ}(Ö¬kˆ(¢d$Ûê¡xlyÑWÖôÂ; À8)Xh¬æ™˜™½©åßr;Ù…¼°Ì{¹z1›Í3ÃkéA“¾(¼©4Hxkñ¦-Ö]ì¢ê¢Ç)ûŽŠu2›SQD/Ø}Z¦ 6ßé1¯åCíŸäËÕÙöâ:—/´„%·3ø‚#níèÚÎ6±A¹òk^+Ê{ûŠœ\ù—8-1 ¤ÚÜN‰¼·¯ÈÙ$4´-^Ïw¿.c ýÁt 5¼ÙŠê_ZJП«¶ýP©Æåy-›žDëE‚V[§ª³êÚÊDã@kÇe´Xc¥ý|ɲ¿a°\m憨ÈóˆWÜoüEî7Ó/UßË÷ÇÕÅB2ä‘Ê>í¢@ $h¢@0z²ºáɈ¥‹ g´¸ßåÝfÞ£¨Û·ZGµÿ,8¹þÕ1ùr;_ã 2@vž®×ÄåÕ1 ä;ãþõ2ÝĤù/…O9>_[ Zº~àÊ”¦ˆÄh„¥Ï’ÅœÜvżúÑ~S¤±%j÷yÿ_•º«éÎÍò%ù;—îz|ÝÂIÅ J[ Ä´Lÿ%¹æJ$¦‰,ÁüáÀrXß¿ ÈÎä}f؇ÖîΡž)ä¹åÞÇkò™À”Öãõn`x`ÁÂrxteµ â‘é›Ã§ ·Y ¬}\/u‹Y((óëß‹YÙÙÝ«/ót“š¯js»ëòÞN•2ÅšæË«ª` åµÂ‹s) ­wJe Óëùm>Ö‡­egôu¼“HJqõdÇŠú«p¬?Û9ªåa£MFïëG¯‚‚ ýÕr³¾ËñmÄ5œ†ÛVô@²Ï¤ÕoÈ5é"åž±÷ ±["ï.¨êÏËù‚)òàgÁ½˜BFÚù–Ú9ø7Ñ‚ÚÅ.øCD¦1ÀØÐÊž„Œyöš—Z!釂‚^ý};'÷ú,Ê:fÞ`Í ÇŒþ={Ò7É#®ã)æMƒu+Á¹J‹Ýèr,î'ñ¬ tgíŽÈì>â+bšÙ›Œìc-î[À$äk¤Q {߃öÌÛœœÃb4{ßB¢¿Ðä/‡x-žï<Ç .U^m,Ö7vÜšR¥C1äW7bÅæýûGM,çkç0 år7Îjÿ3¼Qª2¢¢F¢_¸ÿÙ®ÕÂÐt•úÆùÂoì|§yçG§=:Ÿ”fZþ$;@ÆOs%sQ¤I¡ÎF n§•j©™ËñœÏ@N-У噆ӧ;Y,Ú±5åúìG–bók è:W$\^;²U™{Ð(w' ì‘o;`\1£VOj‚˜,,Üïh£¶µ AåÇì±P„MÛ áº äÈjq,€ñe‚¡–ýñ™øeHòÈj‰í°/ {^_êÌj4R;´¾ú‚ÕÀHà¡ý°hiŠúë‘Z0ð*VCáuÚáŒ=­FÅÜ´ƒ›*vZ•é‡6—ä´]È¥_ç;¬è¦Ý:+¯ë‡ÓTÕ´ XÒ¨)›i5 *¤G¨MI";Üje Ž]†8¡$¨°ZÄD4TË £˜Z´l"£*AH0\j¨CM’TB0°y<› ÈbaÍ Çñe—úZ£*Nþ¦¹ÊNæ5ç¨8¿×wßvVð5׎úG»HR€3·~tóqM–ˆûKKAÎ@àþ<±y¡èG¤uø¦®Üv”ء諡ÃêCáB"€Ã]áõ7ßå°ô .š®ê†Ò«Vë(š9+WRÝä‹ 0Ú©ÿ¨ºI:ß/U‡K<´™L¹ ®=XÔ¢¨]¥n­¾ínî™–ÓY}ÁLM¸ÎC2üÔZ530—°9€Êœp ‘7–ejí€0™fL¤•¢µY¶|è/€’¶¿ÞPŠ Â )“4íõS-F­­iŬ‰¹Iu³Áè ¼®cÓLý¯QÁQ¹)ô¢¸?‹7Z¬Ô4œmDÇN»c°Ò%Y ¤h¯  ²Hç¸rê8ïKB¸ò_l"0/HË„–t†{  u"FxSD‰c5w•íÓ¹¡ã˜”tÐ1íZÍaÌ 9pó¨z0tó 7¨c@a†ö¬Q®A]ª1´k­Å-¯O î}ƒ”– X™“@°Ìk#Qƒº0sCÝ!šµ•ç4&Ñšˆ†ì™»ÇtkhÓ!ƒX… ‡Z$‚f@g˜! E—Éò&f¾ó€®tV蘻oÖ×\5»|!/bÎû¦ØØ›jWž>ÌކqB¡Aa‡Y0)z‘‚@UNæY“>îlŠõ°Å08aý{ç —™ ÷¯Ç|U›ü{+(ȃ P \Uw¤ÜÞ¢GW kGäÀlͳ]Q‡ÒÒ`@‰XlmG¬b—›D¼Á ¢¿5š áá‰ðÓÍüb7 uÓaɈ%9$Bȉÿ`X¯Œ †cŽDØ]*-d0À[R ‡JšâK¯åxÂJõøÞ5ªí.åå¥k´ØX.ÇéÐvÚ•~4ô 2ÓÛh ÅWŽƒìÌ)ò³X饤™¨t0jaøZ¯ÉÛ(ßê1÷¨cçt¨:ž ðàCº ¤É<'€™ù#©Ü4ýCf}ÍmL› ¼Žáö{ø¢l“^L¾&MõÐP²çÚ?æâáQi×ó8˪rh¯Sy­Žƒ‹ËÀz€÷wÅ9nÞ´6«…Òª€¼÷½Ð2[Å×a¬A}5L ÷îh{^  â¥!SÒÁ ߨþÜB2Ÿ‹­ª¾U{×Ê9ç`ãè‚£·«Áî4_ÇNÝ'³*ÓÖ»sÉȇR¨$å*Çr+<4 AÞ°•‹1Œ4ý­U“1Õív‰¤"¬ËAiFKÄŠƒ¥+D,:z·=õü´:¸¤’µ§Æ½›³"Ã9¡Û!rNQ“Dåš9íŠB(Ø0aVxwC–SȆ•—Œ¢ ˆ{ËìK5Ò/íû* ²5šÜL›óéð`C†u)ÐD|Ù£#A)?4e1ðÌzèÛ¦µQVH+7¨ëU¶¡‘7·Y·ìÉ7{`\&ŒØà®Ê6gƒ+PþÌ[9ãJCÛyãF˜²¡sÁ»»&Íóï‚B€°A@A¨Ê >r €ö†¨¸öwCÜáw·4úèC<ëÑÑ,=ò¡!_Èù!W{¯7^ÕáË R/¢%`(¬ãë a9€÷¬E"`kžlH6' 1 m«3 ûÛ‰nÀ›ödwÞÙfxhš“Öü tiu&x®SGIo–°Ò&ÿ¤Å£îñõdÅztÕØ>-9=̧ܭñS¾žÒu©?F?ì÷ÇÃá£>y&cñoò„Ñpô¨?™DÑd2'ãGýh0 }ÿÓUŸ-¡Ãu<:'¾¾^]bíL¿èsúç/7‹€LªÆ³zÚ'wÍåa(Ë+"”}üéÉÉñŸÉžäö °Ë°U&yf&`:Ò,ç÷õfs;í1 {J=#/WëíÍÓÕúª—ï8–iÙ2£Ëô)ù6]Å·¬)¥¾^ÞpÊÓiN¦yWçóe=>hÞ$-:£C˜‡¦ŸzÇÏOçÔý`° É køÆ)b;ç˜aΈ‘¸ÞóÓ|Jf”??e0•s7¢gŠwvöîÅû²VÇÆ‘é­ŽŒNqCÃJ©’•ÃL>KúÅâz•n¦'ý“>t\,|Ú£óìQ蟟_>þ}o’ü(ü?'–§Wn¼zLüŸ<"ÿ'ÑpÒñÿ]<îü_dL S0#Qú´? ¤3Þ̱|é÷ß—ØeÉSÓ^Ôïzäÿ´ÁßÎ~üåU‘5{¦ÔëøÝÏg²·•í±õ\|í>E²mW ¡öpöŠ„Ú:¿)–¹ðÂRµm½N& ^þç-¨î—£ü?Jòÿp8tüÿÿ:(“Á­ö×·æ_Î7JÆòÀ~Ô6®Æ[€xÊå@»òõ€ÃÑ{Ép à›îâðMwÄ´ðXé^ŒòÿP’ÿ£¨õ;þ¿‹§ýO'ÿï¿ü,Ÿ,ÿ^Þݽà= ÿÏßOWtA?­9' çSÀÈÿÇcYÿ;þ¿“Çÿc¾:Ý!p8‡¶†‚ë¸ÆíJðïBÎŒîPØç‡çÿŒDž~IgžÇ0ñÿI8ôÿ£ÁxÔñÿ]<¶ü?£“fZ€#W^$­ðy‘/Óî~°~ÈËaïŸßü‚¬cé…©ÎÍ“§|3ODûÓj}ócÂ<º¾?þû6^n˜ÌŽi¶wêÇ—±{•¡ãƒP‡úªXê®àãEÍÂŒ»¶Uu9 ˜Ð(wò+Ø)õë„#D¨ õI•Òß«Í5Í‹a[¨À5èãÍf=?ßnŠiæ‡Öq°e•÷n³” |šÎé´«z‚å rªóMróñ®*¼ÞÞíA/ŸöJ0xЖw/è$l”ŸöJŒç ”ÊVEö¿"ÿgIˆàŸe!hèúãþ?”ý¢Á êøÿ.ž†ú9ßM§õ¿­¿¸˜G¯ò—ÞPýbƒÝ¨÷;ÿ=<û¯  ºÆzþöGã‰lÿtþ?»yüèÿE/’ÞŸßusÿÌ©”©N±Ô–³§°KjxzR¦˜#À€SCg?†€)º.9/FL7w4`¶ºØÒ‹éw/S:Y-r^èïzMz–l°ªýøâB81TŒ|ËW?Ê¢ž ¨W³;;¤fÿ‚Hïk"ïÓs'ï'‹ŠòÐ_ÑQ¨©|Ô:qVʰìeͨUè”i4.ÈÊf ? 0”EƦw´CC\”±‡#1Ê•¿;ŠÜŠDK€ãàåBlFB‹€#áC¬FÂ+@ciê†Xíiµ´§š!6½C%A€îÁÊ!6ýCuA€þÁò!÷Å“ÊÚ n̨*¹~P\-ê /q_k†Vwq[C¬»[S}qˆè«¡Ü×ê*UÛÜVUîæÀVó!Ë ‡'¹â…Ž|±œ¼¿£ÒCå9…†c_#yý_Kæƒþ/"äø¿Q;ýß.“aߤˆ³0®×3ª› éG%Sx¡À*ò\>~,½oæ_’YžqœþH~½^Qû‰h‚mάýcfĶhÝ˺ïeýgxÓ/û]²Þ’Ïùlè¿Uc}19Ò}ŸSW«‹ 7ÎèNG+³N.sc½ˆq9<\ p*@„µ-ÉŒRœx¹\mò¬4 axÎ|þñzž2=f@þÎ,õÉ,8¿ :âjI'AN«W6« ^,V¿¥…= .׫›€ÙЫ£&¥-Ï“ ž‘.ŸVïþ+Cç.Âë›m ÿ*Î%ê®Bó›R}Ÿ;bñ~KîʤY² l&)铺l_nãÍuõkN±dc-fÅoÿ~™û:ÐÙ¥ŽKǸçòg‡®ó“é¹øÕ¡ã¤ w\üêÐqf@úÍD»e´ G´âž¾±kŸÈIö=a›r â¸TÎ2…î¥=öŒì…1 h'ÂÍ Âo8jå}Õ¬Ÿ‚¦vSºLÔéÆÎ3Ks,ªìþ±Êò /ÎÓó‰=*ŸE ñeÖOOéœ~u—ÓWO$0ÅûKg Ö™×K‘|ÂzH'låo¾}óñÝxõ~UðÛâÎøjç¸|±8Ÿ}UòR`Ïr-šnWhæ8âèr¾®ˆIy½0–Ú¼Ýw9 àPǾÑa®jà›Ï5ØU=´£§dy‚òï* l—s2fqòÄèÉÃ~2ž8YoæCG£Õ‡Áî¾ö𒹈¶CáäÜúÑ/tô]þ^«¥lß”ü˜óUþ'UÆsLX¼ÛÍ’Oµê팡[ôˆn›KíÒaR3>‡çò[¢ÅFM1ÍÝÓÉ'æ<Ãcy™<ù=¾{RÛÚæ:Ö'kÂö©3ŽÍ;éj1¿˜×{‡wùQÛ Š‡®og¾D Ú¬nÖL… j$Xçò(Œ×ÜaLÿ~™'éµÜ}63ÒЃՌL fÜÂŒj­=l,I‚fó“Éø¦â&ʰnŸã‡kξ1ÂymHçŽç°$ þ“W> â BÒîp`¼ìÔ¾°ùÛ|s]¨eR¤@}ÐW‘sу•Wè6ߤ’0ÔD-œ’óIEîC³²Û j;\•á£M¯D„FýÙ¨Ï —ˆsñK™ùpõ1ú¸!'}¬Oþ ¥LFùû¥J`¯®%¥•§€ì;sâ›´õ«¯2·:öhCMºPošP§S´}Ö.~¹»¹X¼Î²êßeà~Çðÿ0ÜwÁåÀ@ˆTTgßd¸+0‰ú±­S§é£þkñâf•n\•wc«éÄVbŒú²Ñ¯ˆÀ· ßÉšh xLˆ™~èkr3gþ乄Ì:¸Ë¥ê‹.ûRëÕÜ®W”2ò1«^Ä_Ê$7 0n° Z4þÛLVÅV3ŸhâFÌšÕ\dë—ó¥|íÊž‹²ÕÛ\ÇÍ追Úüw”‘$‹K¿+%ßdÈW5-¹ëHö&¡FU/4¥Û¤ÐOÒ­a>+® äÇ×?Š .æ5ª·Ü‚™„¡öã*/øjÏñÉÊfýÌ3¦”¥R¶À+в#“dAVÃÛfu,’Ï ;ø½÷";+H›ù:'zVÐEaŒ¾ÌQfFa„ªJ\<…) F¹u/Ÿ$gdŠQ¬Þo¯l#¯waLÇ[”‹ªiSÒL¯„¶„}ÊM4º|<˜­,àÙ‚tÇ=ÉGJ‚?¤IÂveñÍóìPùc#ìË8©Ä â8ÚÖ´º*2)›–èçª!¾ÙpÒN®ž$¢ÛKÖ¾Þ:¼¶›ÌRóŸ˜HWãv{¾ ")9ŸjaŸ•ÿF£î»ª÷¾Í}’ÑÓ¬™ Šh„2[™L”È*AªN<'ÉçB~¹äe7¨U• iT•†fœøÈ¥°KiÞµg)Š9•øg ™¥µ—vÁïùq9Ï.LÔý¹§y9׊q/eÛ^÷¤¹Š{Qd®’_Õdd*9m×¼^ëš}íÞkù™Ó r½s2 Ú¿r #C©JÈ–Bo=BÛŒ.s=ˆÀ¨m.Fà͈P… ¢}ÅÙ%×mPü‡}¸óYà2PuCÐ Ý#Û”Êd)ÿ†‰áæqeàL×,‹é.£H¢¼Bö0nÉu#J¼Ýqç3BqD\{Y*«ñAŸöò~þ-ûWGðoå×dÕ&Ûb…Ã"ÙéíÛ×´ËŒTÜ,@ Ô‰€¹V™ŽžæX^¾M®˜ý5ÙïW4¹ŒN83ߘ4—!é¼³•m„9‘> %+CQ=ÌRœjý狤v'¿âÔçØ3€k”ÿ‡91A]kÏñ ºË`0¥Åyý¡ùZøË©ýO¹¶„5„¾3ËÓ–œ¯6×¹mƒ5$,YS1Ç+¥ÌÌËÅ%ÝÒUë*ϺS¼>‰¾IÎ÷÷9½ØßØ×ßq§ÇwtéRfy²Ÿ<¢âjrWYÁž…)bky‹ÕG™È‚7(„T Å€Ë%aÉLA¥vŽRtùe~…êQSsòÈ­àÎAgy»§ñJ, ñXd1¹:#7gÉš]œýA%úIW>q%Îdºà¹@JΓ{@CÀ W`jH{ÂxðƒC.\Éö’*Ü®W×óóùF(´´åƒ ô-y×4î‚-‹°zJ:püÍ” ^密߿$³zoK#|‡ä”`ÂmÎÖÊ…î¡Íêöjxza»—`®xa3í&kÛà.· /-°¢Ò+¾f5^¨¶¢]û%à† ? å»ÛA) ?&‹J¸°ç¢VT׳¢NЕ.öº×~–5ñît“t†ÈYTm€ e Rm`B%ˆ¿Ï³‹x=ËôÐB#D¶ô¡ŒÆATÒÐU–§Ž`Þ¬fÉW0Q€íÇœ9^ ‰±Šma/Ù •Æ™‰÷|/ÉÅ„ü+½¦¾OdÓߨýày™Y×ä·òôéÓ¢qO>zØ—Rψ©:’Ô)©šjùf‚úW(oV[WK›ì½êYÂÛžÕÈ3š8 …\Tf›Ü1£b&!òüm¾XÐô_ÅBg~Ss¦¦>BRçóÙ,Y¢ë ®²­4r#Iç«Õ"‰—¸„w/R×Ù¾]m2§$2µùe läàâš03º•¡¤É²È…ö&¾£¢îÌkª£.)i²ÙP—T²Æ"d ® 1UPa}di;öb ѼÈl†[”ñ^rûÓEÊ»Þ÷+çYîm;)Þîj0KC¡ E9“A¿:|×j«YGÖÎ6^7ò¿ÑÊÊsýÙ,¼»jB•¹œ¤õŌèæ‘BIŠ-ÞBÚ°$*ŠEÉïa#ÓÌÅ¡:N¿ù7ê-*¸›!ÂhsGÛ­¿ÓjÙn„—‹ØîæÙªöƒ°Å{©tÁb×Pé»/¢Ðõ®ï(™ WU…sK„ðð+2׋HÜ Í×#LðçÁ@®Žðeó].¡§ BVEt¶3oã5yÐëˆè ÜQ@í,/Ÿ^ðë»mòí: ;ƒúU¶ b[eü(®k]^‰¹%ÖP3´æ†îk­w²Xæ\`úâW-ò|@û·÷,f$59>´;PÑÙ#w 4çþGÑvix‘@ØÑíÉjŒzéÅɪt-a³óÑpwøÇ:´qù§ÿÜÌ7[úÖŸª€-æ:c€ÆôUa–ª8œ  é#k+ll¾c_Òh~LÕøŒCŒ¢èà—£Qtm•mk~MåGÕ" c)û¶B VQy˱%Eæ€ëUá:‚¨ç­cÛ ÎRüMƒâκUfA2§±ª´¥Þ¸YU¾`Å»Oè¦+jÈW‹Õ9¡¯;¶ÈʳÐÄ™¶ø†JE´£l˜ê$'mŠ—ŸpÁô„«,€’þ‡†£00íÝâîi1Y2å7ER‚B.OÏ6ܯ]•(ƒàçoJ7Ï¡÷áãDÑ|ÖÑž¼5b+îÛɆßý²]Y„*wgÕŒ²W”å|±`!´> 'ûm)ŇýôÐ)Üûœ.W|ä†×+lÇrö©ˆsE¯óVåe¾IzÛZ·w7çd«F@“­Ñ·¦EõÏ–y8»_' ·p·¢ñìü½Ôý–û7¹1dDÆdl?òå–e¢Ï38ý‰ DhnŸdׄ<³S¼œUo—r>®‹e÷îdž`Öžl`$5-úÁ¢¥¼©·ØJ-iÏK¢æÜ ù7SæaW/;²‹s§ät™ æQ¶jq&@⡚s‘óßpJU6‹«Z—t‡)péü\m1eîà ÐҼݖåÌ¢åw¿ÌSMVÎo¿-SùÀ}Kðž2¾Ñr2šô·¹’àUmÅ•À»Êà#éÝóϸÛwež‰–ÓK´é×-нL`Z*Ÿ'öÚ»lEõ#—¼šCð]¹­¾c¹óòªEß<æUjø„ßÕRóYAøWͼ,“?lgÿ|BþÇJ®–O.VËË%çåUð·ŸhA j{ÇÌ!òHé(«XR£#jž’z‘Ÿk|=”<+ò™ »ó p)wàÈÝ­–Ìy´áŒnVë$øõÃëâ3%êìK*&'/Jeú–~øC†‹4¡…ÀIÌ`þö[)Q4…»ÀÆM|Ä··I¼Î‹x1­;Ç€øS°Y £¥—”32&@-Vé¼*¼T”$¢Y6—Ôg€²"ùå¼Ü‘ÖwÖ.³âA Xìpªµn˜²Ñ´(LdZìݬXQ)¤PiçŸZ\µrŒëÖLÑÏÊ›È;ŠßÔˆÅÉ.íê .æýŸß“‘Š"âäǬÊ&øhÎJj2l îýxÿºkü‘&v?q^cu3ÅðJ‰/WÔvK5Eç›d½¤Åóe^ ¸¬ÜÌð¤Ó„ñ(¼M2õbÕ÷«Þþ4=zg9Jé+Óé÷ô/¶¾û·ï²þñƒ€6eªføîi¯÷Ýÿœm’[Ú¾÷]öÏ¢=ûPµÿîéwÁ¿T†üHЖ5©>•͘”I~÷¬9õƒï¦ß±/0×sö°¡Ó)«Ø¾HW…œC¸«×Q±¹zàÿBfþÇ?ÿáȇ¤ÿþ—ù¿\ü#ýûÇ¿ýË?þñü·yúÇ?ôìÚýñÿð/ÿÖRÏüÇci¦ùŒD*obÑmpç5ó]Vc)cºÙ?[ä¸Ù»%ì–¡¢ãµn¼6¥|‹²Ù ÎZ^ÒõDSYH¬úâ:^^%Sî-Œÿ!c¹”œ"œôßW1Ú?mòCvÔ#œÎ®å¿ýáåΘNÿíßÿnúGqÞ‡ÇaU-ÖoÉË:éG—j¡´…[¤QÎûÑÈ®6¼þ2lÚUÌ@ Z™¤>ªEw4õMÞ_ú'V¼Žr˜Ó0‹3y—e¹¡‘³,êﻜ¾{ZNÚSYú¬‚bM YÿkYsQÔ ˆÞ”ªà\-sAãL–ÈmQ˜à'nÒàS´ °ÓŸZ¼\7¨™9s —ô©HÞõ<_D˜ ³ƒÛ¥ëm[GQÙ(þËO-®€¨æ»gÝ’%K‡;È„T®‹â û.Ò»t“ÜìNA¥¸;ä [*ô[çä†Xwù‹ÙéDNðõŸ˜\üúì]pr2yVëlÑþeH«Ñ(~{;_^®rCPþ¡œ˜Áµ±(…!p_{¶~,s3gÏ–©Úa[ÔûHò¨ÝI ¦i6yŒ¦¸”€ÝlYįÚ]q¬‡¿DÂPx§EäΙÿ¨pÜ´¸·dÓ’ÅÚUÇ Øcks4Á2E`­ Z-WLI[liÚ‚"ì$²%•u«GCÑ¢Ô3É;ÿùÍ/ÁY昭7¬wBœþŠÏù¤IgY_gd§^l¶ä9ÎÏ$æ‹]~—ÖéEý~¿×?é•]=ý’æ9Àñªþ?¼zù„Pí“ðÙ³“~öu£§ÍzÊ;t ÔÛ$¯*§p#ëóþí*ËJJó4[æ–—ez‰Ó€:k²´§„:׫/ó›l¢ä—ߚ•¾•l ÇPºn넪¿ŠjîJ¹HÊmƒJæ˜wPzÀ)/²×Ø¢>?zÔ=ûðdËÑ[]¥óÞïélFt¿ù£öûãáðÙÙýÉXü»ßM°ÿ¨?™DÑd2'cÒ~4}¿`ÀÏ6ÝÄë xDý¬×׫K¬é÷}NÿLØ_@¦FO£ïçdã“]½¢¹–i=Ü'qz1Ÿÿ™ìÞxò$øo^ϦAE'ú„O£€ðìA¯?ìõà |6ö§£0Hãåìzµ¸ ^}¹ þ›àÉ“ç¬Ênþ6xÉ;y>肱ý-9Î’õgr¾¦ÁIz±ž³8¤à;ûñ—?²ó¯¼lpê®N®:™ƒBvÆ‚ü>ƒš9á¿\ÝÞ­çW×›àdÐ[­³àoäâÄ ZÂÕz3ßÞP«}çoâ4/®·´K¼^fi™Bïcrq½\-VWw ^m×Dv!lüáÌñúâšë«(gúzI“ˆ€/X½àM¼¡˜ Ÿÿü‡d¾ ~]ÎÙšlîþø4x±X(¸)ëtý9™=eåRi_¿¯Ö¿QëÉlžæÌwPVCªÿ°þcp¶ºÜüN³jÿB°º$ÇÌ ÿsïk.ÕØÐÞæ"d4ÉD/·‹ìxúÛëy÷ëÇàÅÛÿüíŇ/Þ~üÿ“ Vä×äs’uE/ƒóÌðKF[ÇKr±%èyóêÃË¿W^üðú—×ÿ#ÕþôúãÛWggÁOï>[ëû>¾~ùë//>ïýðþÝÙ«§9Ö)œêjVíý’\Å *4D½‹bUŸ¤ùtŸÐïÃhâýñÝËÿñý« <‚ÈP?üòúepü¤×#hêõ~üø#%˳—yõ楊tÚ{õö8€Å”“Qf*r"?:­ ;k™N¿¤ˆ˜Ã½œ·¥4Š´&,d4|,‡l˜_ÈåÅŸÑýXDò•±6ÇËÚYþp°dËÜçR´:àÂuŽ5!õ?ŠNõ"Ø,ôW41¥Š×‘£Ñ°¦’ÌÊyðÅ[a(,y½cf ³ µ}žß±Œ«%½‰Ð_ÓÊJ™ýD6笥(ëŠÙA{"†s­® »ÍPŠš*‹jáø\ÑyM–óE£\Š<¸—%È_,wDž·1 x«bÄòUŠg³ çÁ€îËš°íø˜ÛE/„›i¹)²$½¤Îm^_zæ¿È®J“Á›úÙF¯9×I<£ÇŸ‚¸È6›e¦Í¨"S˜–}Q¦‹D6V£ «»!ìkN#@¹WcÖ´²š„Á¸•ÞƒÄö8§´¢o6ã”N™¿ù´c`âÌWK3w6»ßçé5£Ðl†¤Û8¯ýLߦ=/ËWèü)µdo^Ókg¶bE 6€RC÷HI ð&½z±œQXJ‡ŽH¶ÏÈJã+zSŸõh ú]1AÿØ+z&Xü!«€òø'}Nó‚/Î( #RsŒæ·ŒØ? (Мf“÷Žæ|,B· ½-bž_ËbL±r’agÔí:yÍB ^QKƒäóä’FÜÓ®&³P‰^öïl6ežYë|y¨H£²Óz‘ÄÔ}¨ôZÜ5úѱ˜òÂ[|¹É•"Fd±î©ÞC&Ðì67óÒUº9pœ èaýý!¸]Q±rNk¶©¤ËY½â°êåL¶×”±j®ëdÁ2ê“©òÆ_‰¼ppG;¸ÖÉR ü˧ï× M$ü`0TlùL|"3ked£?,œel M”=$tõ, Lnu›'ái w„Ý=(äqÜ®mÜ=$¼õv„±7.¯Ñtˆ+®,·ÛÍ¿¬¶òWk¨ü‰Zú¾d2‹fˇq~©Áõ8çªÞU6|SÅ­VŸø@NâB¸‹ƒ¸ÀÜ9‡KlûÇp>ÔÂZ»‡p‰¯C?ƒ5(ãŽß^+Ço‰ÄÃ?}hÜÅÁ›kÑs7=Pó”‚h/êR =TÏ·zJ˜‚=ßʻҪ@Õõ=(¼ñº>ÿh»}¸jŽÊÕ˜_ôœ¶©æ2K.Ìe˜y­‘([ãÞ]÷¸ï+¬fñò…Â5ÓSЉo’<]K‘“÷U4Ò ²¼E³¿äS—öÊ‘‘‹[šyè²¥·±ósʆ<ó}º%‚¾œœƒbå"úø±HÇ,/[lÅÅÁ.R©è±NØàã2Éa OÉm¥×efGõ¥ xÙÓ€5 y$äsãGàÀ¨EZnN®‡,ªMÖÔic\ \ý1Â×é÷/–w„ùÞ>a^2 Š5•cUƒ­âÑ´®Cö:«I±¢ÃOXW £ç;™/™ûäí"¾Hžf}œm/®±âf›R¯"¶8b˜RŠvSú–ÒxˆÒøŸÏ:8—‹/b '½Ê}U%:ŽPJÇŒ4 >Ï“Á›ò(×Kdå1K«úøñc-KcͲqãܬBJÁÎhsŸ€—§ùûêA//)ðWm[›DqÞðsø¡:ƒÀwŠ“‚ç¬D•`¦ž°ùÉ…0ÔôüGŽØò¼P§ÉŒä\A:ZÒ@—5Äü…À­$ƒ{B© *FÛÁDy>·ˆHzã0C«/¡&6q[J8JUÁMå PXígNe$8·èöqqîÛ¨Ø'ùdÕ®ÝX\Fżaîbg¬³Í„á(×'áXvê‡&%¶MÏh­ScµÄ–vÈ¡<°@_ýøjžWŒ+ÏÏ*Ä.x÷!«rÆ|/Êo¹RiÔS—fÎ:'|æiÀVýÅ‚æ³2fAT•åDÁ½êï÷ë9ëY>9¾—åuÜ^0o`Ò#Í‚¾ºÉÁÈ‹ðuî¸xv Y?]Æþ•ëh›ô5xênDËmˆo‰|;TÌV®OßœÄá>rpL~ª÷²áD}c^Žʑԣp¼vey7ÙÙδҵ(.o»Ôµ8¼£ñ©®kÐðx™³Wµ¨®nû@Qðuoн‘[¶ÎfÙƒÿ¬NÔ¹1ã²@ ?ogWœá –ùN¸’K”ÏlÕš^¡—˜}V}ç§ìk[ÆðX!ðÇÀ ß=Æ™8áGt@Ų[Ühhë>‰_í@9Z¶Ö;âb;ëÇX­X&©¿èÓ4·ºÄåî|Àë\ú í^ŒßùJãê›ÂMP'‚Zôý’ÀO×=À9ÇeGùû‡Âå¿ b޶½“ÁkßUwÅ´ßç>¸/²ÅEN£íEˆ—Ñý¦òž±—t±N{¼_»>ôö°~?d`™nô O½%ÈHÈDœãµÎŸvÃ\vl*©EêâÕ¿d×÷6¥ìÝ,ØÃ•Uû6%åvd\Õ«]]ÑÂác¬“€7ùAX(¹ ³•Rö|¿r´RBNä{"Ô¶§X~,§ðkßý•\òÛÉUC­Ò•Rq¾Z-’˜ÝôPjxÅ›j_B‡4°ú82Õ3íΑì¤ÔM©+k•'òÄôiðzS¸„¥U‚¤•Ý9ï%³>Ï3×Óåf~1¿eœžKÆÍÓÞVTä^ W'Ø@^¢ŠH«e`±3æ’Õs¸ï<öÝãöðõè>ågÎ'æ­ü‰Òú®øî)¥‡1ôõúaIõ¢A4œtõvñèë?üúñ§''Ç~þÍÑ)”±çw?Ÿ½ÎEÌŸ)±¼¢´¢ÏNµžÏëÜÞ°$õ¥`šç«ôhŸ½Òy™%Å/;ÈË=¥•©Vñ-ë‚Rd¯ÈžOé7?îF-4½Ñ1ÌcÓO½ãç§¹'páJ¸'ÝLEŸlçIéÝÁë=?-„Ý:ˆ‰åy­¸F Wä%¿*`?{_Gc­›f¨¯ƒ7¦A{¹º¹!7&AµfY)S¥Œï«¼ Y¤äãü&Ñ·KzíºInÎV½/ÍÖéë%Û¬>`0Ë_­âpÅ2¹à¸|Õxj ^ú™‹R&m’%¹òe:Ûàs¼Ø2ÓKÖ­çºÂÁ’oîW«Õì§õª¬«Ì& ¢¨˜+ÔïäF»pï"þÏñù"±ïGêˆI1yo¿Ì/YÓ÷´N×z3ORök…séjÌÆ©ð€éä±·r˜ë¼&Ï|÷´'ή˜³¨‹dþìT÷'`íCñ­€v^#+Y²ÞÄ÷îa§=^UÛûãuR”0¡!¶›²²Ï›_Ï>²Z<™JªÀzaù¨ã %›k‘ˆ)/²2EëLã.á+Ã=cÁÊKº^’îX As¬*s3lÒò•ò2Å!tõдúš@9ïP•Ê=ImÈ­—Xj\E‘p¯ãål!Rí_ØWÉ*\”k£á¡rixžAÁÃn:«µÐ/Ùwè&Êù ת„ ZÅrD82NTTW{&ÇTÏCW·pï­°ýo’õ%_š)¹ãHÄ€BÕÎþ™ˆEAÈêøÆ°-èŒM8?U"¹Jq& ÙW˜ÅßTÒ3Ã\š\5À+奩sE©çqlÃ90P>&k²œ UøQÎeš È|[œ¹©‚¥dòØá†¼A®w7·EŸ¥dVçx!ˆõÝwg•(Ï„fj¶©(‹ÈÙyÉ&iÜMšl }¨$ÕÃWŸÐ§RMYµxÆ rywIÞ7ó²ü»tÉÇqµ‘Íså–ÿÕZw;åÜQ\UïÊ‘ ðr†V zLÓù@ø‘cT)£þ´Èt8?%œrxÀX_ ¥©¾çV{Å4s$¬HQ›š©Bçlë3}ÁÎ빈ljo gô겺'Ô«Ñ3jGÈ‘ËÜå n,3+ö’áŠTµÑ ëõ…ŽYU=¾€)WŸõôý‚×g2¡õüŠ®¸ùX³c\P5ôg@[Ž‹˜»èš5à•ú]Í€n_’oëc¢ì¹T!Øžx—4ŒâJP+ªcг’FQ—†#¦d)±dΰ©P ¤‹ {`©„íÜ·«Í#Hf?);ô idØ´Ú×õ^ʸv*$hê‰L2êβ™¶æ¥=›4Y™³í-µ·C«þJÛ´à—ï™Iëõòs¼˜ø¨ü,pDH9¿±Û™‚ûü"^ÏÈÁDWã¯óÕ‚÷ßçfükeXmý{{0ý›í&ÎhQ3û7H£bÕ9& $úÒ½|ÿ¤~³šÍ/ç8ÀÛhÀôæýã€NS3õÊφ#/ì¹Ï—+r;¹Øü•Z{Õ©¾V7±6ì•=˜-M±4?ÅóÅv Ìö½ú»i¶Ø+g+„ˆ¥N¾0͉ £Ä5À\'>ÍoÐ^¯¶¿./®ãå$F|Ôµ4¨Æ—wLAÀÛ”3cb@.Ï«Åçdm¯rþá.{Õƒú/³î%›g­›ÖUº~õåb±¥¸³ìß“ »@-ie½,L´ Æ×ÞB÷1ÏÃìMˆ+Ë? ä…=`ÉËÕ‹ÙlžÙÎJW…ôEá¶¢Îý­Å lXw±ø±ÄŠ3.öëd6§â(Š}~4Ìl¾Ó£ZËcÚ?—+Zr — 2’6’ø‚#Jí¨Ø×ôÏÈ­Ôg¼ÅZÕA†òÞ¾â$Wìý%N J£ÙS[Ù©ö÷ö'›„ÆàÄëùâî×eŒ³Ýx;Ó•Ððf;˜©©(AÓ™<ó­Jtz»ÚÌ/çY`Pp¶Ú® QeoÏ©ÑæÜäsVµ£?š(hí¸Z€“ k¬äB›/_S/8"ĕ˰--¡ùó Žâ/rG™2§ú^ÔVóM—G*û´s‡ßŠY½ ¿sŒn¬®\%ÉÀ ÎÂeqáÊ;»Íüñêû’¨Η¿Õ¼¼ÊüÛùº±‘Ýõ¢V"µº¥„^gì¾^¦›˜4ÿÅεìÏ«™¾æQ¤W²ÊvÔ:Ksr£äßö '2/ú÷ªæýSL ÝÕtr}¹N±ž•yT0G×zÌØÂuÅ ¬--ꥥþ‚M#}mðo†1Ü”1óØ·¢µ é¨Ì¬OÒ9ö`­qØœHGïã5ùLFµpxu%zJ=úùY€ï6炵V@°2¿Rî‚ïX¨âòëÑ‹Y¬ÙÝ«/ót“¢×#µ•Ýõyo§š‰bAóåU™ðËŠ†ZaOÅ¡EÜÕ;"Þ092½žßæc}ØÊ±*žþåÖ²ié¯ï ˜ïÚK¥Šû»Ý±%!Á|p©þãf’T=ØÑµ äñl<´MØy–×Éã˾ËfMö›®3WÙ­×Añý³[Þ§wˆ§þ£êgy±TýçìÀãK@¶:LrYEMy5W…tm·¼«æ™ÓRaÁ BNت#kMÃU33Ü|bdPÓÇ ¸1X,L@+öH–+‚ãö#Éú|ãuO±&Ø¥(ÕíÐv4@]D‹ 0£`FnEÑõ¼Ú´t¶<-k]—†c áá)Kääc~¼LÇSÎ9Ï~OZ9¤Î/,¡Yu_~ÌÉT§v.4”a˜óÄ‚¦ÝFTÁxâc€ù I¤ŽÓŽ@=ó TØÇS¹H€½Œ1-RZØwƒ .D3­H°aÍ8ØBŸFºü'2p´¥ ¼È+x G‰•Ú€ƒfàš!”FDhÁÁ3ô ÏJô!Á´àày…g<… ÇtfÓ§½òøPO1-¤z„D£)dª)ÁŠš B==¢ñ4ÛTã59­ÔG4e´X32·#-³¹cðØFävP™HCŸõU%•p2µ1rVÝDPI'<Á†GH)tF¸‹ŸéØÈìW¯Æ.at<î5$Õ·")·£¼>I é ö‹ øT€79ç~¡ãc ÊëI Ú ªÈí|GIjhER·¸–¤à¼ü*%²×¸•P:Ó=Ì“äA1Vä•fÚ¹ y¥ëŸËW9uäñ”÷`À/`ñ*£Žlv”³è%l¨^¡yx~zU˜Ç4Gì\áÿšÎ %7 ±‰-ìò‹¤(¶TŽÌš†s—®P«“¿—yR~!@pRµaêabÿ®Ìº\ïlØæ€)Q=õºÌLõƒšÚAs²™ñ^UdTZÈaœ1 å ]-™„AÀU©;Œ@í»À$[a3¿8†;Aê¡ÕÄ·ïtQi¹Èî*%ÚH&gÃàc¨àæÏôi!9nÆÂd¾HW>V>ªÇwªA:Ô'\ªIhyªü$Òáæ´'žH4"r`Ñ«ÒÅÆ€6ȳ‰É ?P«Â#ìÔ–äˆ;ú ž@­Iˆuœ€jø µ&=š„ŒžD­I“¸CêñãA΄`ãéõt ‰¾=>LW d<ɬ „ü~Z²oY8 ™Ý‰šZ¶PÃ暆x®55fá¶,=z;š-K‹l(›Gw¥µ2Êz׈¶¢ˆpÕ‰â Q/ºG•) VèÑ2ë¨ŕȑ?ˬw…©_ˬ£®W•6²Ìº+QAhFM-³Ì*<㦖YïæAŶ3³nd™Œõ–Ù_¿žÁÄ`™xy'þ,³GGevð̆4ÎŽWËl„šF#Z90¢=«i™¼Ê…ƒ~6´«³NR¡I9ßøýZf¸eáGMÎy€ êZf^OòÁ°ªr;ßQ’²²# ü’\-³¡b%E.E~Mûadkœõí›×έȷϞ—K‘wϽF&ÚöÛí´™©­H—Î[kýwkv[Éxr-Œ{–—¯… “ÔNš—´íz!^ë}1wHÝŸ7ôüP cHѽµ¦é×¾uN"ûå$b 4… ¾Ëˆ«ò3²S~úÉk§ülõõvÌûɉêçœw#,¬±Ï°·K™x Kñª4 O|‡¥xw‘n–âU-õ+?›H¿©òÓ¯„Y)?™u3åghP~ú½+"“òÓ¯à3ð¨ütôõÖ*?­¾uÞ•Ÿ¢H§ül"ÊÏa]å§oOŽÇ=NR‘ÕeÚݼã9, uÒ†¥ø5èƒ }}XŠ×“· ö8äÞêò|ÔÉÙåùö¦Gìò|;Çuy¾uÑB]žï.Ïw®¦èò|wy¾}Ùnº<ßÞõˆ]žï.Ïw—ç»óUê|•ÚòUò¥C4z ]Ãì»)7Ô«/·k‚¤9«ÐˆkãåNò§óåo@ªmUM(åÚÆI|aÂWË)Ä]iÞ©Ž:ÕQ§:êTGê¨Suª£NuÔ©Ž:ÕQ§:êTGê¨Suª£Nutª#@UѪfæ&¹9OÖù¨.*š6»X- º6zx–^f-ëèìUF¶¨ÓuÚ¢N[Ôi‹:mQ§-ê´E¶¨ÓuÚ¢N[Ôi‹:mQ§-ê´Eû¡-Ê7›Žÿìm«eº‰™.†Ó¥×óÛ\õòak*Qÿz¥R#9‚^;Ä2aZ5³J©Ž.éCr5'BilfÃÞtLëäfõ?™O¦Y˜ú­Hö, ើÖÛI€å;œÙOþ+ïj‘xsqMoÍ0¶äŸ[Ô€|`$ƒƒ¢üÞ¢þÃæ~ߎxd©)&r¶ªØ¿tm¥,ö.S·# y—ªý:ö›y/ù,tìšnì±Ð±oM“çBÇ^-(ÑIÃBǾÓô4Mqç»$iC±{¶žû,=jÒûzñÐï{4ÆC¯"Î0ò§1ºkZñp`CCgÇ«Æ,J«Ñï¢&­NcüKÒâ$u¯UiãÙL£Ò{1›íFGêTwû¬ºËu:,??O°kÞ°5Uޯ˴X˜L õš€°¾$}@Z{PÿAPŽ)‰H.·)Œ6éW?ÞC Nã,øz®¨>®[Qݯ£ÕÏå‰_^¯ ƒ“VŽ/¿NWƒgVg—ómÁOEõ‘eEu¿¾¡’Ã;â¼îñpÒ’‚ÕwJz? VïNrjúÎD¿;W[3•`“2Z=Žr¹WïGìjúóVQÖwÆÊ6K$e&—ÝçØÆ…lÞPKÂw¹;ø«¿oç„à“åE1Xíôš½YBöœN€´xôàŸôâ:¹‰{™ì?ŸrjzJ1ãiŒ~Øï‡ÃG}òLÆâßäŒ&“GýÉ$Š&“q8“ö“0< úžÆ×>[Bë xtNÈm}½ºÄÚ™~?ÐçôÏ„Cdj4KaO ?#û‡°ˆå¹…|üéÉÉñŸÉVá¶E·Î$® ;lÞ\¼>§ï¥…Këe/‰¦OÉ·é*¾eýPêìñ­§”xω Ãà®=~þf*tIG3CA?õJ©î†2“`±Êò®d\êSÑ;ÛTùôY6ÀX qq0ç(äV§ðÓÈ0ÈJqøâ:ÎÞ½xÿCöuqp¿R¯‚¢;:ï)9Íh†nÂùDè‹ëUº™žôOú”µÄÅ"§½fvœÁûK¼œ-’IºZB ø2‡OZ^±€)ÿ%¦u8Ô„áHj£û€n¾üÍirq™‹LrMw©“€¨´¹Ø `ÝD¼¬o€ŽoêÒâËçû&`*òßeÆ·v'ÿ…ò«"ÿ‘¯:ùo»üW}üÞ/¤8L ¤&Ê7ÇöÂ^&”±+[=y‰6øÛÙ¿ä·I2…cNhtÐKTž¢™ûž^eâ^) J•tÄypÈœ7…úÆšPÏx7¦4aÈΨ¶ÏFµ|‘^,È’Íî^}!'dªquPÛ¾w¼£?åÐΟ²‘o à céOéèx‚»œ´²ÁTPÏOþ”C¿þ”CŸþ”CÏþ”Cþ”C¯V¤¡oÊ¡WóѰ¡?åЫÙhØØŸrèÕp4jìO9òêO9²ò§Ý?åØàO9ö+ Mþ”c¯ÂÙØ£?å¸ʱ•?åx?ü)G5ý)G~ý)Guý)G^åÕQ+þ”#ïþ”#;ñµùµ¶›Ó¨®›Óȯ›Ó¨¶›ÓÈëI>jÅÍiä×Íidåæ4º_7§¥›“»'1ì'gëæÔÈ?O½Ñ·äæä݉ÏâÁ«¼:hèæäîÏJÏVnNîa-NnN¹0@}ž =aïkôséøÁü>Í‹|ú%yÃàÿCÙþC>töŸ]<¶öŸŒNšyúpŽŠœLÆ:7œ ¨igBG¿Xäµ°÷Ïo~9có8._H2wŸVë›Æô¿?þû–œ&—ó„ÆQÎ|±º¹]$_ÔtpæÙXºàuy‘ö¡ÓxyÇ›¾ý–|¡xB.›¥ƒŒØåi¼Ù¬ççÛMýoá~ùöÍÇwÿáÕÛJ@”ÓfEã¢Z;Ò´±h¿\-ß&Wäx¢¹>6ɹâ/3*^&ujpÇ_(Նń8cî=н]ú³oŸ¯V‹$^³bI3?Õ†ÅÜŸÕêýÓGÏô‘9›æ^«ZbÉI±41H]ð¨Qúç3؈D#Ë {ÐÿϦÈQèôç³éíÑЇ•ÓWŽVôú Yꇬî³w_ ºÔy%l”Mz×'ˆ¡é}¥î‹D&¯¤!÷þ Iâ!‹=€D〛Òþð¾Â÷³eæ—ó IýP¹_q —/£šÔÜ}Tlµ‹+)åŸ?Üeã¶ÀšË®4±æü(›ªæF ´²"Ë·«³ÓÅ‹Ée²¦ïôÅg"ùS{=:žÕ{–Ô·éhgÛ‹ëüP׌¢´ªßûÙ&ÖŸxc«±òÿ§w2 ÷@c»ó3¡zµx=_ÜýºŒ‹¤kn5Þ‡d6§×[Ý[isogu§yëDÐNóÖiÞ:Í[§yë4oæíAÞ=;Í['ötš·Nóöur?Lóe–åTnùϻеIYä¼ÒªØ÷ƒ&Ї̋ñÔo¸P å‰ëô,‘ï-‘wz–NÏÒéY:=K§géô,‡xÓèô,ØÓéY:=Ë×Éý0=‹¡r§rQ[î$ø&+5sî›z«~4¹vœyŸ8s§géȺӳtz–NÏÒéY:=K§gy7NÏÒ‰=_…4ßéY:îç¦g‘kcZÒn:–Y²˜NÖüÐÞ%9u„‘oíåÁ !cËĵïòÑyÈÇi§Eè´¡Ó"tZ„N‹pˆrt§EèÄžN‹Ði¾Nî‡]Sù¼Ó¯–<>FiØ]Lˆl2‡î.¦ÝÅ´»˜vÓîbÚ]LQ4ë.¦ØÓ]L»‹é×Éýl.¦6wÒî:z@Äúùrwí®£Ýu´»Žv×Ñî:zˆYwíÄžî:Ú]G¿Nîgsý\ÍÉñëÜy±ö»¸¦®“›ÕgÿdÌ:}ÐDûùó›xsqMošÙ(m¬zþÀ(Ãеڨ‹™ï¶Ëþn—N‹Óiq:-N§Å9-N<›y^tÚãƒ^ð}v­–äåÍKš œqU­d¦im5گ˴ÀÄ›äæ$—¤%>5¹É©:5ëW®hèÔ¬oïÔ¬šõëä~•šµ7KsbåiÓçGþÉ´µ=ªfÿù´ä;|J3üéŠê…‹OOOg‹:côÃ~<>ê“g2ÿ&O Çú“IM&ãpBþM¾èý¶&Í?Ût¯ƒàÑùês²¾^]bíL¿èsúç/7‹€L-e|,|Ú?’åÅŠR;‘|?þôääøÏÏN9²Ï·„÷l 6Œ¿U¸ ¥/‰ä$u(–©Ö†@©®—7œòTš÷Áh4ß§º!ó&iÑÀ<0³`.2§õ‡7Áb•™Ot›¦Žíšc€Çê@$ì(ïÍ€ôª:¯DƒOS´?ÞN¤ú=°`¯ä¾NÒ”CO>IúÅâz•n¦'ý“>s\¬}Úc\—ÂMþÊ¿”í}ï’‡ûèùÿeVe¬6Ç=ÿ‡£Q(ñÿp<Ž:þ¿‹Çÿ/ŠÕÜÜþ¨Íù¯è§z*mð·³É/2d Ega÷ùQÀ?Gð©ðô cùö#õž±±[§w/ùÇÆÊ}YOLüÈpi|EÚ,ÓÁhú’oøš6x“ý^ž·¤•ølÌì. :}ÇZ¨£ŽŒš ûü “©þê\ŽowÏ.¡œx…òd _¹uÐq÷òª¯P=+œDÔÂ}`š%lÏ|Â6ìO!8¤1‡}×1õöùª@²ÁúÓ³¢ ¼·œ·VX ‡ìªÐ'ò£vöTä•x=í(¯D;UÕ^<^¬¤fŸ°ŒlöóP˽ÙC“1a?|Kx'MšœêVšL¤Q‘ 5ñzLNÚÙR·!ÀÀ|ægWMÜÎ ¬“þôe¼†]\$ÈpO˜¶7Ö À…SÌ)F‚ ÷)aóÊÆO¢)s¡™[§q¶)ÁóÊÁOSÕ÷Ff—€sN WÞ}2œ®:8 3O Wþ}2š®=< óO Oñ^…gls œ83k;¿"ä(y6šæž0ðòÌïMçÙ¸9<žy½ã<›L1XLƒJÈÜŽµüVŒÀwbCÏœï.nŽ ©œL¦àW`Ò9i"¨¤sr‚ Ò‰×+ßɳ©Öþ&³_½­®„Ññ¸×”ÕõïY;×?Ü^Œ±ŸXÔì„59ç~¡ãc ÊëIþlÐU=s;ßQ’Z‘”ó!^Ï·»º›"—"¿ú…I(‹Ýм ¨“– ¯Ô=ñ¤j˜x•W' • ¯ÒêÄJÝ0ñ£oèšóç§L?-5é ]‚YŠVw Ø÷¹v=P3¸hTñTm®"Vö?ш]{ ƒý/êG‘dÿŒ¢qgÿÛÅsßö?ÙÃÍ$§ÓÜyÀlnôïôÁ[Êí¼<¨×^ƒGÄ(¶‹O ÛO7U«RµŠÚ%©¡åmâíhÕ_çÁ»ï¼’ÕÛÅN:zÜzÄËxìd‰> pnˆUºÄmwôÙEbw‘Ø]$v£Hl€Õ ¹Þ.tØAÔMb45lŒ¹7kz¨F>Â+Uu‹£Ü›Õ|ÈrÂáÝ«EFZ±œZ!{C¥‡Ês ÆûÖHvÏ.Ÿ\ÿÿöl³zÿÛÕÓÛ5%Í9ÿ/÷KcôûÃþd4Âø?}$þ?†‚QÀÈÏWÎÿåõ—ø¥—1ê¯ÿd8t뿋ǰþWiú‰ý–|ºX-©›@fêOT°ñ1È£Ñ@ZÿhB¦“ÿvñ¸ûœ1²`éø¾l^,ž/æéuîM€û؈i÷¾áF®ðôK: ø}ÀÞ"c†½~óË›Ç1uS\Jž>í‘ÿ×܇:w{q>sWcÿdîsdÓ åžrJ¿}’]Ü ¬‹_æxHç‘,J’9ÍRþ¸ú-Y¾ú’é\ oš ÀékÒ&§ê¬iÖUï•.= £9W€øÞßm7ÒØdÝ7óå61Á_v°ç&ðŸö*"¼£—“ÖÑiîZÚØ$œ îËŒoc²Irh¿?&;s ,aÖiJþÞ­A¡8íåcY +º/ÛŽ[!¨æø/!tÛL¡Ã[¡À@'F8þáÉ“€é!Óàɰ7 íqžÞPJ´ý%P¥Ñòb=¿ÍØLF£Œê6kê%g"¦PÏ ùµ—¤ øñø>o%ìWMÜ15“»nË»ñ€!<00t9Sls¦ðÊi—`¯ˆÖ(¢²#< „žßÙ š¯T¨jÌ Ñx•¢©a+Ûmx „ûºáaöÛ•mÙŸÓžØÉÁ¸û+Ûý¯^€áþ7QÝ€pÿ#7Âîþ·“ÇöþÇÈ]½¾ÈåÇò÷c²MÞrÉŸt”ñኇßéVdÀæB穟›L ÷xºÜˆÆ"_œo7ÉO«õ Á(å…ßÿ}KN¶Ëy2“ZçÖöq§åÅéôbus»H¾p¼‘—÷sNHù~ ¨$¼¯Óâ§Ycùš­Ÿ3Fl4[DÒùfìq)e­vÞ:¯ŒQ_h¶ºzz«2*”qSHiì]«Å¡ó+G/¦¯Biµj:uŒÝ²Í¥,t>ö wÚ«Ôü±S|Üw¡°±þŸÜˆMc˜ü?±œÿ{ Fü·‹ÇVþëtÂNØŸNø¾©¾{Ч1ÿ¿2«Löß¾jÿ¥)Á;þ¿ƒ§û¯xEmz^@wn-ÔÃ1Գݱ¼i©ãði@.¡hjHÚ³$窌vt.(q°¢Dsó²b·4œ=™—ëŽ[¢ÌŸyÙLÍË.ã£hxØæåFV+g³%]ý>Âlà›"ˆD;› Ð¿¡±bQQÇæN5ï/J,¶„IJ-aj Ál½<ÚGUU÷´ð8Þÿj•4éÿJý§I?ìì¿;yöÒÿ×¹,`Fª¹&áa ÖŠHó”8ÛO6UëÁ«”Ä× +hÄæTÓ§Z@P/¬t%ïåqäÿµ‚šüú“¡ÌÿÃq¿ãÿ»xö“ÿ;'ÅY–«™ª%†/P5àøjQK¦œîQ„i˜;çÁÜzVQäzf—rÄßbZË$$vÄÔ03‰ã PºD9¥@ïœ.©cuƒÇ„4ttñLJ, ŸA¡ÒeŠùªŸ\þ»J–tµ“Y âÿGQÿ½“GYÿëu|wS7_´PýÇ“a·þ;y´ëÏýû¬ŽÂOz ÷?rÙÈõ†ýAwÿÛÅãÿ]ñRF.yZ%Nîáh©ö­.&#\'ÂMŒüð4ûš5'ŸÐßË„ëù¬P‘¯eí_ýäIEÇä‚·p˜ët¾Ü\º¼G¡'ëa¾?‹ÖãÒT1}1íù)2îq½®uËq=‹Œà'—ªZQoê°ÒÔb&„Qs½‹ÑëüKTö·ä&¹ûSy¾fÉco–&sµ‡" ÇàCŸõ²Ù®KS5%¯éÇ-Yáõ/zÊ+¾ò2¤•ë¼ÁúínT5¼à¯ ­‚D”H¸‰¿¼» ÷62Òvy¾Ú.YˆÌÍ|Y|Û/”Üä"uÃ[óãåL b¨NlötÌ¢!ÁŸæÉbfBOöý/AÃ|±ˆÏ©h³Þ&°côv\bû¶ Є2bµšJ²ºüi_ñãK‘PòëÕï)~u|MsrS: ,ëú’.Ú9Û‡üZÕ§4)r…¶f_ˆN-#)øDæI 䊠gäThæ†ÈÀâG2 Îò[Ží2¦ä]ÃqoѦ\Vtå|ºò.ÌÏ1Ñ„CP6%`–=µÙŸųð]ÕQ>qѦø–s)õÊêmàŒ´¤Of0™ç[mì²*$„ýl 5ä¨LVZÉ ’VަWAƒ’ˆnÇîÌ\‡iE…’‘#@Ñ‚­ Â ûµL‹Õš{e¶NK†i geC2»µÄ†ªYÀW™éÏäk¨:\6!ø×ÜÎîy6ü,ò&x0 ò¾¯¼ÝÃ=Šþççü_/‰Böµ CþÏq8êô»xŒë/}vÑšê¿&Jþ—pÐùìäÙ™þO¢£¯„çk§DÞu×vš=ßš=9×Óî‘‘Y™97 _ñvs-_Õ¯é£ÚB¶®j>y"tºC8_öÛ«9Y'-â.Ýž“»ñ¤ ¾w°5ÇbÕ“GTÖÖwó1é”W뽪i«û*y‰Ç±­ ¼Òˆ ¥¶(÷Hã±E–`—oíghÛSŽÚ\Û)h¶Oîì²ÑzÊй­ö#8å{“Cn‰ÖwëY²þþØr²Ü*ªëj;E€®ø¯œ'VíÇÙÉ[Ù±¶óʧò½7…6|µÅ”Úvûc·Šm|ó5Pn£gŽ2ÍzšcEdö¢äÆO©ƒk¥ìÖ2ŸË!{¹‚à1{`‹Ç æþV•}örqyy?×ÒÖꟖ'‹ãÅnyµm6Hïl…BgÔY¢j?¹þŸfˆm¥ö}êÛÃɤ³ÿìâá×?¾ºZ'WñfåÅêW=õ×4ŽÂnýwñ 럳ÍO³xª¾¯—÷±xLùcÅþ7îê?ïæiÿ]~QˆcBÃ@| 3Æ0“O%*öž!F·Æ’~{¦¬úvª½LP™éÖÑt“¥½.ãÜB60ØÑ2uÓHúZÀiÃ'qÔ[Ã,u&—úQuŽ®¶ðÙö¼ÌK§&Û/VC²àPâG¸OÎqy ·àæƒ"Û£dë‘fñüèñãúÓsœWþü-óy¯ Tÿľèé__m×å[”¦‰—³E"Î~w¾üÍíÍÅü2ÙÌEhysš%žYÓ<ëQp„ F®tõ–Ü.“¨Ô­œCT À:Y'7ä(‡ÀÞÏ&hÛ œ.pd›®ô…899c§UÂLïú4•ÒˆJ’N—!-“”~P0è4_`-ëŽë6k=Ø$î„§Ò¤°â)³4ßãoW›ùež'âŒ2v(úcxK¥érWjéEÍ3 À¬¦FŠZBü˜lÇ=œâ|;xøûá}I|CýÆüŽápÿNúÝý¼þ—óEò)ûøé2¦!kwõR¾ Áÿ7œ åú?ÃhÜåÿÜÉã~ÿÿ‰ÐÈ#‘Ÿ2 ÁÓ¾™oPý9磄›u““­3 žò¿A;Éœû­6°J8eu€Üo ²¦Ê[;ÍôFÆÝTñW Âê¢é[q»,aõ §Iº0£AyÃr]Ðùœ4¼³Êfx͆öAÉÈn´ª¥Õ(ùr¾X”Ìî^}™§›ol5Úoƒäxi²á®í¾4FGù‚ò_Æ„ÇôÅ¿ÎW F-è8h[«‘Þl7q¢y$´­ÝHDô¸´ om5E¸y •U﯉ µ^'™‡š&ѦÚ̪ÿ÷ñz3?ÅóÅv÷5»7n7£"Çê®6Wtþñ·œ­>õc6y gCÛÞ5¬3×¶ÉšL™ýðâ’úxµBØ`_µpsÿ8¿I~]f sq’Ñ¿potC.£³Ö…&y¯ˆN²Ôô‘i)òìÖ8á«­öˆKþ\®Ö-]’ÑѾ"ú?T>Y;S·Yÿ[«Ô;øü¿ÆƒHÖÿFã°Ëÿº“Ç¡þ{}÷!Ì™`~Ãûœ±/d?Õ›£lgì]v(Gá͵6£~pÔÕ­8ØêÖjŒÕ­M×ð|¸ïí†Âg£¶ÏÀ_׋œA‰QÜK¬RD(’Â- Ì&7m³.7àMÕ)@ÀÖv½Ð$Ÿ”ß|_ÔßËH(èép¸*Ybü}¼¹>(”߀çÔòñ‘Ú0.“õA!=ó&{_ õHWT{’Ë0¿Š»'^Þýúáõa¬äËu2£uUâEêw!)¯Uɤ·ÂÌLrï˜L P‘zj-5N9@7«ËË4Ù .…ü¤ÏJš¡.e<ümßÁ7s˜ªNC_|;œtÇ{°@¾ít´sý;M¨5¡·ÇT‡s«°OJ¬Ã¿|S’8#AáÍ-Ä(›nšâ›™Ít «‰ïS=©òW_Þ {íÊ]¬–‰öÅ*+·àe{ß·ªÃyÌ÷w¿¯â1æÊõŸ£Q—ÿq7ÿ¯ýrüÚ'¯Ýzzi]¼8Æ¿K§®Î¹¥3ÓtÎ-sË×áÜ´¿íð¸LAü 9[ç6Ô¹ unCûH-‡jWùs¼Þ´Å 3›äWCŠ]­ _6±”+dëÚqÕÆŽ¢T@]J#;iU±:RªÜ¦s}ÛCº~ÈwªÎõ­s}{¨g}m×·îyT'þÛ)õ{ þƒpÉñßãѨÓÿïâñÿí+‰›Ä¶šçn³è°½süûáôf¯òv-Sï¸ùÃyêÄ×ÕûÁÿ{ØŸÈñ߃pÐñÿ<^ø¿¨»8:ÍïQ§ú}8ªß²ZˆP/¤Ë?Ðåèòtùöç]þ.ÿ€Œœ.ÿ€©›½É?pô [µ|º {”¡$¹ÃMQ ¥¾Ý¤/°«ÓÅäz¹Z}ݦnT%À—ˆ‚úWªRÕÀ²èÝ'’]tóXÝ6˜†xIÐÌBºàƒ]f¾¤-É7 «qJ©¸þ@•@­I9äk  š±di¥ÆPŠ cUù CW¶¾è–ÅU‘/ÀBâzª”S÷-W…ê;‘Eé"t„¨¡3.ºêM!D¬; ¢Eè%7¬C5ŽEè#©¢´_#[NFkXM‰w™SfG8< ¿™$²î‘óŸÖÓLNžcï×÷ë‡_ ױ܇CGG>–äÇ€Î"ÏÏ¡âó§E|P{U‡.¯‚߯‚×uîˆGóJ%uPØñæK€ˆà"tt§A&¹l’÷]%Z~8ël³Ê¾¨Ö‹®fmï>Õ¹¯óí{`KüG]3 Éþ7ì+õÿF]þçÝ<{éÿWÛýà ¯™Õ΃¡Î‡‰³fznkK]s uX†±4`v\IRá2íSѳj'ˆ‡9ZH#7ðÙˆ²\¹LCqHQÀ,Ç Œ™ ÞÜÑTo\Žnœ\Àù„q0…£”u°q¡ÌLŸ0 §hí? ,MÀ²¡OÈFS iđ눵j";+Œòø–ðÞ ›°¹Ò¨ØöòJ'á° ºÑL€9ò³ÇB7ÂBÁO_Æk8›ž´­„mì ÜdŠåo“`ÃÓ¼•°M¼ÝÉôMfœ&/\ Þ‰WðžMÕ4qTP¹šg^OÀþÈ*'æ+»&R€ O8²ÐIð€yêJxüJ‘Í93k»DmÈQ2§y1ø 4A…z† ¢b8äðø|…”¡dKƒ… ©Z ™Û±–ix0ø†6¤1poܲ¶!¤ ¦àW`Ò‰šÈ*éDClx„”"¯Ra4šj3«ÈìWŸ…¥„Ññ¸ÇI*[q·£¼>Ié0šš‹š½ƒU“s ªt|Œª¼žäѳV¨Êí|G¹TߊK9âõò«!”DÈ^l Ó3݃ä3‘EˆÆ«pzÒÎ…È+]?ósò*§†ý©šJMÞ`@®µRjö*¥†¡Í¦ Å/1Wi2’½à”+f lA {¢!ȱ¥Lœ¼¤¬ªUws£4@Haö”ó«hðäVér”ÔS'þÏ5\oÿ‹†£ÉHŽÿžL†ýoÏ~Åw†¿‡høëBó*¯¶.4O|ºÐ¼.4oÏqÞ…æu¡y2rºÐýÜ츳ß3Î~¾ý×ü:ûywgkäìçÝ™­©³ŸW¯hÐØÙÏ«»rdåÑåîšÔÌÙo`pöóë±5šœý¼zh FýÜý²pg?+ϬA;žY†nê?£ÈȘÓL3ˆ.œúϨ¢3æ4ã0ª_÷ÇQM÷Ç&’à©6®ëþØÄÕIåk“VÕ |“E'Vü×ÙÙɳû㳺îM$€C÷ëº?º{ù,1lƒª}ÖQ¾må¿ïî¸îÅýñÄÎý±‰“ŸJ>Ï,Ý}»ñµsGôíÞççŠèUz£†.^e÷p`åé,”ÚÔ×HD} G·ìO$ ¡'‘W…8ßrw*7Ðïÿ¿½ë{n7Â}•ÿ ï¹±%‘tΓfÆI.s¹™4©ëk‡–èDYrI*õ¯/@$A.€ÅÒ– ¼ÜYÀX‹ï[8xWƤ†áÞ™Áb¾Y©$»ÈMá#h|@•ëé|R*¼Ü!P×ý…”ýVB8ê1~ $ƒ„Ëv³»+¡M­ý±­½ßns³Ým–Éòä¸>@ þ3Ñì{ÝšN7!¸„4®ÄÐi ì­O‘åß%Ù¦üÒU“òÄÐÒSÓeú53)gûÍÚh“’“I¦¥;2y'üìå+KÈPõ&Y»RvAU.ŒÅ Y •>H3&sŒ™fM¤¨:ÜBk¾ŠÇò1dݤ?"p)™ôQ?!1ûâQë /µ\ðâPËG-®ÛÉ•?`¤¤ÉmšdßÞ§¥–÷]$4Jˆt5Kñ˜Ðô©Šb5Ó&aŠÄÎäÎzT †hIU»`QYsºÐKԣݮËÑ}²ê{ØL“ú‘ï>¡fà ºQ½†]¿¨dãÀy÷zùîxÃW]ª™ß‰B_ÍàÆOYþЫ›Ó´^ÍÝÑÝ—IÊ‘ðù6ÓC‚§Í?ýÔöÿÜ‘}ç*½Íƒÿ/½ÿoŒŽ?û±hRĘѼÿa6õï?’Ìýé$¡iW«ÿU ‚Mªt®½ ïÁ·<>úÒ•f¼qÜ/¼Á.zQÌß‹}.N_Í- A$0úF{Ç ѯ‡ïè Q-ZÚ¢U‡Š¶ÿ³Ú‘¾ß¦wïJ/Ì?Nþ»‹×«Ûu|ÙLl-í‘V@ e «¨À­3ÊGYÁ?,ôàîaâFbôºwÍѨÊ_Äý¨2¸î€ þ¥[&ߣ&hôßòÿ¢R*Ćá9,½ÓšÛÙ©¥Ô¢l>šˆÇô¢;Šzz¤Aòá–±w7Ù"]݈ÁÄ4Ø1Ë4¿£®p,†Ç ÐOC¶‡˜çáæ¹ §þù¹ôsî4†éÓŸÓGoƒ.^T[žGሷÓÙœ³²· ×ज़¥’[EÍúÕ!ñ60 Þ,j\xæŽx:ÅȇSÇÄÛÐ)X>œÙoC§`ùpnK¼ ]ÃÀ–xº}µ ÷lÓ0ï6©ˆ·Q 'ÞFnƒ7D¡‚x9ÝðD‘;âmdúÆPs‰Úoß9fjDÆéÔX4GZ€ÿwœ^n…ܧQ6ØŸ_@‡€'¡ï”I ©¬°B·AûCèÍ “6tºõ _Áy MÃuˆ÷ ¿¢ ª1·Ï-“63Y&×íË“ÑT—I9ݬD³!fUd¶…bá/†ð‡eÒÎ{¬V3Å-;8C’i§{ð`:ÐÁÏéìfŽÎ}N·äÁÜÎ¥¸}Py&&òLæ5æÑšíq°tYÍ-N›ÌHT„à2¿%A´åmÙu0órïI=mÙ ¤ªuIqÏéªüØx›ëÛIŽ‘ú9Ý~M‰*ì¸SxÒpçà–½¶køURŒáÇ8ýNŽZÎKT7ß®ý×yœïj´§oÔ?¶7¼peWŽë‹éXŒÐº ÉêâFݶ 2™CL¨ª¾ÏIzë´}C´þß%bߨŶà×wŠL¦qOõˆÅ¡ˆž‚$ÇM§gçÓ.þkž{ü×É9þ Çá”ïŽTüLýÒ†à,^Ô‘Cè,Ùˆæ‚t{äŽfCRECÍŽFÁšÕ]sf±@tÔZãÛ<öÌcÏž-ö¬‚ÐhÆØ3ŒtéI{¦¨eÑÌG3ìJ¾˜»Åy5ú ‰£ãHäè MÃ;†jU÷ÉS u Ѯۨ_rýÖh Ùh8zMÐuêHÜ.Bj'éxƒä’¸3›"kû@§È MmI*O•ÆtD=&•ië¬çU²R›Ž(]@^´Ô§ô7©4mµ™ {DŠÓÒ[ßugª4]I§1æ>ÔV®àðú¨ý¡úPæiyAŸo’ûohÌÍÍ×ÌŠþ«òÿÎfgAÇÿ;=÷þßqÒ#áÿž²™¦M.ÄÒ¨­DtÓH=r&•¬®‘þuzòZâ6äéòÚ4Ur¶{UéAªãëO—Ÿß”ù˜ÖÂÏð¢¸`dùžæel‰ ºC¤=j¢PýwÚX e¬¬¬É@ÿ¼\à‡æ—F©¨8H³l—{mÍïè3½äËGÚC} ¯N+‘å±Û­h&³DÌ `LU4Jô«- KjmàIªÚZ@&L-ä¨&a¤ *dè²ìg+/ÐOÙG>e…¬( 1ƒ S“ãÔ$æC¡j– º$ô&ԢEЕ0Ò!^ ¤aäCH'z(£Us~¬­“ô$Ì”âh_Lz¨Ae×ÖcZ_ïèñ}¬µ&’|°j䌯”sYk9IãÁvk啞ý&­ºÅ=СÕâšX+«+ñ`Õö\¶´‡w sî°ë•è'1Õ°3/ßkþBá¡} Ï9añß?³¥qŠ÷¦aïýŸÙÿêýÿÃ'¬ÿ߇IôPUUu U}èÅÿ7•ýopð6u¨ø?³°wÿ;ŸÏ¼ý#aíé__%ë…ÕÔð²êÄÈñÌn„96IsOK§¾ d=8mÊ¢yevމ#¾„¦+ºP+jßíV2ã判Åyž®nvy"øŠó¹å_ü£IÓ@ÔÇ[d.¯Þ¹díê¼€¦ñ͹Í?¸¥úýŸ{E*¨þ=¼¤õ}[ܨÛVrŠÓúe æÑ,i™õvñýzõ¿ú‹´Þvžl>Ž‹û7»[º<[åÔßÔÍ6¿ÏõZGÙëu².WÎðu-ñN¯ªlwóW²(Ö+X½ò¤¨©yÕ÷ÚPDVД¥-&³§FÓ*¯ 7;"µþË.T›éR·è¨ë”©ÓÔ¨0ö›Ê ”»†²ÐNêá‡z™¦ñ^ÑZÌk§ÂšÛ Éœ¶Ÿ63Ùs+U`;d•±.Úª¶o½£Ûþû„¬ÇMþ¶z¬Ü­Ž›àzúÁ¢.86w²P*z-LÛ¥¯¨“Ó­æ RÀhFšëœóAèA÷GëW¾ºK®óøîžYnw«¯ød‘Žß'ˆú©±*K½Ù“-&›qi²ÔÙLmó˜îoˆ”·ÄJæPQÇÌÔ~dõ ¡pJ0¥,{Òv£3}5úPÞVô7à{T2§ºk‚.ÉtU\MÓ÷Üh·K›Ý»ÑúAKÔðmVٷ·V÷*ÉÓ=¸±äÆÄ¢¢¤ÒkµÀRëçüœ”cDÖÒñÕjA©ï–²Ø4êÆ}j*áhÆÉb›-o=Z=qû í†ÀÒÓRå¶½´^<:à(ûä϶…ýÙa=´¯ì)&¹ÿ·b„Yz€U÷³ çÿf÷ÿŽ‘ ÿ§šiŽè?ÎÀŒ{äŒıçô­«›uúúU¥©ê+ß;iRÑ ZR] (F²J)½ˆ¡Bâå’w[ª¨úIXÛfùÅ˳—g4ˆSÌ<;-À"´Åä?Õ2Zªìÿ_›ïÃÕQØÿHüþëyuÞÿÏϼý%e1Ý•eMtµÿÄë5o¹.ãOc¨]®×Ìä~iÓ¸ˆl\Æ´OZš´´2ØúYøZOj§ªA=Ê'¯Y€êÉ÷üâ Ù©“ücÒ<—ÉšÓv@&dS¡‹_ ¹8¼¦rØEˆM)ì\‹Íªêœ.ŸÕ¸Kª¾p¦~ìhêEšÄyÒlí§,/ÑOÛ˜¶Õ`]®ÉÐ-÷¿ý\ey¦bÙ‰˜­4¼&Ôl?==ÛÓ³==[‹ÍtGŽˆNLV%Ê›ª0Uã|ñ­¼n/æn”ä«b(D÷3=Ø0á ªV‚ Õ/ vÒšºy’åŸîgN¦,“uÐSUµÎßì7˵›Ï'ð ÕÆo~Š™]vK²EêåB­‚n/—ËÂ%¯¯’Û„1“ìòùP>†°>T9d ôêµ­íz·øV} $µôréK/H{C,άsDÿ=Î+[°ÈŒ³Ä u]Çéj½ÿs+I–¹eY®è~_væèåy`«?uhõ§‡m¾\EŸR;úuâO=ReËô@cPYÅáPŸe­"qÀàj4—Q¶ôgNœ-? F›ñrédÀ©œ'3¸Où°þv»É)ψÞõ[2©»I’UÛŸ›Œiâcrw“¤ˆ¼ô6–ìéUEPõ’C9œâ®u³:ÝNçÙþ¾fþ÷÷vŸÑùG?vŸ¢÷ݧO»{ßNÃp(Ÿo|þÿïaä4´È ü[ÝVg @¿ \ÿæÅVw~Úú¿—ßoàÐõÝ•Š€ïŒà‹­£”b¶jÁnãxüb ÿÿ ÝŽú·päD-ô) œq+oÚ˜²Úø{›UÁŸª«à_y•¬üýý}ë~ÛítºíOoϯHYÑŽXö"Þ¹}ø©õîôš‡ ¸ ÃJJ<Ê*Ü~DÁ0nõƒQ õÈÁv â·NÜ¿åëá/Õ£&õ·"οCÆNŒ¨ºé-4ŸÆ“1ŒÈŸèB) GÐ_áèÄ‹_lý‘8ž;táÀÚ6i6KI5A©çÌ¢žLW¯&gWÇAâÇáä8À¼>iavìÁ‡k5÷!þ‘ éß ÝŽ\ÿ¢ßOB„Dà#çýênQhÇG½ õõb µ‡h·@[츭ì¿VÁŠßSp¦DÌ{„{´ çŒ SÐÅ,æŽÝxrÒ/˜lç‹´~¡û%FÍRÑ• º‘Ö „)ÙÏ™ h§K‡†ÅO%LËÅè»ùïn×ñR¢c©xׂHˆõ仞çô<ô&“’Ù#0.ïÚ¹|wˆ¤µÈ¹6;ùÏ|6‡c'd€¡?Ñ¿1R¶˜´ˆàé˜ uÞÃ6…i*/’¸q3JœÒÂæÕ6‹òLÓ`6ƒS½pao9[·GfÅÞ H–ˆ3ÜN§˜^Ž5FüÖhÍМj;iŒÝü‚ô\4ej$š+¢AÙ«`0‘5}ÿ…µ\Š c•§IPfòZŽƒr)}únç8ûܪ*³ˆÙL÷s{qå]Ñ’ð É¢™€óç³ÂGõz,ÁÂLùÀœ)@Z‰úQχ47zÜ*ÖÏDð±\’5ŒaHÀ¨gÀ>ýCʽDS hu€ >ELÒè]ÚRö ¬%ûI*¾y{ .†Ã5ø>ñï 8‡þM| \¼†0~Â^Ÿzð.ûrŽ~ÆÉâ'ð&„PxõÖõ“þÕìþ@(õ®}õœþÜ”ø2mLz™6Ç/ûpÚþz€0 èêAÿ¢÷‡m‡j]œ ]?Ps5JÄœ"$qí¦0%rªxF/–Tb®^Ó- á=!  š`¾:Ò)÷õHI«ƒÛP“©…zMCÖ4DÇlK;FŒ Š1394Àu”fé5­ØÒ ã3 íWEóM=£°µhiæ°Í„¡2ш*bkéèÑJG¹¦ß„€Ä)îki¹(i^2Ò´Ufø[KJKAI3‘”ŒéÆØlº–—–…bf'/MËmÔFç¤&l´Z‹MZl¢vѦä&fæ\ NËEKóœ¦"©ÒÃ’µè´´43ÑÉŒrÌšÖÂÓ²ÐÌl…§©8Žæ ÎX|ê¹>¾h£8Žc§‰Õ!¾årÀ*Ç¡ãG¸HõÍü} Dñ;Y2DràN+§¸òFðÏ£>þ³ìöLÛÐR 6›ýìg†¡`0I„*ynŒ€ò„:m±vÛF„Z³‘XŪ­òq ÖxÓ®‡Î*ÇÊÇD«¬Qºä»XEd¶)?.áìì4¡ÀÜåc‚>ÖÄ {ˆ¼ñµÇÆ5é oÄ úN:q¦Ì¸lBHãIèâ{¤p`7ø6(¹8úiäìéœ\æÌt­1¤õW_$3P=j̼ÏW!VÌК^†·Äˆ1elÄà§äl‚)PÁÚ./®V†·|"e%Æ×—ÒÁ:ã±ç¦}´vЖ·ƒÛÞA3Ó³Üо¸ª¨\0Ÿ\U´- 7] ôI<—ÊÏ"ÏÍÝÙ9µ Ð&tF&ô:ƒA£ˆÃ±Rxhù0Îbç8Ñè7sà—zx2¹W’$ú²¹ŸT馥‹ß·f×a›–G¿Û\àô{ÑñrÛ“Å:9þGØ»Jq5 ª<þÓÓ§{})þÓóýÝýuü§y<ŠøO$ÜÓÿìì€W'ç`£~èŽÉ† AJ&8ÌÑvµF.àèò,jÊÊ‹'$îŒB:l#ÏC/c\—‰’Þï°v¤€5Ü¿uüœÜCT±Hìãðm]$!ä’´ "A|‹þƒá(ÂHÐKÚÚÏÀ(  d{f ìì¼T‡»"Cº‚NØ¿UÄAJBÿàò¬}ïŽÑ:^o+tØYÈ(´³âMF…¢*ØU÷çŸV»ªJ«vä+Ü–A˜)›xT„âNDQ&ý8A ž¬&9¾ãyéIHoüFéndá­66&Yx+ ’%Ž-g›ôšvË… tt4>,§Ñ‚iI4ú3ý-Fƒ8AKÅõ"¦J¦„t@ß…¡3Ùj³ÖÚBséO1 …:Ö9dBAEðœÞ´j—Ô8Š\ß² E‘аæ1")/¸±¬õ8¹¼ ‘1ž}q®f»Q,7¾5¨ }9,Ô&o«k¿Ûbø ÑxzGNè½®îòÄ «.‚ÌÞW·p} (ZÓïÓ=±Ûé®_ó­ã'hçÁŒ'´¬zââB½Ò²æÙȹh]Ð"«Y÷-¸É¨fåsÌÙ,랣á^†d§²ªw‘„uª}@›@zïá0 {nt[¯úqàyˆpÝžëT¿¾uÃÁ%Rs'ïà}®Fïÿ«e½WapAEF?:çeú%™Ö|ˆóœPq3ý¦QÁmK‚~ož;&,V8)_ÃNðj’jæ3[å¢L²$³ºêæm ß4"D)ó›F…hhú¦Q!Z̾iTÈ6‹%AFÁ¢²œXl‹i¥³A-cRÅv:Õ¾È4^ó¡ÝÝ'QŒ`XË.’UVjàâ×OVT /9‹Γ¤Åž-h¡\%£‘Ú·ŽƒQêu?›u ´Û, },†÷sF¨oÿ€“û ¼ÇùR×+ÃÅñ5­hIçcÇú@hÄEú4¬;¶«6.7Á¨ª à}?ÔfVë<ß½í'´Gê~ñíѽžÔ™N*öh°ŸNÇÞâ›Åð‡qßÁ‰õyÔšèm­85ȾÊζf`óŸKrQc.I½õ\.Õ\bÛQ©ìÛ»/­gr¦3É ö“9 5×ó¹LóÉ»ÚÏ騾ƒâz^g:¯ØRæÖuì'Õ}q×úRÍ&µÄ¹ñd.*ÝzjŠS“¾Í²YnäÉ,Ó{"oÓ T¹Â“^!×BÈå"zÿCÌ)Chéõa^ùÄ1ÊR… ¼5®‚—ç“©è8Ïr*öBÄ×}©/þªHeG¹a©bº‚:oa㡞Ýh±Å¥bœÅ"’—(g´±êov£ú0îW ªPBì3“Øt6Ãy" bÕL) Is%è§–½ÎptÄ”Q5:E!it‚%Ų׎kUƒ+–‘}±c›‰ã››ÝȘbU18u1±_YG³î{v£äÕŠ‘ꋊý«4˜ZpÌnÔ™0^1dM¹¢#¼ ÙÛw?»‘æ‚jÅPu•78¹·MŽKz—8@E‰”'…Zç/i_Òp 9êŠ^ÜC¦ŠbŸXƒÊ´…Шê:5m*áò±M –Šs:(u•*Õ n†°j„1”Åâð)„/CÈÔ•°Bé ¸Š”)ÂtR‘eŠ UHSÉ@¦ðéä-|Š Uð©¤Sø4›·¼bù*è[´!pÛ®F}µ PK¶WCˆKÄ!´ê*jDC(Ë6v˜š:pêöpC@K÷e¤ºJ jw`%¬B¤ítƒ}Eƒ*÷Xðþòø ¸º8º8ü øåúú’í¼bÈC~ã¥MÊŠ€zk‚vÓ·!9·· àݶßêKBõ–øhóSÉ [R°Ü,J†Ã,H ´r•¢Á<. ƒ§Í”‡`[è8ˆ¦•ÖS·¼S§ד¶¼“¦“”×s¶¼sV¢F¬§m‰§M¯]­§m‰§M«"­gmyg­R_OÞòN^©ab=qË;qå¶šõÌ-ïÌU¯ÖS·,SÇGÃOMy§þ`¸~éy™4Ÿ·É ÁkùÀðÃ]^aÚcÆ?ž^´ááÉð,¸o;ðûy™™/iPøuLøÙEXòûâ{¡á‘ë_ôûIˆð‰VÒÈy`¿º[´Ó³«WïØÑXļ£9(Ód(ʾðktø= r°¼‹Î<ÆVèäÝ#Ú˜ÇxOáèo¾“,…^˜çÔïxºs²³mÑT³ê1—+,׌+Íÿ›¨¸ mPX: µ©F?†cêèds;ê˜fpbárU¯T3EGI8õðìè·>7BÕ¥aJµUƒ¤Z{x³¥Õ Cº€xŽJO^å 1æêYwòY{Áþ|8ú  =å !/¼ƒÀ䯧©%G¼¸q‘D0ñ·xO®Xâl¨àÓÛs@µ|œÔÝq}|»‚(”O@ª>™šEþÄZI¤Äèé«uØáÉÀ”®°äâÝ=y%\¾¸"ƳÁ _bÂwÊ´V]-ê:H_œü—­Zð#CÅ VÞÿJÑéJ£-ª+€×`€“Óºðƒ½ îÜAšœ§¦tC2 ãߤGü©E¯ \¿&÷ÿ6I*Tþ Î=œS,[îÈé»>áOä²Û€ÒXNl¿ãü˦÷Ïè8õw …«èC+}MŠ£Ÿ;ä1­áŽÆÞÔ¸~<œ¾•úw1̱„Ô¸>ù .P¾Ä»! ÑéQÄ1‰Í®p¤[ )ÉùZdÅø˜ÐB®²ñ”ôx;14è’–k²OAÝåŸîxê~ÎUÅÉ`.]þ í«•\Yƒ éyвo¶P ºÎ‹6Òó9•ŸŒÍŠ6BBÇ|‚¡¹LëúbšyW9”v5 ƒÑg}wŠqPR¾Æº­&«¬h‚–NgZ„þdU™ñ¯-9_„¦3ó’餮t„wÒ™ÿiØb[lI>’šbŽË¶Î¦«-ލb˜Œ §©LÓzj7oã”0£z£ÆœeŠóŒIÍ® G*ˆ ¡Þ32/Œ’.x.c£ñʬDÏd Ç]ØÍJ6ºštMyÆ4t-Iz™Ã”®e–W ë®fº•Mµœ¥í°d§4^вàT&T• ¾Ë¿3&/Zà a£›j€¤Ú„ƒï颬›l,âJŽ'e§“V&eK#Âç…µƒl‘ަÖ^…Ø`ùxÚù€”dTª¾¬Ø(©9zªº!’Q‹ +†OªÑè-+6Ð)‡9 MQ[1<ŒÂ.³bƒœ‚X¤-qj‚QkŸ+†O¢ÑØeVl ÓlOLÐnj{RÚóV Ÿ&Û“Úþ±bJ®aºJc‚ÒŽ·b5’lÔvèiíÐwÌU#ÓõDwL×cÞ¼ûd¾‚ê'¨†JË K½/5NDí–xäceÞ›ô7ïa°v0XÌ“ÿC½™®ˆÿ»ÿ´xþ¿»>ÿŸÏ#žÿow[måq?a"Ûhá·¢I»>Œ[8 Z”l^£N^Q.µ]pØf¬™ÕÍBßâ?ØÛ6n‘b{NÂ}oWd UðAövÕA¶P#ö£©õ£Žº N;í›ö"±9§¯ÙÄz#¾ßú0ÆÝ6¿_¤‘Œò½”n™„̪àGç÷Q:Z±‰xee¼ª’ÏÅl¶îÑÆBQ=æTlû&\í¼¡¨ùàGûê~Ëé’›²éN#2 ï‹’MmE'bÔ­qG¶²x[Ò Æq|‚]»¿p–v±i¡B®iW‡BFéjaÇ ·t|rcÇõ¢z€gÕù®Ûùú}¹9—U]A K¶\ WœbòŠïèL¿,Ì)ïø~sJ¡ºfjÃ@]‚”B|ïàwçÎÙ‰ó޵®šöDâÐvI?—€’ µ§•HçIlWMÛì©â%]!MÞád.!]§6˜KW4èk“=QN¡œÌô>Ñd9ˆœtŽ«B[,…ë·óŠõò·¥Y0êð—BˆÌŠÁRìk6($¬hö§|}¾=ß}¸íúwöÞOœOý‹‰×»~óî®wõóŸðÓ»zç Žþúùc÷î|÷óäóÇ_¿þËýùäý©—|ýô¼0ßzïï~g¾H‡ñCc —á]ZW ˜Ìu›s-´¡ð /®³i›WµR%)éú,‘­H$ÏôJRÏ<Ó·9¬iiBƒp#œéãå?q™ýÞÛíÜõ÷¼?oÝ}úçÝç7¿Æ½ÉÏ£þèWïó›³»vÞÿ½7ú|‡è÷í¿vŽÏ÷Þ=íï½÷F¿vÎwß{½?Ý}öÿî}þøÞ=ï¼;}ÿæ×ο>zQÿÏèÅ<—_>Äf>¬omi%m“å©Ï¿•%*)v;a®C<Š‘ g½3›·ÙeÍË|‡,èlßÚ2L•CÛUHUÊG²ÉhÖk°Ø¼Ý4q›%(ªðßÜ $Æë˜šË Ä£Y¯Àbó–+·ÌX­@Á¤ó¸V`ñ.3C¡p›yûïh¹éÎ`òH鲉‰]q.µ2åÈ/ÜfÎ0ƒ‘˜¡ýwð¬óS‡b¡­0‘±ëËÙ‹² Ì‹¾ÈYóÉîÿÞxAÏñ“ˆ5{ ¸*þ÷³îséþï³gëû¿óyÊã'ñÄÿþ~ó°pxëÍùÅ«£ó,r4^eÕ÷­ð÷öV^¬ŠAtjV´#–Í‚|j½Ã™›¦Ç²J#·Q0ä¸.NáÑŽáCüÖ‰û·|=ü¥zÔ¤þ–>̺vD&wÞH¶‡Ô±eÆ3»4h—DòÎ}ã)§ÙâsŸD‚oä÷›Úóa›ù/Uv…Ó¦Öê+¿wnÖ§4‰µ†)¯Çú]Û[·ìPž'ÚVô^½—¥«ùƒPœ¤¹ÂxlØu"!®ÓIÝÝŒÆÆ!¦/^²ie™‘ç3¯%8˜ÉÄ67:)éÁ¢ºrl²,}Aî”2~£"€jÁ „Ä*AÒÐ{Úð~GõÉÈ€âH$÷}zË<òâþQF^Úl²—‰FŠÁFÚ›€~Z4øã0A%Ú$7¡Uqí¶R=zÍž`œA¼Œ`äD¿KO39O6&ޝ>ʱÁ~iŒ~„ì¶+A@”ù[Qcà‡„Œ±P²‘˜Å¡¸iå ”õšÆ—Ò,wƒ>«»Í–¯Õ[ڼ³‚iåmiº6’ êÒ "«4s¸r×Õ½¼)+2†¿9­H^$àÒœá’V®Fó‚3³Ûcé€5úùRÜŽ°¤|ôåÛµ‚´ª“ÑÏ‚¶V"¹øâ(p%ÐSš{] CUâu…LÀç׊@wô­ÞrHfpñÀ×0‰¹š‡k¬•l}&p3­—r…YBºTiÖ³óÿ³_ÐXƒþ×¹çÿî<}ÞÙ-äÿîtÖçÿóxçÿ…ã~ËüÜFgôé:eTGW„þ|9†£qº¤©-E@fÕ÷:îµ½ü¨ûb+ ýƒäÜñoTGìÙ{ay=†l©%Ö@1ÐÔ5.D'}yÙãtËä>¦Ÿ_‹C—¨& çD$BüA¡µ |zBW8,GßœµÖKbB8ÌÛrp[\4ãÝü׋-„¯{‚Ôìßþ¡±k@hòÙ¡8 m=øoâá¢ÏVÍÊcSüA LÕp±SjMÜö~@åÛ4x;1¼ ƒ;×ïW;†×p8o´Í‹ðÆñÝ?…@ï4œ¥Qn´Ñ,Ån“­…Ðá­ 4z8üçÀ¯Ù¨feþâD'ÎÄsonã+Ø Ç÷zAàA§¸*mÚ?†a츾°"n‰”Ü–V´ÂX¥Yæ2s“xHo1wÑÏØ–½ëz¾{™øº Y:ªY»U¥ÎÙ›¡`ü«Üã¬`2öóUN´yWzæŽßÊÑÙ²Íñr÷ J˜äm÷!‚ÀtØCÐ!n‡×ß‘¾±ð®“W[…C]aÍÔuÄL1QåÁ»(d;©ªVÏô()uJ]$N̼.•Kª¦³%·bø=¦°Œæå^©Â¾ã ¯~q»ÔcsWµ]ŸÿÌã)?ÿùpýšœÿ¨Âÿ‚ÙÚ4>Ø,ÓZÃ(iÁAÒþпA²Ï‘$ëæàêâèrçôݯ&g8wÐC{u[®{lsþÃ×5ÏEŸÖùxurn„æ6908êÚTø>Zàx)VTCeZ˜­—››‡,ùàa ?Ú.Äé.Ôz¾YǬ—š³=Åt“Ì‹‡ÿ³³£M艈RwIÜõ•ÜÙÁqâKk‘Hr‡’3bº]1ðÌ3Ýþ%'ˬçe‰©Ž÷³D]ÿöo–¨ò°ÍûI€ÚEˆ²wi&ˆ*”L…™%AP(*‘¬¿üÔŽ´åxíG4„‡Âéš³¥‡ b„›6›õuèø“£ 1œ÷Í?ä*J[9¤Ã6KGÊììˆ!ˆfO:BêRº)ºV:þWEêÝÜ´©k-Ç—è©É#{j‘$7/™ÆHû—ôi_TahTIïuØä5Lü”ðPŸ_¾6dÝg³¨§»#Á«Â»RÀ[Š}•3¥ˆ\ŽW?79›¬¨ó“ª¯ŠN“EÅÚŒ×d9HGjÅAé•BUô:“|ÇÞâæ¯þHœ²½¶G¥ÿ¬{f)X$YÿÒ|gV7%KC†f‰¤o0ôà*Nz©Íà+â:1Bþ1Zê®CbÎ=&ߎÿ÷A·µÛz n û„V„‚ô9•6£.É“N ÆœJoWi%  [ý—.‰4Nk®ÇnJzìüoU­Î“鈅“E軽náþW÷ù:þë\žúúß§·)åüNy`PFdä–$Ú¨a8DExšS]鲫YõÐLãšÚywl|{ÎıosƒéeT13VËjá+eSLpªLn `‹22•¹®’ÑÈÁÇq14(æPB~nH²2þ¿.¬cž,oªÚî ~]âÿrS/nr^_·%<•ÞŸ×o`œô<7BÒûÙ‰y#xä0+‰üê¢òµz¢dÍ(…´òjaZnCV×—IœuN[ÃÒ„Jªº¥í‰ºÛ?DD£qŸ`Z¿tÜÐŒ*§¡+;Šžb‹ƒZÈ æ`Ìjö(¤)À¾¶2h¢#3ñmø‹ÜÚqöÇ$ñçT ܨŸDX6šª?ˆñ¥°ºÕãR9½i&¢Ön!7’$6D^Å¥róÒFf_Ú,BHà˜=‰sÉÆÒa¾¸5ÞÝ’¬<ÎJT£KâÛ'õɼãÕfvñJ¶kIn5ØGž'CÞ¥j[UXúñ!t×plyáùŒ‹ÛbIÀÈ‘ÙÞl)[ÙÝòb'ÝÄ÷58qÓ ‚k{Æ%’€’­ZЮ1tœÍ(›Y˹֖œ'] ¤”=§Vj¶+ÚªÍê¤{3v[q\ëîp¥vºÓpFT5ò¬°ˆ45¦JØnä ­ÀL6n¾&—°Ç‚ÀœK@,0ñÒÑ‹\ܨY›Qkcý…£ãè:*Ö•/_0ZFnÕM DQ.V@;(ÅŠÈÉu@Š¥Ê1 ñoƒ&5£åÓ6¤Ã´3æOÔ*8uƒAIj0þw%®åR¤Šš[Ó¯5¡"¸£2ÓÝsº34¢oÐ㼺ûÍRމ ÖÞÔš ˆ’]l)‘VBU*ÐÒ¥&¤{y³“/làK‰,£‰/ê‡K7«I׉2 neêêÒ!¯z(U‡—nk'ŸžÌÿç½C|}îñŸ÷ööžã?ï¯ãÍåy¬ñ¿0[Ðõûä*Ü'W=˜n@‹K÷,£òò‰Û4ªN„:"A–æÌ$¬“e“äöí‚2ýÊÈ\Xª_ bˆ0zè£"€9Å + ¡àa‰ßÃIÙ˜„¨&w.M.l*Ç<ÃÁZ†Éš.8”4ŽtÉ͕Ɨe•8–b™3HLÖ9ÅÞ"ºŠff¶ÒEj),u:_ëŽw®‹ë¯œÈíëã;ΘÒ/›/x¤_LÂÿÕhûêÞE’aà ŸÀ(žÔ¤q3°gùTA‹a‚HD&xìx;ÏãzlzÉ¿u=ˆ“4^Ô½i<Â*nÔl›¶mõ³;n~ø8ŽOó8?º>jÖóó³FÅì¤ñùÇ6?ÿ¸Õ¦çŸ ¿ùùÇÍ6>ÿÖÊùŸnÇ/SÕNÆÆ¥a_”n,;+Èq…Þø@Û¸j»0o«@;‹a‘¦ªãÏ–`±*!“ªsËè·e–ŒPi™ÂäÖê~:,ˆšžQèY…lb¥ø=M÷¶¡Ëd½š4Y¹|#âK–î.5a2\Í﬉´- –ïjÊÑš¯I•×Pç“«TéD|yS ­P§¼“ºx0ž‹âþT‡Öõº¸­tÏhêÓül`¼Ó¯Aý€¿±Eh5•«Pº7ÂŽñ='ŠR/ Ú" žþ”@rá÷$gfâÛB0poÜ88j,ö“‰HDÇŸÐ0´“vÜûšh±@*\/ÙV /‘Jµaëñ"YTMãà»9B\Àáöã 5ns œð¢®R)Õ+åæY¬P‹Ò€m m¼¸h4cÔ€ômèx°B›F%B†Ž.†Cìà„Ç~Äšé_yBß>jÜ¿uü+Ì–HÏUñéKߺÁû…Õ[•Ö`…°q&„r‰ù1.㺨‘åëõbV/Ió$å2scKº4-ÇŠ­i³LRøc]ÕµSÙ×ëZ¿4 ÉTÈá5sÊ%íܶ«—Â…ë€3Ì0SÎHJ®hüÚJ xsÏØ³•&ÐEèǯ FS _j ô â«4RÂ×0Ž©3•3}‚žªÓµeË~d¿¢Ç^<ì[ÁW,Ï’ÌL%§@K9x»µ&¥¿*Íí³`Ím¹­Df¬Å.ÊUEÑ—îJ ¨4¿š°€s{z~gQ!£óY¶´b:ʯ-æò kˆâ=¿Lg˜ L-hAµÎU6ch‹ùËJYëìáÕç4û~}OTx²ûŸW¿uÑ&NÆqÓW@Ëïvq0éþç³Î³gëûŸóxÌîN{ýsÓþúç¦ùõÏMåõÏKb»*F˜ÈGØ£·þ#Ë» ›5ï‚nÚßÝ,»|Y=:£Hòd)¾è¶gv1”¯ áËLD n?avô‹ÝJEiq!”¬ü#‹>«* õ[æ«­Ÿà3,8±£rPØ.ƒPö¡Ý”?²ëÆxÓPÉhX6|Š€ó×,8¼ª[,b‡Yα"],äï‚ë ƒ˜9_²Î ½@3ЧCËý<ª»#î$5ûã½,ýJÇYœ˜ ÌY¯ e/_ÄüDH稈o!À…Á-*ÏdþâÅëýå&þÛ-|©ä‡_µÉ;r¨€«Ü¸wÐéyAJ…S¡cåÙ4maiŽldäsµx &ÅgvŠŠ6 Ÿ¹uBéÆÏjÌ¡™‰·d(^Z¦% æóXXÜ%–[¡v»X©®µ›”êi€i± ¨ÅrÍM²HÆÙz¸‚ˆB€Ñ޼› tãÛÑN7_OZyqÔ6·pÜc€³Œ³$_Ÿ„úèã÷!#Œõгß9ŒòAßñð ƒÆŠa‡Á 铲V‘º³ƒ*quDƒû[·‹Q7€x\81[€Áˆq†÷è6H<„PH±B¦Îñ&> á6BøÃÓ¤wîL‚}ºÃtB˜3潌6šÕ_~<úë ÏÅÀh»æzÌʾ¢ý¢VȬGˆøI“iRyˆaÀ™åÅVpâa‚Œ–k+r&j½ÄÞ;>Áª€> Q\ð9zÒá׸ÇÐ@šG’Ì ^Ÿ€ÄG4?pû1¾¥“UAßq‚ýà¿FpÒ“mÊðúQØoù.Z7Á]› NíQ{èŽÓÿuêìtñ_äVüoS!úÅö—žçø_·qëǨêWp CHˆÂ!DFáA'¤Xrzˆç5…†‹©ùïÎsENô˜ÀS0Y{}D·ˆL†ø;P `ìü~Œ Þ0ZÉ×6áHíÑài;ºuºxp·ñÈSÂ+Bª^oˆ>"BVmYfA SΕj ØÃ ¥b*hAàûF?û!$‰;R ¤¸…‘ÑŠ¯À5tFùà[Ù DxCZaóçMhÚý?ߘJ hãJ$¸j¼}‡ÙÍòíŠX΀`9ëkßÀ“Ùÿ"U£1"™ùÚÿ:OwŸudûßÞîÞÚþ7GaÿÃáÞ¾ßÄ)¿I®lÀ唯=Ä“w½í\!‚”b‚°vvÒzÅL‘8=îUN^[ß‹RvÁˆTQžZà&Xº1,l–éQYÕÆf©mÀÒȨlÇ0¤ª®YŒ8rp‚g=5¹DD€ì£Ý±•M.ÂÈ‘Œ+– (%Mà¥X';EÂÝ+R¿å5©ñˆ?’Äupbt¾IòRJÉF’ _»#¸µ±T fŒ¸BPD[Ôk 롃Oº¶xl©šáØ–G˜¾¯ä³³|é¹5páE¼Mõ‘Ô8>ØAb9‡ržVD›•PLuû !þk«l¤r¥±E÷A8°ª„‡@º•Wâ¯ZU HL#æ®ÇÞµù$Òä„ƒÉ f"±‹ppó‚SM9á™17²ñ.ïŠ$éÎ A6ü(çªhA£CK—xãªÊsùíU.ß‹&4†€ 4«x ˜23õãÀõ‹kœQwј˜„šZU~12s‘¼ +€-ט!‰Õ7b&ß{QËߎ·*|7ÖÞ³~2ýïŽ=&!¤„Ó˜X¡ÿ!µOŽÿýüÙÞóµþ7G©ÿ©”¸"}X¤„:úÚ&éKë[éxµ‘¹S(òLb¸ßãó記]òOwÜçÂXå¯LÛÍõņ™À™·;ô'®Ì:É!¹2ß$.+${“S¯ñ#“¸©Kfb Un6dY˜Ck¤åšKËÆá§,ã ŸeÅ< ZØ Ùá9‹´)KU4( Ž¥È…Ân>ö“0$ŽÐy-|öÀNÇ>´®Z€®×¢q_J•"Q”(EA±&™R˜%pƃŸ:)ÆðWqJDÃ! ×ySÖÁ“ÉItø†Í'€©òÿ}Þ)Øÿ;{kûÿ\žGœÿåö(ÏûÔz‡ïI®|õˆ—F†‡3=Q?¦ìå=s&5ZxÆá»?»c“èè3Jä |aId(4Nµ³ÆëI·Í&"®0ÆZ¡`E"5Œ¹WèÖ>¬šFêô_î²b!ÔéÈ8’Ý”]éÃ6=(«ø|¥}IÚõ‡+ÚWU\> «T8N±{ßÀ™*¼aNv&ÄTªµØE´Q-¥êH6Ê•P7rR†.ƒ@hˆ1›¨^ºUÕÞª¢M-#âŒ'i—nÍ>âÍ]ñÕ wŽ¡|t³dæ…/‰iíâ>÷Ø¢¬X‡b.›ˆ®¢›—ÒHJCêeŽ®Qd3$OUcÖh^ýHÂU§½[㌕œÍèˆ7g*äˆ&·F(®Q%`ub4 [1º–¼g>žÁ´öŸÌþ‡¶îÝ8‹ôÏUö¿ýn÷™œÿy¿ÛYÛÿæñÄæ¹U7ü‡² ‹H©Åë܉ÏÞeh6.é0½¡ˆçˆéúü¬NÚ5ë!ÅåŒí†]­Ý0ï_Ìv˜½O= f‹¢k·Ø©ˆ ‹œ‡šÑÒSâÓ0 Â|¶{AàA§8D›–Ry`š–§HmnŸòø¨× á]£íšÚà­?E6=ÍL½ƒ&17Nx`°ïŽœbbO릑8Ø|Ë×ÁŒ@F Ïࣻ›AŒ[žd­½½j6ÅâeeƒÓ¥W”tã¶:h¡mÔ:ba¡yžëÊþXEÞ<íú,=J©7øÂÕR„HÆÇÊɶèK겸ñ[Ϙ @²Ÿ£j÷ ªi B®d3'×ÍSíÜ»8Aà#=+6““ôøÆ{ÆIÆ»Zü Ç5ÀõðøL£c`&âô'yd±—D`8ƒAz¿£SƒÚøḠ^Š}ðNp,€N?F±*`N¹­^\øÕziõÖ=Ò Sbpô-ÏŠÍ¡S‘Ÿ407U‡Mßúäl)¸]Í#-ž™å2€ŠÅÍñ8«HYœõ¡Í‹íìJâu…Ikâܪ8¥G)’ȦFí2ŸUÉÿ›ÇS~þ÷áú5;ÿÃÇJü! î˜¨?ì³ó/‡NùÞ‡ª÷jè ‡„8|YúšHœèçNDv‹<(NCÅÚGV·Lc?êf¥Ãq·x­7&IÏaÙÇüì/¬Ô€whŸG7¯ ø_¢f{”XÚèjßañ„çøõñ™G7ªÓ‡>§P™!ÕjóöÏCÚúƒ5Ù¦ÈoÑ’DÊ÷ׯ ñZHiΖÄ•oÓJQbøŽŒº¦×5=#V|æ¿ÂQµ}*jáè9œ WIσv`ê&@Ó+9>ænÜv4 T!Øn$ö+‹Ü9J·@f¾0ä‘fr±ˆ´–jëºÉÉUrÌÅŠÚRsT“×ÒYIƒRÖ"Ámù´H–â>þ,» À͉¨CebØX.—n[“þ•ÓÖàUkCbñX~ûÚ†&x¥)YñJtíÛÎ FŠ·G^ËÁ´¤¿¥^R@i]9€´ÞœG@:5XS‚RLÞˆš1[.r¤žlA*–§ù KN^–Š5Pê•èúÃÀé÷¡‡Ç„Ä35Ùú– §ò£#j¡,/®uÃ¥|òüOw¯&Q GÄ´A=°Bÿ{žÅÝÝÇ: ŽÿÓÝ[ûÎåi^ÿÃÌÄs’qbXb?ò@`­™k5µuDA ­¨°Ök¢¾Êi¥ÖÕˆÍôZ¥f9B(¢q­ó( ÉÅþó!ã Õ²ÒÇ© þå!ÚB‘&FHÐs°àA§ö€TG5œè%18˜|ö§2˜D€`1ûÍ+k¿ýû·cÛ\7¹Æ›!ªÀÚ-v$Öã°Rå#L;Ñ$ªÒ¦]¿“é(hèçÚJOλ¯°#äy+Š r@Wný”*G ˆ¢žŒÑ£;Ïn@Žæ]œ-$¿¾’§#Áy7pès É9᎘ìø0H"pîúí³§$iJ \`÷ ØÃÙj|ø_ýàÞZ$“EG"9ê€ÚÆ©gÀ‹¿8º$ D ®“&ÁÅÍÅ÷ÁÎÀáœ'8 IBNïSԢƷe†óUÐlüu‹A€ç  ·íÒþÄæò¬,$›Ià%,ÙI`‘JRàÆ8ï¾5ËÒ¨äÚËþŸ‡'`òüùßxí†Q EÔ8êv[ÿ{ÔÝmMÐÿ÷Z¾8î¶pîšÀdøDÅvI±]Rl—ÛŃqC¡Ô)µGJí‘R{ßoâ!gèDpQÌ3$¥>=˜cAÄxþóæë.þßÞpÜýïðú½‹_îâ—»äå~¹‡_îá—{ÿýïß”hæX…n—’‚Áañ,†ãšä¶~ÀMRH^pÞ‡X@ªH’)$â42€±ãzM¹’5;jåj¡”ëCeTÈ-5xéËÜKÃÔ4F&][ÌÔ¤aQØ8ž£2a€tliN– ŒÙ5cÒl4 CJ“†[éI0ØŒtÛÙJRòQ¨o˜ái\e›Qo“sÚ#…á© áìG¹­HZ—ÂÒÕ ÆÖ#‹9œÆ†´Žÿ¼~ÖÏúY?ëgý¬Ÿõ³~ÖÏúY?ëgý¬Ÿõ³~ÖÍóÿ|ÿËÇ€ZSI-2.1-a1/ZSI/wstools/UserTuple.py0000644000175100017510000000777607706773116015236 0ustar zsizsi""" A more or less complete user-defined wrapper around tuple objects. Adapted version of the standard library's UserList. Taken from Stefan Schwarzer's ftputil library, available at , and used under this license: Copyright (C) 1999, Stefan Schwarzer All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the above author nor the names of the contributors to the software may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ # $Id: UserTuple.py 277 2003-07-21 14:18:54Z warnes $ #XXX tuple instances (in Python 2.2) contain also: # __class__, __delattr__, __getattribute__, __hash__, __new__, # __reduce__, __setattr__, __str__ # What about these? class UserTuple: def __init__(self, inittuple=None): self.data = () if inittuple is not None: # XXX should this accept an arbitrary sequence? if type(inittuple) == type(self.data): self.data = inittuple elif isinstance(inittuple, UserTuple): # this results in # self.data is inittuple.data # but that's ok for tuples because they are # immutable. (Builtin tuples behave the same.) self.data = inittuple.data[:] else: # the same applies here; (t is tuple(t)) == 1 self.data = tuple(inittuple) def __repr__(self): return repr(self.data) def __lt__(self, other): return self.data < self.__cast(other) def __le__(self, other): return self.data <= self.__cast(other) def __eq__(self, other): return self.data == self.__cast(other) def __ne__(self, other): return self.data != self.__cast(other) def __gt__(self, other): return self.data > self.__cast(other) def __ge__(self, other): return self.data >= self.__cast(other) def __cast(self, other): if isinstance(other, UserTuple): return other.data else: return other def __cmp__(self, other): return cmp(self.data, self.__cast(other)) def __contains__(self, item): return item in self.data def __len__(self): return len(self.data) def __getitem__(self, i): return self.data[i] def __getslice__(self, i, j): i = max(i, 0); j = max(j, 0) return self.__class__(self.data[i:j]) def __add__(self, other): if isinstance(other, UserTuple): return self.__class__(self.data + other.data) elif isinstance(other, type(self.data)): return self.__class__(self.data + other) else: return self.__class__(self.data + tuple(other)) # dir( () ) contains no __radd__ (at least in Python 2.2) def __mul__(self, n): return self.__class__(self.data*n) __rmul__ = __mul__ ZSI-2.1-a1/ZSI/wstools/c14n.py0000755000175100017510000004011310413067004014011 0ustar zsizsi#! /usr/bin/env python '''XML Canonicalization Patches Applied to xml.dom.ext.c14n: http://sourceforge.net/projects/pyxml/ [ 1444526 ] c14n.py: http://www.w3.org/TR/xml-exc-c14n/ fix -- includes [ 829905 ] c14n.py fix for bug #825115, Date Submitted: 2003-10-24 23:43 -- include dependent namespace declarations declared in ancestor nodes (checking attributes and tags), -- handle InclusiveNamespaces PrefixList parameter This module generates canonical XML of a document or element. http://www.w3.org/TR/2001/REC-xml-c14n-20010315 and includes a prototype of exclusive canonicalization http://www.w3.org/Signature/Drafts/xml-exc-c14n Requires PyXML 0.7.0 or later. Known issues if using Ft.Lib.pDomlette: 1. Unicode 2. does not white space normalize attributes of type NMTOKEN and ID? 3. seems to be include "\n" after importing external entities? Note, this version processes a DOM tree, and consequently it processes namespace nodes as attributes, not from a node's namespace axis. This permits simple document and element canonicalization without XPath. When XPath is used, the XPath result node list is passed and used to determine if the node is in the XPath result list, but little else. Authors: "Joseph M. Reagle Jr." "Rich Salz" $Date: 2006-03-30 23:47:16 +0000 (Thu, 30 Mar 2006) $ by $Author: boverhof $ ''' _copyright = '''Copyright 2001, Zolera Systems Inc. All Rights Reserved. Copyright 2001, MIT. All Rights Reserved. Distributed under the terms of: Python 2.0 License or later. http://www.python.org/2.0.1/license.html or W3C Software License http://www.w3.org/Consortium/Legal/copyright-software-19980720 ''' import string from xml.dom import Node try: from xml.ns import XMLNS except: class XMLNS: BASE = "http://www.w3.org/2000/xmlns/" XML = "http://www.w3.org/XML/1998/namespace" try: import cStringIO StringIO = cStringIO except ImportError: import StringIO _attrs = lambda E: (E.attributes and E.attributes.values()) or [] _children = lambda E: E.childNodes or [] _IN_XML_NS = lambda n: n.name.startswith("xmlns") _inclusive = lambda n: n.unsuppressedPrefixes == None # Does a document/PI has lesser/greater document order than the # first element? _LesserElement, _Element, _GreaterElement = range(3) def _sorter(n1,n2): '''_sorter(n1,n2) -> int Sorting predicate for non-NS attributes.''' i = cmp(n1.namespaceURI, n2.namespaceURI) if i: return i return cmp(n1.localName, n2.localName) def _sorter_ns(n1,n2): '''_sorter_ns((n,v),(n,v)) -> int "(an empty namespace URI is lexicographically least)."''' if n1[0] == 'xmlns': return -1 if n2[0] == 'xmlns': return 1 return cmp(n1[0], n2[0]) def _utilized(n, node, other_attrs, unsuppressedPrefixes): '''_utilized(n, node, other_attrs, unsuppressedPrefixes) -> boolean Return true if that nodespace is utilized within the node''' if n.startswith('xmlns:'): n = n[6:] elif n.startswith('xmlns'): n = n[5:] if (n=="" and node.prefix in ["#default", None]) or \ n == node.prefix or n in unsuppressedPrefixes: return 1 for attr in other_attrs: if n == attr.prefix: return 1 # For exclusive need to look at attributes if unsuppressedPrefixes is not None: for attr in _attrs(node): if n == attr.prefix: return 1 return 0 def _inclusiveNamespacePrefixes(node, context, unsuppressedPrefixes): '''http://www.w3.org/TR/xml-exc-c14n/ InclusiveNamespaces PrefixList parameter, which lists namespace prefixes that are handled in the manner described by the Canonical XML Recommendation''' inclusive = [] if node.prefix: usedPrefixes = ['xmlns:%s' %node.prefix] else: usedPrefixes = ['xmlns'] for a in _attrs(node): if a.nodeName.startswith('xmlns') or not a.prefix: continue usedPrefixes.append('xmlns:%s' %a.prefix) unused_namespace_dict = {} for attr in context: n = attr.nodeName if n in unsuppressedPrefixes: inclusive.append(attr) elif n.startswith('xmlns:') and n[6:] in unsuppressedPrefixes: inclusive.append(attr) elif n.startswith('xmlns') and n[5:] in unsuppressedPrefixes: inclusive.append(attr) elif attr.nodeName in usedPrefixes: inclusive.append(attr) elif n.startswith('xmlns:'): unused_namespace_dict[n] = attr.value return inclusive, unused_namespace_dict #_in_subset = lambda subset, node: not subset or node in subset _in_subset = lambda subset, node: subset is None or node in subset # rich's tweak class _implementation: '''Implementation class for C14N. This accompanies a node during it's processing and includes the parameters and processing state.''' # Handler for each node type; populated during module instantiation. handlers = {} def __init__(self, node, write, **kw): '''Create and run the implementation.''' self.write = write self.subset = kw.get('subset') self.comments = kw.get('comments', 0) self.unsuppressedPrefixes = kw.get('unsuppressedPrefixes') nsdict = kw.get('nsdict', { 'xml': XMLNS.XML, 'xmlns': XMLNS.BASE }) # Processing state. self.state = (nsdict, {'xml':''}, {}, {}) #0422 if node.nodeType == Node.DOCUMENT_NODE: self._do_document(node) elif node.nodeType == Node.ELEMENT_NODE: self.documentOrder = _Element # At document element if not _inclusive(self): inherited,unused = _inclusiveNamespacePrefixes(node, self._inherit_context(node), self.unsuppressedPrefixes) self._do_element(node, inherited, unused=unused) else: inherited = self._inherit_context(node) self._do_element(node, inherited) elif node.nodeType == Node.DOCUMENT_TYPE_NODE: pass else: raise TypeError, str(node) def _inherit_context(self, node): '''_inherit_context(self, node) -> list Scan ancestors of attribute and namespace context. Used only for single element node canonicalization, not for subset canonicalization.''' # Collect the initial list of xml:foo attributes. xmlattrs = filter(_IN_XML_NS, _attrs(node)) # Walk up and get all xml:XXX attributes we inherit. inherited, parent = [], node.parentNode while parent and parent.nodeType == Node.ELEMENT_NODE: for a in filter(_IN_XML_NS, _attrs(parent)): n = a.localName if n not in xmlattrs: xmlattrs.append(n) inherited.append(a) parent = parent.parentNode return inherited def _do_document(self, node): '''_do_document(self, node) -> None Process a document node. documentOrder holds whether the document element has been encountered such that PIs/comments can be written as specified.''' self.documentOrder = _LesserElement for child in node.childNodes: if child.nodeType == Node.ELEMENT_NODE: self.documentOrder = _Element # At document element self._do_element(child) self.documentOrder = _GreaterElement # After document element elif child.nodeType == Node.PROCESSING_INSTRUCTION_NODE: self._do_pi(child) elif child.nodeType == Node.COMMENT_NODE: self._do_comment(child) elif child.nodeType == Node.DOCUMENT_TYPE_NODE: pass else: raise TypeError, str(child) handlers[Node.DOCUMENT_NODE] = _do_document def _do_text(self, node): '''_do_text(self, node) -> None Process a text or CDATA node. Render various special characters as their C14N entity representations.''' if not _in_subset(self.subset, node): return s = string.replace(node.data, "&", "&") s = string.replace(s, "<", "<") s = string.replace(s, ">", ">") s = string.replace(s, "\015", " ") if s: self.write(s) handlers[Node.TEXT_NODE] = _do_text handlers[Node.CDATA_SECTION_NODE] = _do_text def _do_pi(self, node): '''_do_pi(self, node) -> None Process a PI node. Render a leading or trailing #xA if the document order of the PI is greater or lesser (respectively) than the document element. ''' if not _in_subset(self.subset, node): return W = self.write if self.documentOrder == _GreaterElement: W('\n') W('') if self.documentOrder == _LesserElement: W('\n') handlers[Node.PROCESSING_INSTRUCTION_NODE] = _do_pi def _do_comment(self, node): '''_do_comment(self, node) -> None Process a comment node. Render a leading or trailing #xA if the document order of the comment is greater or lesser (respectively) than the document element. ''' if not _in_subset(self.subset, node): return if self.comments: W = self.write if self.documentOrder == _GreaterElement: W('\n') W('') if self.documentOrder == _LesserElement: W('\n') handlers[Node.COMMENT_NODE] = _do_comment def _do_attr(self, n, value): ''''_do_attr(self, node) -> None Process an attribute.''' W = self.write W(' ') W(n) W('="') s = string.replace(value, "&", "&") s = string.replace(s, "<", "<") s = string.replace(s, '"', '"') s = string.replace(s, '\011', ' ') s = string.replace(s, '\012', ' ') s = string.replace(s, '\015', ' ') W(s) W('"') def _do_element(self, node, initial_other_attrs = [], unused = None): '''_do_element(self, node, initial_other_attrs = [], unused = {}) -> None Process an element (and its children).''' # Get state (from the stack) make local copies. # ns_parent -- NS declarations in parent # ns_rendered -- NS nodes rendered by ancestors # ns_local -- NS declarations relevant to this element # xml_attrs -- Attributes in XML namespace from parent # xml_attrs_local -- Local attributes in XML namespace. # ns_unused_inherited -- not rendered namespaces, used for exclusive ns_parent, ns_rendered, xml_attrs = \ self.state[0], self.state[1].copy(), self.state[2].copy() #0422 ns_unused_inherited = unused if unused is None: ns_unused_inherited = self.state[3].copy() ns_local = ns_parent.copy() inclusive = _inclusive(self) xml_attrs_local = {} # Divide attributes into NS, XML, and others. other_attrs = [] in_subset = _in_subset(self.subset, node) for a in initial_other_attrs + _attrs(node): if a.namespaceURI == XMLNS.BASE: n = a.nodeName if n == "xmlns:": n = "xmlns" # DOM bug workaround ns_local[n] = a.nodeValue elif a.namespaceURI == XMLNS.XML: if inclusive or (in_subset and _in_subset(self.subset, a)): #020925 Test to see if attribute node in subset xml_attrs_local[a.nodeName] = a #0426 else: if _in_subset(self.subset, a): #020925 Test to see if attribute node in subset other_attrs.append(a) # # TODO: exclusive, might need to define xmlns:prefix here # if not inclusive and a.prefix is not None and not ns_rendered.has_key('xmlns:%s' %a.prefix): # ns_local['xmlns:%s' %a.prefix] = ?? #add local xml:foo attributes to ancestor's xml:foo attributes xml_attrs.update(xml_attrs_local) # Render the node W, name = self.write, None if in_subset: name = node.nodeName if not inclusive: if node.prefix is not None: prefix = 'xmlns:%s' %node.prefix else: prefix = 'xmlns' if not ns_rendered.has_key(prefix) and not ns_local.has_key(prefix): if not ns_unused_inherited.has_key(prefix): raise RuntimeError,\ 'For exclusive c14n, unable to map prefix "%s" in %s' %( prefix, node) ns_local[prefix] = ns_unused_inherited[prefix] del ns_unused_inherited[prefix] W('<') W(name) # Create list of NS attributes to render. ns_to_render = [] for n,v in ns_local.items(): # If default namespace is XMLNS.BASE or empty, # and if an ancestor was the same if n == "xmlns" and v in [ XMLNS.BASE, '' ] \ and ns_rendered.get('xmlns') in [ XMLNS.BASE, '', None ]: continue # "omit namespace node with local name xml, which defines # the xml prefix, if its string value is # http://www.w3.org/XML/1998/namespace." if n in ["xmlns:xml", "xml"] \ and v in [ 'http://www.w3.org/XML/1998/namespace' ]: continue # If not previously rendered # and it's inclusive or utilized if (n,v) not in ns_rendered.items(): if inclusive or _utilized(n, node, other_attrs, self.unsuppressedPrefixes): ns_to_render.append((n, v)) elif not inclusive: ns_unused_inherited[n] = v # Sort and render the ns, marking what was rendered. ns_to_render.sort(_sorter_ns) for n,v in ns_to_render: self._do_attr(n, v) ns_rendered[n]=v #0417 # If exclusive or the parent is in the subset, add the local xml attributes # Else, add all local and ancestor xml attributes # Sort and render the attributes. if not inclusive or _in_subset(self.subset,node.parentNode): #0426 other_attrs.extend(xml_attrs_local.values()) else: other_attrs.extend(xml_attrs.values()) other_attrs.sort(_sorter) for a in other_attrs: self._do_attr(a.nodeName, a.value) W('>') # Push state, recurse, pop state. state, self.state = self.state, (ns_local, ns_rendered, xml_attrs, ns_unused_inherited) for c in _children(node): _implementation.handlers[c.nodeType](self, c) self.state = state if name: W('' % name) handlers[Node.ELEMENT_NODE] = _do_element def Canonicalize(node, output=None, **kw): '''Canonicalize(node, output=None, **kw) -> UTF-8 Canonicalize a DOM document/element node and all descendents. Return the text; if output is specified then output.write will be called to output the text and None will be returned Keyword parameters: nsdict: a dictionary of prefix:uri namespace entries assumed to exist in the surrounding context comments: keep comments if non-zero (default is 0) subset: Canonical XML subsetting resulting from XPath (default is []) unsuppressedPrefixes: do exclusive C14N, and this specifies the prefixes that should be inherited. ''' if output: apply(_implementation, (node, output.write), kw) else: s = StringIO.StringIO() apply(_implementation, (node, s.write), kw) return s.getvalue() ZSI-2.1-a1/scripts/0000755000175100017510000000000010712455110012201 5ustar zsizsiZSI-2.1-a1/scripts/wsdl2dispatch0000644000175100017510000000054410441102623014677 0ustar zsizsi#!/bin/env python ############################################################################ # Joshua Boverhof, LBNL # Monte Goode , LBNL # See Copyright for copyright notice! ########################################################################### from ZSI.generate.commands import wsdl2dispatch wsdl2dispatch() ZSI-2.1-a1/scripts/wsdl2py0000644000175100017510000000053010441102623013523 0ustar zsizsi#!/bin/env python ############################################################################ # Joshua Boverhof, LBNL # Monte Goode , LBNL # See Copyright for copyright notice! ########################################################################### from ZSI.generate.commands import wsdl2py wsdl2py() ZSI-2.1-a1/doc/0000755000175100017510000000000010712455110011257 5ustar zsizsiZSI-2.1-a1/doc/next.png0000644000175100017510000000077710437331051012757 0ustar zsizsi‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒ =p3f]ž=ÆbKGDâµ=º“IDATxÚÍ“ÁÂ0Dc@©‰ ùÿ¯•‚vͶã­{åMf¥értF@š‡ñ u¬Q‚@îNô ;:ñÀ%ÙQ°…!X³ÁxmS1 ZOc*ŒTx×ô®<Ø wæçüqþžh“A,Z~LzTXtSoftwarexÚsÐPÖôÌMLOõMLÏLÎV0Ñ3Ò3R°´Ô70Õ70TH.Ê,.©tÈ­,.ÉLÖK-ÖK)-ÈÏ+ÑKÎÏôK€ôÝÄ^3zTXtSignaturexÚ3231³´L47374K11426NL31·05L210HL3|nÐɾÈÄzTXtPagexÚ36ª06Ò6Ð6 šùGwÃIEND®B`‚ZSI-2.1-a1/doc/up.png0000644000175100017510000000110110437331051012403 0ustar zsizsi‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f?0­bKGD{¼lÕIDATxÚ}’Û… D“2+oñÿ?{Y…'tj;`&ótO˧€„xM€íÆ"7vªã½ ‡¬TÀ㣤PÈ€5a§ãhëKíàZý¬—쥕@{ål½EÓ¦]°üÉAm ˆ¸P[§âýâmdP¦†šMD.ÔÈä’‘}Ólî™%ÀóV¢öL»òq€>óìZLŒL ª´N€×„l-è1°wA4ð=r`Ð?7cÀj&$p¼ÇhÐá,²@ׄxx¢® 3LzTXtSoftwarexÚsÐPÖôÌMLOõMLÏLÎV0Ñ3Ò3R°´Ô70Õ70TH.Ê,.©tÈ­,.ÉLÖK-ÖK)-ÈÏ+ÑKÎÏôK€ôÝÄ^3zTXtSignaturexÚ304L³0JL4M4KI4H56µ4L¶L444H40µ421vC·[̓zTXtPagexÚ36ª06Ò6Ð6 šùGwÃIEND®B`‚ZSI-2.1-a1/doc/contents.png0000644000175100017510000000121110437331051013616 0ustar zsizsi‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f?0­bKGD{¼lIDATxÚÍ’Ý’Ã …‹‚ ÆÞÿe1I»7íMgg3™xF>`|À‡çñüdydÍïlª•O'>hGBa®a¤ƒV8 +šVœ†½ï¨Õ—é‹v/ºŒæÜ{R˜38 wJŒhº"U‹o. i|ÂM-àI3è¯S$e¯Ú|§ÚÈEåoˆ3£vë èR°,߬3.7wè€å`ZËj ZSI: The Zolera Soap Infrastructure Developer's Guide

ZSI: The Zolera Soap Infrastructure
Developer's Guide

Rich Salz,

Christopher Blunck

Release 2.1.0
November 01, 2007

COPYRIGHT

Copyright © 2001, Zolera Systems, Inc.
All Rights Reserved.

Copyright © 2002-2003, Rich Salz.
All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.





Acknowledgments

We are grateful to the members of the soapbuilders mailing list (see http://groups.yahoo.com/soapbuilders), Fredrik Lundh for his soaplib package (see http://www.secretlabs.com/downloads/index.htm#soap), Cayce Ullman and Brian Matthews for their SOAP.py package (see http://sourceforge.net/projects/pywebsvcs).

We are particularly grateful to Brian Lloyd and the Zope Corporation (http://www.zope.com) for letting us incorporate his ZOPE WebServices package and documentation into ZSI.

Abstract:

ZSI, the Zolera SOAP Infrastructure, is a Python package that provides an implementation of SOAP messaging, as described in The SOAP 1.1 Specification. In particular, ZSI parses and generates SOAP messages, and converts between native Python datatypes and SOAP syntax. It can also be used to build applications using SOAP Messages with Attachments. ZSI is ``transport neutral'', and provides only a simple I/O and dispatch framework; a more complete solution is the responsibility of the application using ZSI. As usage patterns emerge, and common application frameworks are more understood, this may change.

ZSI requires Python 2.3 or later.

The ZSI homepage is at http://pywebsvcs.sf.net/.


Contents

1. Introduction

ZSI, the Zolera SOAP Infrastructure, is a Python package that provides an implementation of the SOAP specification, as described in The SOAP 1.1 Specification. In particular, ZSI parses and generates SOAP messages, and converts between native Python datatypes and SOAP syntax.

ZSI requires Python 2.3 or later.

The ZSI project is maintained at SourceForge, at http://pywebsvcs.sf.net. ZSI is discussed on the Python web services mailing list, visit http://lists.sourceforge.net/lists/listinfo/pywebsvcs-talkto subscribe.

For those interested in using the wsdl2py tool see the Users Guide, it contains a detailed example of how to use the code generation facilities in ZSI.

For those interested in a high-level tutorial covering ZSI and why Python was chosen, see the article http://www.xml.com/pub/a/ws/2002/06/12/soap.html, written by Rich Salz for xml.com.

SOAP-based processing typically involves several steps. The following list details the steps of a common processing model naturally supported by ZSI (other models are certainly possible):

  1. ZSI takes data from an input stream and parses it, generating a DOM-based parse tree as part of creating a ParsedSoap object. At this point the major syntactic elements of a SOAP message -- the Header, the Body, etc. -- are available.
  2. The application does header processing. More specifically, it does local dispatch and processing based on the elements in the SOAP Header. The SOAP actor and mustUnderstand attributes are also handled (or at least recognized) here.
  3. ZSI next parses the Body, creating local Python objects from the data in the SOAP message. The parsing is often under the control of a list of data descriptions, known as typecodes, defined by the application because it knows what type of data it is expecting. In cases where the SOAP data is known to be completely self-describing, the parsing can be dynamic through the use of the TC.Any class.
  4. The application now dispatches to the appropriate handler in order to do its ``real work.'' As part of its processing it may create output objects
  5. The application creates a SoapWriter instance and outputs an initial set of namespace entries and header elements.
  6. Any local data to be sent back to the client is serialized. As with Body parsing, the datatypes can be described through typecodes or determined dynamically (here, through introspection).
  7. In the event of any processing exceptions, a Fault object can be raised, created, and/or serialized.

Note that ZSI is ``transport neutral'', and provides only a simple I/O and dispatch framework; a more complete solution is available through the use of included WSDL tools (wsdl2py), but otherwise this is the responsibility of the application using ZSI. As usage patterns emerge, and common application frameworks are more understood, this may change.

Within this document, tns is used as the prefix for the application's target namespace, and the term element refers to a DOM element node.)

1.1 How to Read this Document

Readers interested in using WSDL and clients to web services, and those intending on implementing web services based on existing WSDL should refer to the Users Guide. Others interested in developing the simplest SOAP applications, or spending the least amount of time on building a web services infrastructure should read chapters 2, 3, and 10 of this document. Readers who are developing complex services, and who are familiar with XML Schema and/or WSDL, should read this manual in order. This will provide them with enough information to implement the processing model described above. They can skip probably skip chapters 2 and 10.

ZSI has the capability to process WSDL definitions and XML Schema documents (described in The Web Services Description Language and XMLSchema 1.0) and generate typecodes automatically. For more information see the Users Guide.

2. Examples

This chapter contains a number of examples to show off some of ZSI's features. It is broken down into client-side and server-side examples, and explores different implementation options ZSI provides.

2.1 Server Side Examples

2.1.1 Simple example

Using the ZSI.dispatch module, it is simple to expose Python functions as web services. Each function is invoked with all the input parameters specified in the client's SOAP request. Any value returned by the function will be serialized back to the client; multiple values can be returned by returning a tuple.

The following code shows some simple services:

#!/usr/local/bin/python2.4
# SOAP Array

def hello():
    return ["Hello, world"]

def echo(*args):
    return args

def sum(*args):
    sum = 0
    for i in args: sum += i
    return [sum]

def average(*args):
    return [sum(*args) / len(args)]

from ZSI import dispatch
dispatch.AsCGI(rpc=True)

Each function defines a SOAP request, so if this script is installed as a CGI script, a SOAP message can be posted to that script's URL with any of hello, echo, or average as the request element, and the value returned by the function will be sent back. These functions expect and return SOAP-ENC:arrayType instances which are marshalled into python list instances, this script interoperates with the client.Binding. For more information see Appendix A.

The ZSI CGI dispatcher catches exceptions and sends back a SOAP fault. For example, a fault will be sent if the hello function is given any arguments, or if the average function is given a non-integer.

Here is another example but using SOAP-ENC:Struct instances which are marshalled into python dict instances, this script interoperates with the client.NamedParamBinding. For more information see Appendix B.

#!/usr/local/bin/python2.4
# SOAP Struct

def hello():
    return {"value":"Hello, world"}

def echo(**kw):
    return kw

def sum(**kw):
    sum = 0
    for i in kw.values(): sum += i
	return {"value":sum}

def average(**kw):
	d = sum(**kw)
    return d["value"] = d["value"]/len(kw)

from ZSI import dispatch
dispatch.AsCGI(rpc=True)

2.1.2 low level soap processing example

We will now show a more complete example of a robust web service implemented at the SOAP layer. It takes as input a player name and array of integers, and returns the average. It is presented in sections, following the steps detailed above. A complete working example of this service is available in Appendix C.

The first section reads in a request, and parses the SOAP header.

from ZSI import *
import sys
IN, OUT = sys.stdin, sys.stdout
try:
    ps = ParsedSoap(IN)
except ParseException, e:
    OUT.write(FaultFromZSIException(e).AsSOAP())
    sys.exit(1)
except Exception, e:
    # Faulted while processing; we assume it's in the header.
    OUT.write(FaultFromException(e, 1).AsSOAP())
    sys.exit(1)

# We are not prepared to handle any actors or mustUnderstand elements,
# so we'll arbitrarily fault back with the first one we found.
a = ps.WhatActorsArePresent()
if len(a):
    OUT.write(FaultFromActor(a[0]).AsSOAP())
    sys.exit(1)
mu = ps.WhatMustIUnderstand()
if len(mu):
    uri, localname = mu[0]
    OUT.write(FaultFromNotUnderstood(uri, localname).AsSOAP())
    sys.exit(1)

This section defines the mappings between Python objects and the SOAP data being transmitted. Recall that according to the SOAP specification, RPC input and output are modeled as a structure.

class Player:
    def __init__(self, *args):
        if not len(args): return
        self.Name = args[0]
        self.Scores = args[1:]
Player.typecode = TC.Struct(Player, [
                                TC.String('Name'),
                                TC.Array('Integer', TC.Integer(), 'Scores', undeclared=True),
                                ], 'GetAverage')
class Average:
    def __init__(self, average=None):
        self.average = average
Average.typecode = TC.Struct(Average, [
                                TC.Integer('average'),
                                ], 'GetAverageResponse')

This section parses the input, performs the application-level activity, and serializes the response.

try:
    player = ps.Parse(Player.typecode)
except EvaluateException, e:
    OUT.write(FaultFromZSIException(e).AsSOAP())
    sys.exit(1)

try:
    total = 0
    for value in player.Scores: total = total + value
    result = Average(total / len(player.Scores))
    sw = SoapWriter()
    sw.serialize(result, Average.typecode)
    sw.close()
    OUT.write(str(sw))
except Exception, e:
    OUT.write(FaultFromException(e, 0, sys.exc_info()[2]).AsSOAP())
    sys.exit(1)

In the serialize() call above, the second parameter is optional, since result is an instance of the Average class, and the Average.typecode attribute is the typecode for class instances.

2.1.3 A mod_python example

The Apache module mod_python (see http://www.modpython.org) embeds Python within the Apache server. In order to expose operations within a module via mod_python, use the dispatch.AsHandler() function. The dispatch.AsHandler() function will dispatch requests to any operation defined in the module you pass it, which allows for multiple operations to be defined in a module. The only trick is to use __import__ to load the XML encodings your service expects. This is a required workaround to avoid the pitfalls of restricted execution with respect to XML parsing.

The following is a complete example of a simple handler. The soap operations are implemented in the MyHandler module:

def hello():
    return {"value":"Hello, world"}

def echo(**kw):
    return kw

def sum(**kw):
    sum = 0
    for i in kw.values(): sum += i
	return {"value":sum}

def average(**kw):
	d = sum(**kw)
    d["value"] = d["value"]/len(kw)
	return d

Dispatching from within mod_python is achieved by passing the aforementined MyHandler module to dispatch.AsHandler(). The following code exposes the operations defined in MyHandler via SOAP:

from ZSI import dispatch
from mod_python import apache

import MyHandler
mod = __import__('encodings.utf_8', globals(), locals(), '*')
mod = __import__('encodings.utf_16_be', globals(), locals(), '*')

def handler(req):
    dispatch.AsHandler(modules=(MyHandler,), request=req, rpc=True)
    return apache.OK

2.2 Client Side Examples

2.2.1 Simple Example

ZSI provides two ways for a client to interactive with a server: the Binding or NamedParamBinding class and the ServiceProxy class. The first is useful when the operations to be invoked are not defined in WSDL or when only simple Python datatypes are used; the ServiceProxy class can be used to parse WSDL definitions in order to determine how to serialize and parse the SOAP messages.

During development, it is often useful to record ``packet traces'' of the SOAP messages being exchanged. Both the Binding and ServiceProxy classes provide a tracefile parameter to specify an output stream (such as a file) to capture messages. It can be particularly useful when debugging unexpected SOAP faults.

The first example provided below demonstrates how to use the NamedParamBinding class to connect to a remote service and perform an operation.

#!/usr/bin/env python
import sys,time
from ZSI.client import NamedParamBinding as NPBinding

b = NPBinding(url='http://127.0.0.1/cgi-bin/soapstruct', tracefile=sys.stdout)
print "Hello: ", b.hello()
print "Echo: ", b.echo(name="josh", year=2006, pi=3.14, time=time.gmtime())
print "Sum: ", b.sum(one=1, two=2, three=3)
print "Average: ", b.average(one=100, two=200, three=300, four=400)

2.2.2 Complex Example: pickler.py

If the operation invoked returns a ComplexType, typecode information must be provided in order to tell ZSI how to deserialize the response. Here is a sample server-side implementation (for the complete example see Appendix D):

class Person:
  def __init__(self, name=None, age=0):
    self.name = name
    self.age = age

Person.typecode = TC.Struct(Person,
			    [TC.String('name'),
			     TC.InonNegativeInteger('age')],
			    'myApp:Person')

# my web service that returns a complex structure
def getPerson(name):
  fp = open('%s.person.pickle', % name, 'r')
  return pickle.load(fp)

# my web service that accepts a complex structure
def savePerson(person):
  fp = open('%s.person.pickle' % person.name, 'w')
  pickle(person, fp)
  fp.close()

In order for ZSI to transparently deserialize the returned complex type into a Person instance, a module defining the class and its typecode can be passed into the Binding. It is also possible to explicitly tell ZSI what typecode to use by passing it as a parameter to the Binding.Receive() method.

The following fragment shows both styles:

import sys
from ZSI.client import Binding
from MyComplexTypes import Person

b = Binding(url='http://localhost/test3/pickler.py', tracefile=sys.stdout)
person = Person('christopher', 26)
rsp = b.savePerson(person)

Because the returned complex type is defined in a class present in typesmodule, transparent deserialization is possible. When sending complex types to the server, it is not necessary to list the module in typesmodule:

import sys
import MyComplexTypes
from ZSI.client import NamedParamBinding as NPBinding, Binding
from ZSI import TC

kw = {'url':'http://localhost/test3/pickler.py', 'tracefile':sys.stdout}
b = NPBinding(**kw)
rsp = b.getPerson(name='christopher')
assert type(rsp) is dict, 'expecting a dict'
assert rsp['Person']['name'] == 'christopher', 'wrong person'

b = NPBinding(typesmodule=MyComplexTypes, **kw)
rsp = b.getPerson(name='christopher')
assert isinstance(rsp['Person'], MyComplexTypes.Person), (
    'expecting instance of %s' %MyComplexTypes.Person)

b = Binding(typesmodule=MyComplexTypes, **kw)
class Name(str):
    typecode = TC.String("name")

rsp = b.getPerson(Name('christopher'))
assert isinstance(rsp['Person'], MyComplexTypes.Person), (
    'expecting instance of %s' %MyComplexTypes.Person)

3. Exceptions

exception ZSIException
Base class for all ZSI Exceptions, it is a subtype of the Python Exception class.

exception ParseException
ZSI can raise this exception while creating a ParsedSoap object. It is a subtype of the ZSIException class. The string form of a ParseException object consists of a line of human-readable text. If the backtrace is available, it will be concatenated as a second line.

The following attributes are read-only:

inheader
A boolean that indicates if the error was detected in the SOAP Header element.

str
A text string describing the error.

trace
A text string containing a backtrace to the error. This may be None if it was not possible, such as when there was a general DOM exception, or when the str text is believed to be sufficient.

exception EvaluateException
This exception is similar to ParseException, except that ZSI may raise it while converting between SOAP and local Python objects.

The following attributes are read-only:

str
A text string describing the error.

trace
A text backtrace, as described above for ParseException.

4. Utilities

ZSI defines some utility methods that general applications may want to use.

Version( )
Returns a three-element tuple containing the numbers representing the major, minor, and release identifying the ZSI version. New in version 1.1.

4.1 Low-Level Utilities

ZSI also defines some low-level utilities for its own use that start with a leading underscore and must be imported explicitly. They are documented here because they can be useful for developing new typecode classes.

These functions are mostly used in in parse methods and the ParsedSoap class. The serialization routines use the ElementProxy class to encapsulate common DOM-level operations.

Some lambda's are defined so that some DOM accessors will return an empty list rather than None. This means that rather than writing:

if elt.childNodes:
   for N in elt.childNodes:
      ...
One can write:
for N in _children(elt):
   ...

Other lambda's return SOAP-related attributes from an element, or None if not present.

_attrs( element)
Returns a list of all attributes of the specified element.

_backtrace( elt, dom)
This function returns a text string that traces a ``path'' from dom, a DOM root, to elt, an element within that document, in XPath syntax.

_child_elements( element)
Returns a list of all children elements of the specified element.

_children( element)
Returns a list of all children of the specified element.

_copyright _empty_nsuri_list

_find_arraytype( element)
The value of the SOAP arrayType attribute. New in version 1.2.

_find_attr( element, name)
The value of the unqualified name attribute.

_find_attrNS( element, namespaceURI, localName)
The value of a name attribute in a namespace namespaceURI.

_find_attrNodeNS( element, namespaceURI, localName)
Works just like _find_attrNS, but this function grabs the attribute Node to distinquish between an unspecified attribute(None) and one set to empty string("").

_find_default_namespace( element)
Returns the value of the default namespace.

_find_encstyle( element)
The value of the SOAP encodingStyle attribute.

_find_href( element)
The value of the unqualified href attribute.

_find_type( element)
The value of the XML Schema type attribute.

_find_xmlns_prefix( element, prefix)
The value of the xmlns:prefix type attribute.

_find_xsi_attr( element, attribute)
Find the attribute in any of the XMLSchema namespaces.

_get_element_nsuri_name( element)
Returns a (namespace,name) tuple representing the element tag.

_get_idstr( obj)
Substitute for id function. Python 2.3.x generates a FutureWarning for negative IDs, so we use a different prefix character to ensure uniqueness, and call abs() to avoid the warning.

_get_postvalue_from_absoluteURI( url)
Returns POST value from url, and caches these values.

_resolve_prefix( element, prefix)
resolve prefix to a namespaceURI. If None or empty str, return default namespace or None if not defined.

_valid_encoding( elt)
Return true if the element elt has a SOAP encoding that can be handled by ZSI (currently Section 5 of the SOAP 1.1 specification or an empty encoding for XML).

5. The ParsedSoap module -- basic message handling

This class represents an input stream that has been parsed as a SOAP message.

class ParsedSoap( input[, **keywords])
Creates a ParsedSoap object from the provided input source. If input is not a string, then it must be an object with a read() method that supports the standard Python ``file read'' semantics.

The following keyword arguments may be used:

Keyword Default Description
envelope True expect a SOAP Envelope
keepdom False Do not release the DOM when this object is destroyed. To access the DOM object, use the GetDomAndReader() method. The reader object is necessary to properly free the DOM structure using reader.releaseNode(dom). New in version 1.2.
readerclass None Class used to create DOM-creating XML readers; described below. New in version 1.2.
resolver None Value for the resolver attribute; see below.
trailers False Allow trailing data elements to appear after the Body.

The following attributes of a ParsedSoap are read-only:

body
The root of the SOAP Body element. Using the GetElementNSdict() method on this attribute can be useful to get a dictionary to be used with the SoapWriter class.

body_root
The element that contains the SOAP serialization root; that is, the element in the SOAP Body that ``starts off'' the data.

data_elements
A (possibly empty) list of all child elements of the Body other than the root.

header
The root of the SOAP Header element. Using the GetElementNSdict() method on this attribute can be useful to get a dictionary to be used with the SoapWriter class.

header_elements
A (possibly empty) list of all elements in the SOAP Header.

trailer_elements
Returns a (possibly empty) list of all elements following the Body. If the trailers keyword was not used when the object was constructed, this attribute will not be instantiated and retrieving it will raise an exception.

The following attribute may be modified:

resolver
If not None, this attribute can be invoked to handle absolute href's in the SOAP data. It will be invoked as follows:

resolver( uri, tc, ps, **keywords)
The uri parameter is the URI to resolve. The tc parameter is the typecode that needs to resolve href; this may be needed to properly interpret the content of a MIME bodypart, for example. The ps parameter is the ParsedSoap object that is invoking the resolution (this allows a single resolver instance to handle multiple SOAP parsers).

Failure to resolve the URI should result in an exception being raised. If there is no content, return None; this is not the same as an empty string. If there is content, the data returned should be in a form understandable by the typecode.

The following methods are available:

Backtrace( elt)
Returns a human-readable ``trace'' from the document root to the specified element.

FindLocalHREF( href, elt)
Returns the element that has an id attribute whose value is specified by the href fragment identifier. The href must be a fragment reference -- that is, it must start with a pound sign. This method raises an EvaluateException exception if the element isn't found. It is mainly for use by the parsing methods in the TypeCode module.

GetElementNSdict( elt)
Return a dictionary for all the namespace entries active at the current element. Each dictionary key will be the prefix and the value will be the namespace URI.

GetMyHeaderElements( [actorlist=None])
Returns a list of all elements in the Header that are intended for this SOAP processor. This includes all elements that either have no SOAP actor attribute, or whose value is either the special ``next actor'' value or in the actorlist list of URI's.

GetDomAndReader( )
Returns a tuple containing the dom and reader objects, (dom, reader). Unless keepdom is true, the dom and reader objects will go out of scope when the ParsedSoap instance is deleted. If keepdom is true, the reader object is needed to properly clean up the dom tree with reader.releaseNode(dom).

IsAFault( )
Returns true if the message is a SOAP fault.

Parse( how)
Parses the SOAP Body according to the how parameter, and returns a Python object. If how is not a TC.TypeCode object, then it should be a Python class object that has a typecode attribute.

ResolveHREF( uri, tc[, **keywords])
This method is invoked to resolve an absolute URI. If the typecode tc has a resolver attribute, it will use it to resolve the URI specified in the uri parameter, otherwise it will use its own resolver, or raise an EvaluateException exception.

Any keyword parameters will be passed to the chosen resolver. If no content is available, it will return None. If unable to resolve the URI it will raise an EvaluateException exception. Otherwise, the resolver should return data in a form acceptable to the specified typecode, tc. (This will almost always be a file-like object holding opaque data; for XML, it may be a DOM tree.)

WhatActorsArePresent( )
Returns a list of the values of all the SOAP actor attributes found in child elements of the SOAP Header.

WhatMustIUnderstand( )
Returns a list of "(uri, localname)" tuples for all elements in the SOAP Header that have the SOAP mustUnderstand attribute set to a non-zero value.

ZSI supports multiple DOM implementations. The readerclass parameter specifies which one to use. The default is to use minidom, provided through the DefaultReader class in the ZSI.parse module.

The specified reader class must support the following methods:

fromString( string)
Return a DOM object from a string.

fromStream( stream)
Return a DOM object from a file-like stream.

releaseNode( dom)
Free the specified DOM object.

The DOM object must support the standard Python mapping of the DOM Level 2 specification. While only a small subset of specification is used, the particular methods and attributes used by ZSI are available only by inspecting the source.

To use the cDomlette DOM provided by the 4Suite package, use the NonvalidatingReader class in the Ft.Xml.Domlette module. Due to name changes in the 1.0 version of 4Suite, a simple adapter class is required to use this DOM implementation.

from 4Suite.Xml.Domlette import NonvalidatingReaderBase

class 4SuiteAdapterReader(NonvalidatingReaderBase):

    def fromString(self, str):
        return self.parseString(str)

    def fromStream(self, stream):
        return self.parseStream(stream)

    def releaseNode(self, node):
        pass

6. The TypeCode classes -- data conversions

The TypeCode module defines classes used for converting data between SOAP data and local Python objects. Python numeric and string types, and sequences and dictionaries, are supported by ZSI. The TC.TypeCode class is the parent class of all datatypes understood by ZSI.

All typecodes classes have the prefix TC., to avoid name clashes.

ZSI provides fine-grain control over the names used when parsing and serializing XML into local Python objects, through the use of two attributes: the pname, the aname. The pname specifies the name expected on the XML element being parsed and the name to use for the output element when serializing. The aname is the name to use for the analogous attribute in the local Python object.

The pname is the parameter name. It specifies the incoming XML element name and the default values for the Python attribute and serialized names. All typecodes take the pname argument. This name can be specified as either a list or a string. When specified as a list, it must have two elements which are interpreted as a ``(namespace-URI, localname)'' pair. If specified this way, both the namespace and the local element name must match for the parse to succeed. For the Python attribute, and when generating output, only the ``localname'' is used. If a namespace-URI is specified then the full qualified name is used for output, and it is required for input; this requires the namespace prefix to be specified.

The aname is the attribute name. This parameter overrides any value implied by the pname. Typecodes nested in a TC.Struct or TC.ComplexType can use this parameter to specify the tag, dictionary key, or instance attribute to set.

The nsdict parameter to the SoapWriter construct can be used to specify prefix to namespace-URI mappings, these are otherwise handled automatically.

6.1 TC.TypeCode

The TypeCode class is the parent class of all typecodes.

class TypeCode( **keywords)
The following keyword arguments may be used:

Keyword Default Description
pname None parameter name of the object
aname None attribute name of the object
minOccurs 1 schema facet minimum occurances
maxOccurs 1 schema facet maximum occurances
nillable False schema facet is this nillable (xsi:nil="true")
typed True Output type information (in the xsi:type attribute) when serializing. By special dispensation, typecodes within a TC.Struct object inherit this from the container.
unique 0 If true, the object is unique and will never be ``aliased'' with another object, so the id attribute need not be output.
pyclass None when parsing data, instances of this class can be created to store the data. Default behavior is reflective of specific TypeCode classes.
attrs_aname '_attrs' attribute name of the object where attribute values are stored. Used for serialization and parsing.

Optional elements are those which do not have to be an incoming message, or which have the XML Schema nil attribute set. When parsing the message as part of a Struct, then the Python instance attribute will not be set, or the element will not appear as a dictionary key. When being parsed as a simple type, the value None is returned. When serializing an optional element, a non-existent attribute, or a value of None is taken to mean not present, and the element is skipped.

typechecks
This is a class attribute. If true (the default) then all typecode constructors do more rigorous type-checking on their parameters.

tag
This is a class attribute. Specifies the global element declaration this typecode represents, the value is a "(namespace, name)" tuple.

type
This is a class attribute. Specifies the global type definition this typecode represents, the value is a "(namespace, name)" tuple.

attribute_typecode_dict
This is a class attribute. This is a dict of "(URI, NCName)" tuple keys, the values of each is a typecode. This is how attribute declarations other than SOAP and XMLSchema attribute declarations (eg. xsi:type, id, href, etc) are represented.

logger
This is a class attribute. logger instance for this class.

The following methods are useful for defining new typecode classes; see the section on dynamic typing for more details. In all of the following, the ps parameter is a ParsedSoap object.

checkname( elt, ps)
Checks if the name and type of the element elt are correct and raises a EvaluateException if not. Returns the element's type as a "(uri, localname)" tuple if so.

checktype( elt, ps)
Like checkname() except that the element name is ignored. This method is actually invoked by checkname() to do the second half of its processing, but is useful to invoke directly, such as when resolving multi-reference data.

nilled( elt, ps)
If the element elt has data, this returns False. If it has no data, and the typecode is not optional, an EvaluateException is raised; if it is optional, a True is returned.

simple_value( elt, ps, mixed=False)
Returns the text content of the element elt. If no value is present, or the element has non-text children, an EvaluateException is raised. If mixed is False if child elements are discovered an EvaluateException is raised, else join all text nodes and return the result.

6.2 TC.Any -- the basis of dynamic typing

SOAP provides a flexible set of serialization rules, ranging from completely self-describing to completely opaque, requiring an external schema. For example, the following are all possible ways of encoding an integer element i with a value of 12:

6.2.1 simple data

- requires type information
<tns:i xsi:type="SOAP-ENC:integer">12</tns:i>
<tns:i xsi:type="xsd:nonNegativeInteger">12</tns:i>
<SOAP-ENC:integer>12</SOAP-ENC:integer>
<tns:i>12</tns:i>

The first three lines are examples of typed elements. If ZSI is asked to parse any of the above examples, and a TC.Any typecode is given, it will properly create a Python integer for the first three, and raise a EvaluateException for the fourth.

6.2.2 compound data

- Struct or Array Compound data, such as a struct, may also be self-describing (namespace are omitted for clarity):
<tns:foo>
    <tns:i xsi:type="SOAP-ENC:integer">12</tns:i>
    <tns:name xsi:type="SOAP-ENC:string">Hello world</tns:name>
</tns:foo>

If this is parsed with a TC.Any typecode, either a Python dict is created or if aslist is True a list:

ps = ParsedSoap(xml, envelope=False)
print ps.Parse(TC.Any())
{   'name': u'Hello world',    'i': 12   }

print ps.Parse(TC.Any(aslist=True))
[ 12, u'Hello world' ]
Note that one preserves order, while the other preserves the element names.

6.2.3 class description

class Any( name[, **keywords])
Used for parsing incoming SOAP data (that is typed), and serializing outgoing Python data.

The following keyword arguments may be used:

Keyword Default Description
aslist False If true, then the data is (recursively) treated as a list of values. The default is a Python dictionary, which preserves parameter names but loses the ordering. New in version 1.1.

In addition, if the Python object being serialized with an Any has a typecode attribute, then the serialize method of the typecode will be invoked to do the serialization. This allows objects to override the default dynamic serialization.

Referring back to the compound XML data above, it is possible to create a new typecode capable of parsing elements of type mytype. This class would know that the i element is an integer, so that the explicit typing becomes optional, rather than required.

6.2.4 Adding new types

Most of the TypeCodes classes in TC are registered with Any, making an instance of itself available for dynamic typing. New TypeCode classes can be created and registered with Any by using RegisterType. In order to override an existing entry in the registry call RegisterType with clobber=True. The serialization entries are mappings between builtin Python types and a TypeCode instance, it is not possible to have one Python type map to multiple typecodes. The parsing entries are mappings between (namespaceURI,name) tuples, representing the xsi:type attribute, and a TypeCode instance. Thus, only one instance of a TypeCode class can represent a XML Schema type. So this mechanism is not appropriate for representing XML Schema element information.

class NEWTYPECODE(TypeCode)( ...)
The new typecode should be derived from the TC.TypeCode class, and TypeCode.__init__() must be invoked in the new class's constructor.

parselist
This is a class attribute, used when parsing incoming SOAP data. It should be a sequence of "(uri, localname)" tuples to identify the datatype. If uri is None, it is taken to mean either the XML Schema namespace or the SOAP encoding namespace; this should only be used if adding support for additional primitive types. If this list is empty, then the type of the incoming SOAP data is assumed to be correct; an empty list also means that incoming typed data cannot by dynamically parsed.

errorlist
This is a class attribute, used when reporting a parsing error. It is a text string naming the datatype that was expected. If not defined, ZSI will create this attribute from the parselist attribute when it is needed.

seriallist
This is a class attribute, used when serializing Python objects dynamically. It specifies what types of object instances (or Python types) this typecode can serialize. It should be a sequence, where each element is a Python class object, a string naming the class, or a type object from Python's types module (if the new typecode is serializing a built-in Python type).

parse( elt, ps)
ZSI invokes this method to parse the elt element and return its Python value. The ps parameter is the ParsedSoap object, and can be used for dereferencing href's, calling Backtrace() to report errors, etc.

serialize( sw, pyobj[, **keywords])
ZSI invokes this method to output a Python object to a SOAP stream. The sw parameter will be a SoapWriter object, and the pyobj parameter is the Python object to serialize.

The following keyword arguments may be used:

Keyword Default Description
attrtext None Text (with leading space) to output as an attribute; this is normally used by the TC.Array class to pass down indexing information.
name None Name to use for serialization; defaults to the name specified in the typecode, or a generated name.
typed per-typecode Whether or not to output type information; the default is to use the value in the typecode.

Once the new typecode class has been defined, it should be registered with ZSI's dynamic type system by invoking the following function:

RegisterType( class[, clobber=0[, **keywords]])
By default, it is an error to replace an existing type registration, and an exception will be raised. The clobber parameter may be given to allow replacement. A single instance of the class object will be created, and the keyword parameters are passed to the constructor.

If the class is not registered, then instances of the class cannot be processed as dynamic types. This may be acceptable in some environments.

6.3 TC.SimpleType

Parent class of all simple types.

empty_content
This is a class attribute. Value returned when tag or node is present, is not nilled, and without text content.

6.4 Strings

SOAP/XMLSchema Strings are Python strings.

class String( name[, **keywords])
The parent type of all strings.

The following keyword arguments may be used:

Keyword Default Description
resolver None A function that can resolve an absolute URI and return its content as a string, as described in the ParsedSoap description.
strip True If true, leading and trailing whitespace are stripped from the content.

class Enumeration( value_list, name[, **keywords])
Like TC.String, but the value must be a member of the choices sequence of text strings

In addition to TC.String, the basic string, several subtypes are provided that transparently handle common encodings. These classes create a temporary string object and pass that to the serialize() method. When doing RPC encoding, and checking for non-unique strings, the TC.String class must have the original Python string, as well as the new output. This is done by adding a parameter to the serialize() method:

Keyword Default Description
orig None If deriving a new typecode from the string class, and the derivation creates a temporary Python string (such as by Base64String), than this parameter is the original string being serialized.

class Base64String( name[, **keywords])
The value is encoded in Base-64.

class HexBinaryString( name[, **keywords])
Each byte is encoded as its printable version.

class URI( name[, **keywords])
The value is URL quoted (e.g., %20 for the space character).

It is often the case that a parameter will be typed as a string for transport purposes, but will in fact have special syntax and processing requirements. For example, a string could be used for an XPath expression, but it is more convenient for the Python value to actually be the compiled expression. Here is how to do that:

import xml.xpath.pyxpath
import xml.xpath.pyxpath.Compile as _xpath_compile

class XPathString(TC.String):
    def __init__(self, name, **kw):
        TC.String.__init__(self, name, **kw)

    def parse(self, elt, ps):
        val = TC.String.parse(self, elt, ps)
        try:
            val = _xpath_compile(val)
        except:
            raise EvaluateException("Invalid XPath expression",
                        ps.Backtrace(elt))
        return val

In particular, it is common to send XML as a string, using entity encoding to protect the ampersand and less-than characters.

class XMLString( name[, **keywords])
Parses the data as a string, but returns an XML DOM object. For serialization, takes an XML DOM (or element node), and outputs it as a string.

The following keyword arguments may be used:

Keyword Default Description
readerclass None Class used to create DOM-creating XML readers; described in the ParsedSoap chapter.

6.5 Integers

SOAP/XMLSchema integers are Python integers.

class Integer( [**keywords])
The parent type of all integers. This class handles any of the several types (and ranges) of SOAP integers.

The following keyword arguments may be used:

Keyword Default Description
format %d Format string for serializing. New in version 1.2.

class IEnumeration( choices[, **keywords])
Like TC.Integer, but the value must be a member of the choices sequence.

A number of sub-classes are defined to handle smaller-ranged numbers.

class Ibyte( [**keywords])
A signed eight-bit value.

class IunsignedByte( [**keywords])
An unsigned eight-bit value.

class Ishort( [**keywords])
A signed 16-bit value.

class IunsignedShort( [**keywords])
An unsigned 16-bit value.

class Iint( [**keywords])
A signed 32-bit value.

class IunsignedInt( [**keywords])
An unsigned 32-bit value.

class Ilong( [**keywords])
An signed 64-bit value.

class IunsignedLong( [**keywords])
An unsigned 64-bit value.

class IpositiveInteger( [**keywords])
A value greater than zero.

class InegativeInteger( [**keywords])
A value less than zero.

class InonPositiveInteger( [**keywords])
A value less than or equal to zero.

class InonNegativeInteger( [**keywords])
A value greater than or equal to zero.

6.6 Floating-point Numbers

SOAP/XMLSchema floating point numbers are Python floats.

class Decimal( [**keywords])
The parent type of all floating point numbers. This class handles any of the several types (and ranges) of SOAP floating point numbers.

The following keyword arguments may be used:

Keyword Default Description
format %f Format string for serializing. New in version 1.2.

class FPEnumeration( value_list, name[, **keywords])
Like TC.Decimal, but the value must be a member of the value_list sequence. Be careful of round-off errors if using this class.

Two sub-classes are defined to handle smaller-ranged numbers.

class FPfloat( name[, **keywords])
An IEEE single-precision 32-bit floating point value.

class FPdouble( name[, **keywords])
An IEEE double-precision 64-bit floating point value.

6.7 Dates and Times

SOAP dates and times are Python time tuples in UTC (GMT), as documented in the Python time module. Time is tricky, and processing anything other than a simple absolute time can be difficult. (Even then, timezones lie in wait to trip up the unwary.) A few caveats are in order:

  1. Some date and time formats will be parsed into tuples that are not valid time values. For example, 75 minutes is a valid duration, although not a legal value for the minutes element of a time tuple.

  2. Fractional parts of a second may be lost when parsing, and may have extra trailing zero's when serializing.

  3. Badly-formed time tuples may result in non-sensical values being serialized; the first six values are taken directly as year, month, day, hour, minute, second in UTC.

  4. Although the classes Duration and Gregorian are defined, they are for internal use only and should not be included in any TypeCode you define. Instead, use the classes beginning with a lower case g in your typecodes.

In addition, badly-formed values may result in non-sensical serializations.

When serializing, an integral or floating point number is taken as the number of seconds since the epoch, in UTC.

class Duration( [**keywords])
A relative time period. Negative durations have all values less than zero; this makes it easy to add a duration to a Python time tuple.

class Gregorian( [**keywords])
An absolute time period. This class should not be instantiated directly; use one of the gXXX classes instead.

class gDateTime( [**keywords])
A date and time.

class gDate( [**keywords])
A date.

class gYearMonth( [**keywords])
A year and month.

class gYear( [**keywords])
A year.

class gMonthDay( [**keywords])
A month and day.

class gDay( [**keywords])
A day.

class gTime( [**keywords])
A time.

6.8 Boolean

SOAP Booleans are Python integers.

class Boolean( [**keywords])
When marshaling zero or the word ``false'' is returned as 0 and any non-zero value or the word ``true'' is returned as 1. When serializing, the number 0 or 1 will be generated.

6.9 XML

XML is a Python DOM element node. If the value to be serialized is a Python string, then an href is generated, with the value used as the URI. This can be used, for example, when generating SOAP with attachments. Otherwise, the XML is typically put inside a wrapper element that sets the proper SOAP encoding style.

For efficiency, incoming XML is returend as a ``pointer'' into the DOM tree maintained within the ParsedSoap object. If that object is going to go out of scope, the data will be destroyed and any XML objects will become empty elements. The class instance variable copyit, if non-zero indicates that a deep copy of the XML subtree will be made and returned as the value. Note that it is generally more efficient to keep the ParsedSoap object alive until the XML data is no longerneeded.

class XML( [**keywords])
This typecode represents a portion of an XML document embedded in a SOAP message. The value is the element node.

The following keyword arguments may be used:

Keyword Default Description
copyit TC.XML.copyit Return a copy of the parsed data.
comments 0 Preserve comments in output.
inline 0 The XML sub-tree is single-reference, so can be output in-place.
resolver None A function that can resolve an absolute URI and return its content as an element node, as described in the ParsedSoap description.
wrapped 1 If zero, the XML is output directly, and not within a SOAP wrapper element. New in version 1.2.

When serializing, it may be necessary to specify which namespace prefixes are ``active'' in the XML. This is done by using the unsuppressedPrefixes parameter when calling the serialize() method. (This will only work when XML is the top-level item being serialized, such as when using typecodes and document-style interfaces.)

Keyword Default Description
unsuppressedPrefixes [] An array of strings identifying the namespace prefixes that should be output.

6.10 ComplexType

Represents the XMLSchema ComplexType . New in version 2.0.

class ComplexType( pyclass, ofwhat[, **keywords])
This class defines a compound data structure. If pyclass is None, then the data will be marshaled into a Python dictionary, and each item in the ofwhat sequence specifies a (possible) dictionary entry. Otherwise, pyclass must be a Python class object. The data is then marshaled into the object, and each item in the ofwhat sequence specifies an attribute of the instance to set.

Note that each typecode in ofwhat must have a name.

The following keyword arguments may be used:

Keyword Default Description
inorder False Items within the structure must appear in the order specified in the ofwhat sequence.
inline False The structure is single-reference, so ZSI does not have to use href/id encodings.
mutable False If an object is going to be serialized multiple times, and its state may be modified between serializations, then this keyword should be used, otherwise a single instance will be serialized, with multiple references to it. This argument implies the inline argument. New in version 1.2.
type None A "(uri, localname)" tuple that defines the type of the structure. If present, and if the input data has a xsi:type attribute, then the namespace-qualified value of that attribute must match the value specified by this parameter. By default, type-checking is not done for structures; matching child element names is usually sufficient and senders rarely provide type information.
mixed False using a mixed content model, allow text and element content.
mixed_aname '_text' if mixed is True, text content is set in this attribute (key).

If the typed keyword is used, then its value is assigned to all typecodes in the ofwhat parameter. If any of the typecodes in ofwhat are repeatable, then the inorder keyword should not be used and the hasextras parameter must be used.

For example, the following C structure:

struct foo {
    int i;
    char* text;
};
could be declared as follows:
class foo:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return str((self.name, self.i, self.text))

foo.typecode = TC.Struct(foo,
    ( TC.Integer('i'), TC.String('text') ),
    'foo')

6.11 Struct

SOAP Struct is a complex type for accessors identified by name. No element may have the same name as any other, nor may any element have a maxOccurs > 1. SOAP Structs are either Python dictionaries or instances of application-specified classes.

6.12 Arrays

SOAP arrays are Python lists; multi-dimensional arrays are lists of lists and are indistinguishable from a SOAP array of arrays. Arrays may be sparse, in which case each element in the array is a tuple of "(subscript, data)" pairs. If an array is not sparse, a specified fill element will be used for the missing values.

Currently only singly-dimensioned arrays are supported.

class Array( atype, ofwhat[, **keywords])
The atype parameter is a (URI,NCName) tuple representing the SOAP array type. The ofwhat parameter is a typecode describing the array elements.

The following keyword arguments may be used:

Keyword Default Description
childnames None Default name to use for the child elements.
dimensions 1 The number of dimensions in the array.
fill None The value to use when an array element is omitted.
mutable False If an object is going to be serialized multiple times, and its state may be modified between serializations, then this keyword should be used, otherwise a single instance will be serialized, with multiple references to it.
nooffset 0 Do not use the SOAP offset attribute so skip leading elements with the same value as fill.
sparse False The array is sparse.
size None An integer or list of integers that specifies the maximum array dimensions.
undeclared False The SOAP "arrayType" attribute need not appear.

6.13 Apache Datatype

The Apache SOAP project, urlhttp://xml.apache.org/soap/index.html, has defined a popular SOAP datatype in the http://xml.apache.org/xml-soap namespace, a Map.

The Map type is encoded as a list of item elements. Each item has a key and value child element; these children must have SOAP type information. An Apache Map is either a Python dictionary or a list of two-element tuples.

class Apache.Map( name[, **keywords])
An Apache map. Note that the class name is dotted.

The following keyword arguments may be used:

Keyword Default Description
aslist 0 Use a list of tuples rather than a dictionary.

7. The SoapWriter module -- serializing data

The SoapWriter class is used to output SOAP messages. Note that its output is encoded as UTF-8; when transporting SOAP over HTTP it is therefore important to set the charset attribute of the Content-Type header.

The SoapWriter class reserves some namespace prefixes:

Prefix URI
SOAP-ENV http://schemas.xmlsoap.org/soap/envelope/
SOAP-ENC http://schemas.xmlsoap.org/soap/encoding/
ZSI http://www.zolera.com/schemas/ZSI/
xsd http://www.w3.org/2001/XMLSchema
xsi http://www.w3.org/2001/XMLSchema-instance

class SoapWriter( optional**keywords)
The following keyword arguments may be used:

Keyword Default Description
encodingStyle None If not None, then use the specified value as the value for the SOAP encodingStyle attribute. New in version 1.2.
envelope True Create a SOAP Envelope New in version 1.2.
nsdict {} Dictionary of namespaces to declare in the SOAP Envelope
header True create a SOAP Header element
outputclass ElementProxy wrapper around DOM or other XML library.

Creating a SoapWriter object with envelope set to False results in an object that can be used for serializing objects into a string.

serialize( pyobj[, typecode=None[, root=None[, header_pyobjs=None[, **keywords]]]])
This method serializes the pyobj Python object as directed by the typecode typecode object. If typecode is omitted, then pyobj should be a Python object instance of a class that has a typecode attribute. It returns self, so that serializations can be chained together, or so that the close() method can be invoked. The root parameter may be used to explicitly indicate the root (main element) of a SOAP encoding, or indicate that the item is not the root. If specified, it should have the numeric value of zero or one. Any other keyword parameters are passed to the typecode's serialize method.

close( )
Invokes all the callbacks, if any. The close operations can only happen once, if invoked a second time it will just return. This method will be invoked automatically if the object is deleted.

__str__( )
Invokes the close method, and returns a string representation of the serialized object. Assumes that serialize has been invoked.

The following methods are primarily useful for those writing new typecodes.

AddCallback( func, arg)
Used by typecodes when serializing, allows them to add output after the SOAP Body is written but before the SOAP Envelope is closed. The function func() will be called with the SoapWriter object and the specified arg argument, which may be a tuple.

Forget( obj)
Forget that obj has been seen before. This is useful when repeatedly serializing a mutable object.

Known( obj)
If obj has been seen before (based on its Python id), return 1. Otherwise, remember obj and return 0.

ReservedNS( prefix, uri)
Returns true if the specified namespace prefix and uri collide with those used by the implementation.

writeNSDict( nsdict)
Outputs nsdict as a namespace dictionary. It is assumed that an XML start-element is pending on the output stream.

8. The Fault module -- reporting errors

SOAP defines a fault message as the way for a recipient to indicate it was unable to process a message. The ZSI Fault class encapsulates this.

class Fault( code, string[, **keywords])
The code parameter is a text string identifying the SOAP fault code, a namespace-qualified name. The class attribute Fault.Client can be used to indicate a problem with an incoming message, Fault.Server can be used to indicate a problem occurred while processing the request, or Fault.MU can be used to indicate a problem with the SOAP mustUnderstand attribute. The string parameter is a human-readable text string describing the fault.

The following keyword arguments may be used:

Keyword Default Description
actor None A string identifying the actor attribute that caused the problem (usually because it is unknown).
detail None A sequence of elements to output in the detail element; it may also be a text string, in which case it is output as-is, and should therefore be XML text.
headerdetail None Data, treated the same as the detail keyword, to be output in the SOAP header. See the following paragraph.

If the fault occurred in the SOAP Header, the specification requires that the detail be sent back as an element within the SOAP Header element. Unfortunately, the SOAP specification does not describe how to encode this; ZSI defines and uses a ZSI:detail element, which is analogous to the SOAP detail element.

The following attributes are read-only:

actor
A text string holding the value of the SOAP faultactor element.

code
A text string holding the value of the SOAP faultcode element.

detail
A text string or sequence of elements containing holding the value of the SOAP detail element, when available.

headerdetail
A text string or sequence of elements containing holding the value of the ZSI header detail element, when available.

string
A text string holding the value of the SOAP faultstring element.

AsSOAP( [, **kw])
This method serializes the Fault object into a SOAP message. The message is returned as a string. Any keyword arguments are passed to the SoapWriter constructor. New in version 1.1; the old AsSoap() method is still available.

If other data is going to be sent with the fault, the following two methods can be used. Because some data might need to be output in the SOAP Header, serializing a fault is a two-step process.

DataForSOAPHeader( )
This method returns a text string that can be included as the header parameter for constructing a SoapWriter object.

serialize( sw)
This method outputs the fault object onto the sw object, which is a SoapWriter instance.

Some convenience functions are available to create a Fault from common conditions.

FaultFromActor( uri[, actor])
This function could be used when an application receives a message that has a SOAP Header element directed to an actor that cannot be processed. The uri parameter identifies the actor. The actor parameter can be used to specify a URI that identifies the application, if it is not the ultimate recipient of the SOAP message.

FaultFromException( ex, inheader[, tb[, actor]])
This function creates a Fault from a general Python exception. A SOAP ``server'' fault is created. The ex parameter should be the Python exception. The inheader parameter should be true if the error was found on a SOAP Header element. The optional tb parameter may be a Python traceback object, as returned by "sys.exc_info()[2]". The actor parameter can be used to specify a URI that identifies the application, if it is not the ultimate recipient of the SOAP message.

FaultFromFaultMessage( ps)
This function creates a Fault from a ParsedSoap object passed in as ps. It should only be used if the IsAFault() method returned true.

FaultFromNotUnderstood( uri, localname,[, actor])
This function could be used when an application receives a message with the SOAP mustUnderstand attribute that it does not understand. The uri and localname parameters should identify the unknown element. The actor parameter can be used to specify a URI that identifies the application, if it is not the ultimate recipient of the SOAP message.

FaultFromZSIException( ex[, actor])
This function creates a Fault object from a ZSI exception, ParseException or EvaluateException, passed in as ex. A SOAP ``client'' fault is created. The actor parameter can be used to specify a URI that identifies the application, if it is not the ultimate recipient of the SOAP message.

9. The resolvers module -- fetching remote data

The resolvers module provides some functions and classes that can be used as the resolver attribute for TC.String or TC.XML typecodes. They process an absolute URL, as described above, and return the content. Because the resolvers module can import a number of other large modules, it must be imported directly, as in "from ZSI import resolvers".

These first two functions pass the URI directly to the urlopen function in the urllib module. Therefore, if used directly as resolvers, a client could direct the SOAP application to fetch any file on the network or local disk. Needless to say, this could pose a security risks.

Opaque( uri, tc, ps[, **keywords])
This function returns the data contained at the specified uri as a Python string. Base-64 decoding will be done if necessary. The tc and ps parameters are ignored; the keywords are passed to the urlopen method.

XML( uri, tc, ps[, **keywords])
This function returns a list of the child element nodes of the XML document at the specified uri. The tc and ps parameters are ignored; the keywords are passed to the urlopen method.

The NetworkResolver class provides a simple-minded way to limit the URI's that will be resolved.

class NetworkResolver( [prefixes=None])
The prefixes parameter is a list of strings defining the allowed prefixes of any URI's. If asked to fetch the content for a URI that does start with one of the prefixes, it will raise an exception.

In addition to Opaque and XML methods, this class provides a Resolve method that examines the typecode to determine what type of data is desired.

If the SOAP application is given a multi-part MIME document, the MIMEResolver class can be used to process SOAP with Attachments.

The MIMEResolver class will read the entire multipart MIME document, noting any Content-ID or Content-Location headers that appear on the headers of any of the message parts, and use them to resolve any href attributes that appear in the SOAP message.

class MIMEResolver( ct, f[, **keywords])
The ct parameter is a string that contains the value of the MIME Content-Type header. The f parameter is the input stream, which should be positioned just after the message headers.

The following keyword arguments may be used:

Keyword Default Description
seekable 0 Whether or not the input stream is seekable; passed to the constructor for the internal multifile object. Changed in version 2.0: default had been 1.
next None A resolver object that will be asked to resolve the URI if it is not found in the MIME document. New in version 1.1.
uribase None The base URI to be used when resolving relative URI's; this will typically be the value of the Content-Location header, if present. New in version 1.1.

In addition to to the Opaque, Resolve, and XML methods as described above, the following method is available:

GetSOAPPart( )
This method returns a stream containing the SOAP message text.

The following attributes are read-only:

parts
An array of tuples, one for each MIME bodypart found. Each tuple has two elements, a mimetools.Message object which contains the headers for the bodypart, and a StringIO object containing the data.

id_dict
A dictionary whose keys are the values of any Content-ID headers, and whose value is the appropriate parts tuple.

loc_dict
A dictionary whose keys are the values of any Content-Location headers, and whose value is the appropriate parts tuple.

10. Dispatching and Invoking

New in version 1.1.

ZSI is focused on parsing and generating SOAP messages, and provides limited facilities for dispatching to the appropriate message handler. This is because ZSI works within many client and server environments, and the dispatching styles for these different environments can be very different.

Nevertheless, ZSI includes some dispatch and invocation functions. To use them, they must be explicitly imported, as shown in the example at the start of this document.

The implementation (and names) of the these classes reflects the orientation of using SOAP for remote procedure calls (RPC).

Both client and server share a class that defines the mechanism a client uses to authenticate itself.

class AUTH( )
This class defines constants used to identify how the client authenticated: none if no authentication was provided; httpbasic if HTTP basic authentication was used, or zsibasic if ZSI basic authentication (see below)) was used.

The ZSI schema (see the last chapter of this manual) defines a SOAP header element, BasicAuth, that contains a name and password. This is similar to the HTTP basic authentication header, except that it can be used independently from an HTTP transport.

10.1 Dispatching

The ZSI.dispatch module allows you to expose Python functions as a web service. The module provides the infrastructure to parse the request, dispatch to the appropriate handler, and then serialize any return value back to the client. The value returned by the function will be serialized back to the client. If an exception occurs, a SOAP fault will be sent back to the client.

10.1.1 Dispatch Behaviors

By default the callback is invoked with the pyobj representation of the body root element, and it is expected to return a self-describing request (w/typecode). Parsing is done via a typecode from typesmodule, or Any. Other keyword options are available in dispatch mechanisms (see below) that result in different behavior.

10.1.1.1 rpc

An rpc service will ignore the body root (RPC Wrapper) of the request, and parse all "parts" of message via individual typecodes. The callback function is expected to return the parts of the message in a dict or a list. The dispatch mechanism will try to serialize it as a Struct but if this is not possible it will be serialized as an Array. Parsing done via a typecode from typesmodule, or Any. Not compatible with docstyle.

10.1.1.2 docstyle

Callback is invoked with a ParsedSoap instance representing the request, and the return value is serialized with an XML typecode (DOM). The result in wrapped as an rpc-style message, with Response appended to the request wrapper. Not compatible with rpc.

10.1.2 Special Modules

These are keyword options available to all dispatch mechansism (see below).

10.1.2.1 modules

Dispatch is based solely on the name of the root element in the incoming SOAP request; the request URL is ignored. These modules will be search for a matching function. If no modules are specified, only the __main__ module will be searched.

10.1.2.2 typesmodule

Used for parsing. This module should contain class definitions with the typecode attribute set to a TypeCode instance. By default, a class definition matching the root element name will be retrieved or the Any typecode will be used. If using rpc, each child of the root element will be used to retrieve a class definition of the same name.

10.1.3 Dispatch Mechanisms

Three dispatch mechanisms are provided: one supports standard CGI scripts, one runs a dedicated server based on the BaseHTTPServer module, and the third uses the JonPY package, http://jonpy.sourceforge.net, to support FastCGI.

AsServer( [**keywords])
This creates a HTTPServer object with a request handler that only supports the ``POST'' method. Dispatch is based solely on the name of the root element in the incoming SOAP request; the request URL is ignored.

The following keyword arguments may be used:

Keyword Default Description
port 80 Port to listen on.
addr '' Address to listen on.
docstyle False Exhibit the docstyle behavior.
rpc False Exhibit the rpc behavior.
modules (__main__,) List of modules containing functions that can be invoked.
typesmodule (__main__,) This module is used for parsing, it contains class definitions that specify the typecode attribute.
nsdict {} Namespace dictionary to send in the SOAP Envelope

AsCGI( [**keywords])
This method parses the CGI input and invokes a function that has the same name as the top-level SOAP request element.

The following keyword arguments may be used:

Keyword Default Description
rpc False Exhibit the rpc behavior.
modules (__main__,) List of modules containing functions that can be invoked.
typesmodule (__main__,) This module is used for parsing, it contains class definitions that specify the typecode attribute.
nsdict {} Namespace dictionary to send in the SOAP Envelope

AsHandler( request=None[, **keywords])

This method is used within a JonPY handler to do dispatch.

The following keyword arguments may be used:

Keyword Default Description
request None modpython HTTPRequest instance.
modules (__main__,) List of modules containing functions that can be invoked.
docstyle False Exhibit the docstyle behavior.
rpc False Exhibit the rpc behavior.
typesmodule (__main__,) This module is used for parsing, it contains class definitions that specify the typecode attribute.
nsdict {} Namespace dictionary to send in the SOAP Envelope

AsJonPy( request=None[, **keywords])

This method is used within a JonPY handler to do dispatch.

The following keyword arguments may be used:

Keyword Default Description
request None jonpy Request instance.
modules (__main__,) List of modules containing functions that can be invoked.
docstyle False Exhibit the docstyle behavior.
rpc False Exhibit the rpc behavior.
typesmodule (__main__,) This module is used for parsing, it contains class definitions that specify the typecode attribute.
nsdict {} Namespace dictionary to send in the SOAP Envelope

The following code shows a sample use:

import jon.fcgi
from ZSI import dispatch
import MyHandler

class Handler(cgi.Handler):
    def process(self, req):
        dispatch.AsJonPy(modules=(MyHandler,), request=req)

jon.fcgi.Server({jon.fcgi.FCGI_RESPONDER: Handler}).run()

10.1.4 Other Dispatch Stuff

GetClientBinding( )
More sophisticated scripts may want to use access the client binding object, which encapsulates all information about the client invoking the script. This function returns None or the binding information, an object of type ClientBinding, described below.

class ClientBinding( ...)
This object contains information about the client. It is created internally by ZSI.

GetAuth( )
This returns a tuple containing information about the client identity. The first element will be one of the constants from the AUTH class described above. For HTTP or ZSI basic authentication, the next two elements will be the name and password provided by the client.

GetNS( )
Returns the namespace URI that the client is using, or an empty string. This can be useful for versioning.

GetRequest( )
Returns the ParsedSoap object of the incoming request.

The following attribute is read-only:

environ
A dictionary of the environment variables. This is most useful when AsCGI() is used.

10.2 The client module -- sending SOAP messages

ZSI includes a module to connect to a SOAP server over HTTP, send requests, and parse the response. It is built on the standard Python httplib and Cookie modules. It must be explicitly imported, as in "from ZSI.client import AUTH,Binding".

10.2.1 _Binding

class _Binding( [**keywords])
This class encapsulates a connection to a server, known as a binding. A single binding may be used for multiple RPC calls. Between calls, modifiers may be used to change the URL being posted to, etc.

Cookies are also supported; if a response comes back with a Set-Cookie header, it will be parsed and used in subsequent interactions.

The following keyword arguments may be used:

Keyword Default Description
auth (AUTH.none,) A tuple with authentication information; the first value should be one of the constants from the AUTH class.
nsdict {} Namespace dictionary to send in the SOAP Envelope
soapaction '' Value for the SOAPAction HTTP header.
readerclass None Class used to create DOM-creating XML readers; see the description in the ParsedSoap class.
writerclass None ElementProxy Class used to create XML writers; see the description in the SoapWriter class.
tracefile None An object with a write method, where packet traces will be recorded.
transport HTTPConnection/HTTPSConnection transport class
transdict {} keyword arguments for connection initialization
url n/a URL to post to.
wsAddressURI None URI, identifies the WS-Address specification to use. By default it's not used.
sig_handler None XML Signature handler, must sign and verify.

If using SSL, the cert_file and key_file keyword parameters may be passed to the transport's constructor via the transdict. For details about HTTPSConnection see the documentation for the httplib module.

Once a _Binding object has been created, the following modifiers are available. All of them return the binding object, so that multiple modifiers can be chained together.

AddHeader( header, value)
Output the specified header and value with the HTTP headers.

SetAuth( style, name, password)
The style should be one of the constants from the AUTH class described above. The remaining parameters will vary depending on the style. Currently only basic authentication data of name and password are supported.

SetNS( uri)
Set the default namespace for the request to the specified uri.

SetURL( url)
Set the URL where the post is made to url.

ResetHeaders( )
Remove any headers that were added by AddHeader().

The following attribute may also be modified:

trace
If this attribute is not None, it should be an object with a write method, where packet traces will be recorded.

Once the necessary parameters have been specified (at a minimum, the URL must have been given in the constructor are through SetURL), invocations can be made.

RPC( url, opname, pyobj, replytype=None[, **keywords])
This is the highest-level invocation method. It calls Send() to send pyobj to the specified url to perform the opname operation, and calls Receive() expecting to get a reply of the specified replytype.

This method will raise a TypeError if the response does not appear to be a SOAP message, or if is valid SOAP but contains a fault.

Send( url, opname, pyboj[, **keywords])
This sends the specified pyobj to the specified url, invoking the opname method. The url can be None if it was specified in the Binding constructor or if SetURL has been called. See below for a shortcut version of this method.

The following keyword arguments may be used:

SOAP Envelope
Keyword Default Description
auth_header None String (containing presumably serialized XML) to output as an authentication header.
nsdict {} Namespace dictionary to send in the SOAP Envelope
requesttypecode n/a Typecode specifying how to serialize the data.
soapaction Obtained from the Binding Value for the SOAPAction HTTP header.

Methods are available to determine the type of response that came back:

IsSOAP( )
Returns true if the message appears to be a SOAP message. (Some servers return an HTML page under certain error conditions.)

IsAFault( )
Returns true if the message is a SOAP fault.

Having determined the type of the message (or, more likely, assuming it was good and catching an exception if not), the following methods are available to actually parse the data. They will continue to return the same value until another message is sent.

ReceiveRaw( )
Returns the unparsed message body.

ReceiveSoap( )
Returns a ParsedSOAP object containing the parsed message. Raises a TypeError if the message wasn't SOAP.

ReceiveFault( )
Returns a Fault object containing the SOAP fault message. Raises a TypeError if the message did not contain a fault.

Receive( replytype=None)
Parses a SOAP message. The replytype specifies how to parse the data. If it s None, dynamic parsing will be used, usually resulting in a Python list. If replytype is a Python class, then the class's typecode attribute will be used, otherwise replytype is taken to be the typecode to use for parsing the data.

Once a reply has been parsed (or its type examined), the following read-only attributes are available. Their values will remain unchanged until another reply is parsed.

reply_code
The HTTP reply code, a number.

reply_headers
The HTTP headers, as a mimetools object.

reply_msg
A text string containing the HTTP reply text.

10.2.2 Binding

If an attribute is fetched other than one of those described in _Binding, it is taken to be the opname of a remote procedure, and a callable object is returned. This object dynamically parses its arguments, receives the reply, and parses that.

class Binding( [**keywords])
For other keyword arguments see _Binding.
Keyword Default Description
typesmodule None See explanation in Dispatching

opname( *args)
Using this shortcut requires that the url attribute is set, either throught the constructor or SetURL().

10.2.3 NamedParamBinding

If an attribute is fetched other than one of those described in _Binding, it is taken to be the opname of a remote procedure, and a callable object is returned. This object dynamically parses its arguments, receives the reply, and parses that.

class NamedParamBinding( [**keywords])
For other keyword arguments see _Binding.
Keyword Default Description
typesmodule None See explanation in Dispatching

opname( **kwargs)
Using this shortcut requires that the url attribute is set, either throught the constructor or SetURL().

11. Bibliography

Bibliography

1
This is the first item in the Bibliography.

2
This is the second item in the Bibliography.

A. CGI Script Array

A.1 Intro

This is an example of a simple web service CGI Script. The service returns and expects SOAP Arrays (python list). A sample soap trace is provided below. In this example the CGI script is dispatched as a rpc service.

A.1.1 rpc wrapper

The wrapper element of the request is the dispatch key to the callback function, the child elements are passes as a list or dict of values to the callback function. The callback function is expected to return a list or dict of values, the response wrapper is by default set to the request wrapper name appended Response.

A.2 CGI Script

#!/usr/local/bin/python2.4
# SOAP Array

def hello():
    return ["Hello, world"]

def echo(*args):
    return args

def sum(*args):
    sum = 0
    for i in args: sum += i
    return [sum]

def average(*args):
    return [sum(*args) / len(args)]

from ZSI import dispatch
dispatch.AsCGI(rpc=True)

A.3 client test script

#!/usr/bin/env python
# client.py
import sys
from ZSI.client import Binding
b = Binding(url='http://127.0.0.1/cgi-bin/simple', tracefile=sys.stdout)
print b.hello()
try:
    print b.hello(1)
except Exception, ex:
    print "Fault: ", ex

print b.echo("whatever", "hi", 1, 2)
print b.sum(*[2*i for i in range(5)])
print b.average(*[2*i for i in range(5)])

A.4 SOAP Trace

A.4.1 hello

$ ./client.py 
Hello:  _________________________________ Wed Oct  4 17:36:33 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<hello SOAP-ENC:arrayType="xsd:anyType[0]"></hello>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

_________________________________ Wed Oct  4 17:36:34 2006 RESPONSE:
200

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<helloResponse SOAP-ENC:arrayType="xsd:anyType[1]">
			<element id="o671b0" xsi:type="xsd:string">Hello, world</element>
		</helloResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
[u'Hello, world']

A.4.2 hello fault

_________________________________ Wed Oct  4 17:36:34 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<hello SOAP-ENC:arrayType="xsd:anyType[1]">
			<element id="o1803988" xsi:type="xsd:int">1</element>
		</hello>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
_________________________________ Wed Oct  4 17:36:35 2006 RESPONSE:
500

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<SOAP-ENV:Fault>
			<faultcode>SOAP-ENV:Server</faultcode>
			<faultstring>Processing Failure</faultstring>
			<detail>
				<ZSI:FaultDetail>
<ZSI:string>exceptions:TypeError hello() takes no arguments (1 given)</ZSI:string>
<ZSI:trace>build/bdist.darwin-8.8.0-Power_Macintosh/egg/ZSI/dispatch.py:86:_Dispatch</ZSI:trace>
				</ZSI:FaultDetail>
			</detail>
		</SOAP-ENV:Fault>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Fault:  Processing Failure
exceptions:TypeError
hello() takes no arguments (1 given)
[trace: build/bdist.darwin-8.8.0-Power_Macintosh/egg/ZSI/dispatch.py:86:_Dispatch]

A.4.3 echo

_________________________________ Wed Oct  4 17:36:35 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<echo SOAP-ENC:arrayType="xsd:anyType[4]">
			<element id="o644c0" xsi:type="xsd:string">whatever</element>
			<element id="o644e0" xsi:type="xsd:string">hi</element>
			<element id="o1803988" xsi:type="xsd:int">1</element>
			<element id="o180397c" xsi:type="xsd:int">2</element>
		</echo>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
_________________________________ Wed Oct  4 17:36:36 2006 RESPONSE:
200

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<echoResponse SOAP-ENC:arrayType="xsd:anyType[4]">
			<element id="o4f4290" xsi:type="xsd:string">whatever</element>
			<element id="o4f4338" xsi:type="xsd:string">hi</element>
			<element id="o1803988" xsi:type="xsd:int">1</element>
			<element id="o180397c" xsi:type="xsd:int">2</element>
		</echoResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

[u'whatever', u'hi', 1, 2]

A.4.4 sum

_________________________________ Wed Oct  4 17:36:36 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<sum SOAP-ENC:arrayType="xsd:anyType[5]">
			<element id="o1803994" xsi:type="xsd:int">0</element>
			<element id="o180397c" xsi:type="xsd:int">2</element>
			<element id="o1803964" xsi:type="xsd:int">4</element>
			<element id="o180394c" xsi:type="xsd:int">6</element>
			<element id="o1803934" xsi:type="xsd:int">8</element>
		</sum>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
_________________________________ Wed Oct  4 17:36:37 2006 RESPONSE:
200

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<sumResponse SOAP-ENC:arrayType="xsd:anyType[1]">
			<element id="o18038a4" xsi:type="xsd:int">20</element>
		</sumResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
[20]

A.4.5 average

_________________________________ Wed Oct  4 17:36:37 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<average SOAP-ENC:arrayType="xsd:anyType[5]">
			<element id="o1803994" xsi:type="xsd:int">0</element>
			<element id="o180397c" xsi:type="xsd:int">2</element>
			<element id="o1803964" xsi:type="xsd:int">4</element>
			<element id="o180394c" xsi:type="xsd:int">6</element>
`			<element id="o1803934" xsi:type="xsd:int">8</element>
		</average>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
_________________________________ Wed Oct  4 17:36:38 2006 RESPONSE:
200

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<averageResponse SOAP-ENC:arrayType="xsd:anyType[1]">
			<element id="o1803964" xsi:type="xsd:int">4</element>
		</averageResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
[4]

B. CGI Script Struct

B.1 Intro

This is an example of a simple web service CGI Script. The service returns and expects SOAP Structs (python dict). A sample soap trace is provided below. In this example the CGI script is dispatched as a rpc service.

B.1.1 rpc wrapper

The wrapper element of the request is the dispatch key to the callback function, the child elements are passes as a list or dict of values to the callback function. The callback function is expected to return a list or dict of values, the response wrapper is by default set to the request wrapper name appended Response.

B.2 CGI Script

#!/usr/local/bin/python2.4
# SOAP Struct

def hello():
    return {"value":"Hello, world"}

def echo(**kw):
    return kw

def sum(**kw):
    sum = 0
    for i in kw.values(): sum += i
	return {"value":sum}

def average(**kw):
	d = sum(**kw)
    return d["value"] = d["value"]/len(kw)

from ZSI import dispatch
dispatch.AsCGI(rpc=True)

B.3 client test script

#!/usr/bin/env python
import sys,time
from ZSI.client import NamedParamBinding as NPBinding

b = NPBinding(url='http://127.0.0.1/cgi-bin/soapstruct', tracefile=sys.stdout)
print "Hello: ", b.hello()
print "Echo: ", b.echo(name="josh", year=2006, pi=3.14, time=time.gmtime())
print "Sum: ", b.sum(one=1, two=2, three=3)
print "Average: ", b.average(one=100, two=200, three=300, four=400)

B.4 SOAP Trace

B.4.1 hello

C. Complete Low Level Example

C.1 Intro

This is a complete example of using the low level soap utilities in ZSI to implement a web service.

C.2 code

C.2.1 httpserver script

Minimal http server example, opens up a new process to do the SOAP processing.
#!/usr/bin/env python
# file: httpserver.py
import os
from subprocess import Popen, PIPE
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

class RequestHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers['content-length'])
        xml_in = self.rfile.read(length)
        p = Popen(os.path.join(os.path.curdir, 'player.py'),
                  shell=True, stdin=PIPE, stdout=PIPE)

        (stdout, stderr) = p.communicate(xml_in)
        code = 200
        if stdout.find('Fault') >= 0: code = 500 
        self.send_response(code)
        self.send_header('Content-type', 'text/xml; charset="utf-8"')
        self.send_header('Content-Length', str(len(stdout)))
        self.end_headers()
        self.wfile.write(stdout)
        self.wfile.flush()

if __name__ == '__main__':
    server = HTTPServer(('localhost', 8080), RequestHandler)
    server.serve_forever()

C.2.2 typecode module

# file: typecode.py
# CHECK PYTHONPATH: Must be able to import
class Player:
    def __init__(self, *args):
        if not len(args): return
        self.Name = args[0]
        self.Scores = args[1:]
Player.typecode = TC.Struct(Player, [
                                TC.String('Name'),
                                TC.Array('Integer', TC.Integer(), 'Scores', undeclared=True),
                                ], 'GetAverage')
class Average:
    def __init__(self, average=None):
        self.average = average
Average.typecode = TC.Struct(Average, [
                                TC.Integer('average'),
                                ], 'GetAverageResponse')

C.2.3 player script

#!/usr/bin/env python
# file: player.py
from ZSI import *
import sys
IN, OUT = sys.stdin, sys.stdout
try:
    ps = ParsedSoap(IN)
except ParseException, e:
    OUT.write(FaultFromZSIException(e).AsSOAP())
    sys.exit(1)
except Exception, e:
    # Faulted while processing; we assume it's in the header.
    OUT.write(FaultFromException(e, 1).AsSOAP())
    sys.exit(1)

# We are not prepared to handle any actors or mustUnderstand elements,
# so we'll arbitrarily fault back with the first one we found.
a = ps.WhatActorsArePresent()
if len(a):
    OUT.write(FaultFromActor(a[0]).AsSOAP())
    sys.exit(1)
mu = ps.WhatMustIUnderstand()
if len(mu):
    uri, localname = mu[0]
    OUT.write(FaultFromNotUnderstood(uri, localname).AsSOAP())
    sys.exit(1)

from typecode import Player, Average
try:
    player = ps.Parse(Player.typecode)
except EvaluateException, e:
    OUT.write(FaultFromZSIException(e).AsSOAP())
    sys.exit(1)

try:
    total = 0
    for value in player.Scores: total = total + value
    result = Average(total / len(player.Scores))
    sw = SoapWriter()
    sw.serialize(result, Average.typecode)
    sw.close()
    OUT.write(str(sw))
except Exception, e:
    OUT.write(FaultFromException(e, 0, sys.exc_info()[2]).AsSOAP())
    sys.exit(1)

C.2.4 client test script

#!/usr/bin/env python2.4
#file: client.py
from ZSI import *
from ZSI.wstools.Namespaces import SCHEMA
from typecode import Player, Average

if __name__ == '__main__':
    import sys
    from ZSI.client import Binding
    b = Binding(url='http://localhost:8080', tracefile=sys.stdout)
    pyobj = b.RPC(None, None, Player("Josh",10,20,30), replytype=Average)
    print pyobj
    print pyobj.__dict__

C.3 SOAP Trace

C.3.1 GetAverage

$./client.py 
_________________________________ Thu Oct  5 14:57:39 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<GetAverage>
			<Name xsi:type="xsd:string">Josh</Name>
			<Scores>
				<element>10</element>
				<element>20</element>
				<element>30</element>
			</Scores>
		</GetAverage>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
_________________________________ Thu Oct  5 14:57:39 2006 RESPONSE:
200
OK
-------
Server: BaseHTTP/0.3 Python/2.5
Date: Thu, 05 Oct 2006 21:57:39 GMT
Content-type: text/xml; charset="utf-8"
Content-Length: 431

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<GetAverageResponse>
			<average>20</average>
		</GetAverageResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

<__main__.Average instance at 0x5f9760>
{'average': 20}

C.3.2 fault

Purposely send a incorrect Nae element for the Name.
$./client.py 
_________________________________ Thu Oct  5 14:33:25 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<GetAverage>
			<Nae xsi:type="xsd:string">Josh</Nae>
			<Scores>
				<element>10</element>
				<element>20</element>
				<element>30</element>
			</Scores>
		</GetAverage>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

_________________________________ Thu Oct  5 14:33:26 2006 RESPONSE:
500
Internal Server Error

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<SOAP-ENV:Fault>
			<faultcode>SOAP-ENV:Client</faultcode>
			<faultstring>Unparseable message</faultstring>
			<detail><Eoe440>&lt;ZSI:ParseFaultDetail&gt;
&lt;ZSI:string&gt;Element "Name" missing from complexType&lt;/ZSI:string&gt;
&lt;ZSI:trace&gt;/SOAP-ENV:Envelope/SOAP-ENV:Body/GetAverage&lt;/ZSI:trace&gt;
&lt;/ZSI:ParseFaultDetail&gt;</Eoe440></detail>
		</SOAP-ENV:Fault>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Traceback (most recent call last):
  File "./player_client.py", line 25, in ?
    pyobj = b.RPC(None, None, Player("Josh",10,20,30), replytype=Average)
  File "/private/var/www/htdocs/guide/client.py", line 176, in RPC
    
  File "/private/var/www/htdocs/guide/client.py", line 420, in Receive
    
ZSI.FaultException: Unparseable message
<Element Node at 5f9f58: Name='Eoe440' with 0 attributes and 1 children>

D. pickler example

D.1 Intro

This is an example of a stateful mod_python web service.

D.2 code

D.2.1 typecode module

Module containing complex type typecode.
# Complex type definition
from ZSI import *
class Person:
  def __init__(self, name=None, age=0):
    self.name = name
    self.age = age

Person.typecode = TC.Struct(Person,
                            [TC.String('name'),
                             TC.InonNegativeInteger('age')],
                            pname=('urn:MyApp','Person'))

D.2.2 pickler script

Configure appache to use this script with mod_python PythonHandler.
# pickler.py
import pickle, new
from mod_python import apache
from ZSI import dispatch
import MyComplexTypes

# my web service that returns a complex structure
def getPerson(name=None):
  #fp = open('/tmp/%s.person.pickle'%Person.name, 'r')
  fp = open('/tmp/%s.person.pickle'%name, 'r')
  #return pickle.load(fp)
  p = pickle.load(fp)
  print "PERSON: ", p
  print "typecode: ", p.typecode
  return p

# my web service that accepts a complex structure
def savePerson(Person):
  print "PERSON: ", Person
  fp = open('/tmp/%s.person.pickle'%Person.name, 'w')
  pickle.dump(Person, fp)
  fp.close()
  return {}

mod = __import__('encodings.utf_8', globals(), locals(), '*')
mod = __import__('encodings.utf_16_be', globals(), locals(), '*')


handles = new.module('handles')
handles.getPerson = getPerson
handles.savePerson = savePerson
def handler(req):
    dispatch.AsHandler(modules=(handles,), request=req, typesmodule=MyComplexTypes, rpc=True)
    return apache.OK

D.2.3 client: invoke savePerson

D.2.3.1 script

import sys
from ZSI.client import Binding
from MyComplexTypes import Person

b = Binding(url='http://localhost/test3/pickler.py', tracefile=sys.stdout)
person = Person('christopher', 26)
b.savePerson(person)

D.2.3.2 SOAP Trace

_________________________________ Wed Oct 11 13:10:05 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<savePerson xmlns:ns1="urn:MyApp">
			<ns1:Person><name xsi:type="xsd:string">christopher</name>
				<age xsi:type="xsd:nonNegativeInteger">26</age>
			</ns1:Person>
		</savePerson>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

_________________________________ Wed Oct 11 13:10:05 2006 RESPONSE:
Server: Apache/2.0.53-dev (Unix) mod_ruby/1.2.4 Ruby/1.8.2(2004-12-25) 
mod_python/3.1.4 Python/2.4.1
Transfer-Encoding: chunked
Content-Type: text/xml

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<savePersonResponse></savePersonResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

D.2.4 client: invoke getPerson 3 different ways

D.2.4.1 script

import sys
import MyComplexTypes
from ZSI.client import NamedParamBinding as NPBinding, Binding
from ZSI import TC

kw = {'url':'http://localhost/test3/pickler.py', 'tracefile':sys.stdout}
b = NPBinding(**kw)
rsp = b.getPerson(name='christopher')
assert type(rsp) is dict, 'expecting a dict'
assert rsp['Person']['name'] == 'christopher', 'wrong person'

b = NPBinding(typesmodule=MyComplexTypes, **kw)
rsp = b.getPerson(name='christopher')
assert isinstance(rsp['Person'], MyComplexTypes.Person), (
    'expecting instance of %s' %MyComplexTypes.Person)

b = Binding(typesmodule=MyComplexTypes, **kw)
class Name(str):
    typecode = TC.String("name")

rsp = b.getPerson(Name('christopher'))
assert isinstance(rsp['Person'], MyComplexTypes.Person), (
    'expecting instance of %s' %MyComplexTypes.Person)

D.2.4.2 SOAP Trace

All responses are exactly the same, for comparison the three requests are presented first and only the last response is included.
_________________________________ Wed Oct 11 13:19:00 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<getPerson>
			<name id="o6c2a0" xsi:type="xsd:string">christopher</name>
		</getPerson>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

** OMIT RESPONSE **

_________________________________ Wed Oct 11 13:19:00 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<getPerson>
			<name id="o6c2a0" xsi:type="xsd:string">christopher</name>
		</getPerson>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

** OMIT RESPONSE **

_________________________________ Wed Oct 11 13:19:00 2006 REQUEST:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<getPerson>
			<name xsi:type="xsd:string">christopher</name>
		</getPerson>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

_________________________________ Wed Oct 11 13:19:00 2006 RESPONSE:
Server: Apache/2.0.53-dev (Unix) mod_ruby/1.2.4 Ruby/1.8.2(2004-12-25) 
mod_python/3.1.4 Python/2.4.1
Transfer-Encoding: chunked
Content-Type: text/xml

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
	xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
	xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<SOAP-ENV:Header></SOAP-ENV:Header>
	<SOAP-ENV:Body>
		<getPersonResponse xmlns:ns1="urn:MyApp">
			<ns1:Person>
				<name xsi:type="xsd:string">christopher</name>
				<age xsi:type="xsd:nonNegativeInteger">26</age>
			</ns1:Person>
		</getPersonResponse>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

About this document ...

ZSI: The Zolera Soap Infrastructure
Developer's Guide
, November 01, 2007, Release 2.1.0

This document was generated using the LaTeX2HTML translator.

LaTeX2HTML is Copyright © 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds, and Copyright © 1997, 1998, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The application of LaTeX2HTML to the Python documentation has been heavily tailored by Fred L. Drake, Jr. Original navigation icons were contributed by Christopher Petrilli.

ZSI-2.1-a1/doc/previous.png0000644000175100017510000000077710437331051013655 0ustar zsizsi‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f?0­bKGD{¼l“IDATxÚÕ’Aà DiIZ¼ÿe›€/Ù8vÛÎvþÃ$Ä/ ¿H5=°÷SÊ`óƒ'R3¿ÈÀjþŽBŠûj±y Registration web service ZSI-2.1-a1/doc/examples/server/receive_request/complex/manual/0000755000175100017510000000000010712455110022521 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/complex/manual/ComplexTypes.py0000644000175100017510000000064210046173213025532 0ustar zsizsifrom ZSI import TC class User: def __init__(self, name=None, userId=None, age=-1): self.Name = name self.UserId = userId self.Age = age User.typecode = TC.Struct(User, [TC.String('Name', oname='Name'), TC.String('UserId', oname='UserId'), TC.Iinteger('Age', oname='Age')], 'User') ZSI-2.1-a1/doc/examples/server/receive_request/complex/manual/.cvsignore0000644000175100017510000000000610046173766024533 0ustar zsizsi*.pyc ZSI-2.1-a1/doc/examples/server/receive_request/complex/manual/server.py0000755000175100017510000000033610046173213024407 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch import ComplexTypes as MyComplexTypes def RegisterUser(user): return "OK" if __name__ == '__main__': dispatch.AsServer(port=8080, typesmodule=(MyComplexTypes,)) ZSI-2.1-a1/doc/examples/server/receive_request/complex/interface.wsdl0000644000175100017510000000160410046173213024101 0ustar zsizsi ZSI-2.1-a1/doc/examples/server/receive_request/complex/types.xsd0000644000175100017510000000056710046173213023141 0ustar zsizsi ZSI-2.1-a1/doc/examples/server/receive_request/complex/wsdl2py/0000755000175100017510000000000010712455110022650 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/complex/wsdl2py/.cvsignore0000644000175100017510000000002710046173213024650 0ustar zsizsiRegistration_services* ZSI-2.1-a1/doc/examples/server/receive_request/complex/wsdl2py/server.py0000755000175100017510000000056110046173213024536 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch import Registration_services_types from Registration_services import RegisterUserResponseWrapper def RegisterUser(user): response = RegisterUserResponseWrapper() response._Message = "OK" return response if __name__ == '__main__': dispatch.AsServer(port=8080, typesmodule=(Registration_services_types,)) ZSI-2.1-a1/doc/examples/server/receive_request/complex/client/0000755000175100017510000000000010712455110022522 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/complex/client/ComplexTypes.py0000644000175100017510000000065010046173213025532 0ustar zsizsifrom ZSI import TC class User: def __init__(self, name=None, userId=None, age=-1): self.Name = name self.UserId = userId self.Age = age User.typecode = TC.Struct(User, [TC.String('Name', oname='Name'), TC.String('UserId', oname='UserId'), TC.Iinteger('Age', oname='Age')], 'types:User') ZSI-2.1-a1/doc/examples/server/receive_request/complex/client/.cvsignore0000644000175100017510000000000610046173213024517 0ustar zsizsi*.pyc ZSI-2.1-a1/doc/examples/server/receive_request/complex/client/client.py0000755000175100017510000000071410046173213024360 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy from ComplexTypes import User import sys def main(): user = User('john_doe', 'John Doe', 25) nsdict = { 'types' : 'http://pycon.org/typs' } registration = ServiceProxy('../binding.wsdl', nsdict=nsdict, tracefile=sys.stdout) response = registration.RegisterUser(user) print response if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/server/receive_request/simple/0000755000175100017510000000000010712455110021066 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/simple/binding.wsdl0000644000175100017510000000247410046173766023420 0ustar zsizsi Example web service ZSI-2.1-a1/doc/examples/server/receive_request/simple/interface.wsdl0000644000175100017510000000140710046173766023741 0ustar zsizsi ZSI-2.1-a1/doc/examples/server/receive_request/simple/CGI/0000755000175100017510000000000010712455110021470 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/simple/CGI/cgi.py0000755000175100017510000000030710046173766022625 0ustar zsizsifrom Echo_services import EchoResponseWrapper def echo(message): response = EchoResponseWrapper() response._Message = message return response from ZSI import dispatch dispatch.AsCGI() ZSI-2.1-a1/doc/examples/server/receive_request/simple/CGI/README0000644000175100017510000000013510046173766022365 0ustar zsizsiTo run the CGI server, do the following: 1.) wsdl2py -f ../binding.wsdl 2.) Start apache ZSI-2.1-a1/doc/examples/server/receive_request/simple/mod_python/0000755000175100017510000000000010712455110023246 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/simple/mod_python/.cvsignore0000644000175100017510000000002210046173766025256 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/server/receive_request/simple/mod_python/README0000644000175100017510000000013510046173766024143 0ustar zsizsiTo run the CGI server, do the following: 1.) wsdl2py -f ../binding.wsdl 2.) Start apache ZSI-2.1-a1/doc/examples/server/receive_request/simple/mod_python/mod_python.py0000644000175100017510000000045310046173766026020 0ustar zsizsifrom ZSI import dispatch from mod_python import apache mod = __import__('encodings.utf_8', globals(), locals(), '*') mod = __import__('encodings.utf_16_be', globals(), locals(), '*') import MyHandler def handler(req): dispatch.AsHandler(modules=(MyHandler,), request=req) return apache.OK ZSI-2.1-a1/doc/examples/server/receive_request/simple/mod_python/MyHandler.py0000644000175100017510000000023610046173766025522 0ustar zsizsifrom Example_services import EchoResponseWrapper def echo(message): response = EchoResponseWrapper() response._Message = message return response ZSI-2.1-a1/doc/examples/server/receive_request/simple/client/0000755000175100017510000000000010712455110022344 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/simple/client/client.py0000755000175100017510000000051710046173766024220 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy import sys MESSAGE = "Hello from Python!" def main(): server = ServiceProxy('../binding.wsdl', use_wsdl=True) print ' Sending: %s' % MESSAGE response = server.echo(Message=MESSAGE) print 'Response: %s' % response['Message'] if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/server/receive_request/simple/standalone/0000755000175100017510000000000010712455110023216 5ustar zsizsiZSI-2.1-a1/doc/examples/server/receive_request/simple/standalone/.cvsignore0000644000175100017510000000002210046173766025226 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/server/receive_request/simple/standalone/README0000644000175100017510000000014710046173766024116 0ustar zsizsiTo run the standalone server, do the following: 1.) wsdl2py -f ../binding.wsdl 2.) ./standalone.py ZSI-2.1-a1/doc/examples/server/receive_request/simple/standalone/standalone.py0000755000175100017510000000041610046173766025742 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from Example_services import EchoResponseWrapper def echo(message): response = EchoResponseWrapper() response._Message = message return response if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/server/send_response/0000755000175100017510000000000010712455110017252 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/complex/0000755000175100017510000000000010712455110020721 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/complex/binding.wsdl0000644000175100017510000000245710046173766023254 0ustar zsizsi Registration web service ZSI-2.1-a1/doc/examples/server/send_response/complex/manual/0000755000175100017510000000000010712455110022176 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/complex/manual/ComplexTypes.py0000644000175100017510000000064310046173766025225 0ustar zsizsifrom ZSI import TC class User: def __init__(self, name=None, userId=None, age=-1): self.Name = name self.UserId = userId self.Age = age User.typecode = TC.Struct(User, [TC.String('Name', oname='Name'), TC.String('UserId', oname='UserId'), TC.Iinteger('Age', oname='Age')], 'User') ZSI-2.1-a1/doc/examples/server/send_response/complex/manual/.cvsignore0000644000175100017510000000000610046173766024210 0ustar zsizsi*.pyc ZSI-2.1-a1/doc/examples/server/send_response/complex/manual/server.py0000755000175100017510000000043710046173766024103 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from ComplexTypes import User def GetUser(user_id): user = User(user_id, 'John Doe', 28) return user if __name__ == '__main__': nsdict = { 'types' : 'http://pycon.org/types' } dispatch.AsServer(port=8080, nsdict=nsdict) ZSI-2.1-a1/doc/examples/server/send_response/complex/interface.wsdl0000644000175100017510000000155210046173766023575 0ustar zsizsi ZSI-2.1-a1/doc/examples/server/send_response/complex/types.xsd0000644000175100017510000000056710046173766022633 0ustar zsizsi ZSI-2.1-a1/doc/examples/server/send_response/complex/wsdl2py/0000755000175100017510000000000010712455110022325 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/complex/wsdl2py/.cvsignore0000644000175100017510000000002710046173766024342 0ustar zsizsiRegistration_services* ZSI-2.1-a1/doc/examples/server/send_response/complex/wsdl2py/server.py0000755000175100017510000000064710046173766024235 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from Registration_services import GetUserResponseWrapper from Registration_services_types import ns1 def GetUser(user_id): user = ns1.User_Def() user._UserId = user_id user._Name = "John Doe" user._Age = 32 response = GetUserResponseWrapper() response._User = user return response if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/server/send_response/complex/client/0000755000175100017510000000000010712455110022177 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/complex/client/.cvsignore0000644000175100017510000000002710046173766024214 0ustar zsizsiRegistration_services* ZSI-2.1-a1/doc/examples/server/send_response/complex/client/client.py0000755000175100017510000000074310046173766024054 0ustar zsizsi#!/usr/bin/env python import sys from Registration_services import * def main(): locator = RegistrationServiceLocator() service = locator.getRegistration(tracefile=sys.stdout) request = GetUserRequestWrapper() request._UserId = "john_doe" response = service.GetUser(request) print ' Age: %d' % response._User._Age print ' Name: %s' % response._User._Name print 'UserId: %s' % response._User._UserId if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/server/send_response/simple/0000755000175100017510000000000010712455110020543 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/simple/binding.wsdl0000644000175100017510000000247410046173766023075 0ustar zsizsi Example web service ZSI-2.1-a1/doc/examples/server/send_response/simple/interface.wsdl0000644000175100017510000000140710046173766023416 0ustar zsizsi ZSI-2.1-a1/doc/examples/server/send_response/simple/no_typecode/0000755000175100017510000000000010712455110023053 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/simple/no_typecode/client.py0000755000175100017510000000047510046173766024732 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy import sys MESSAGE = "Hello from Python!" def main(): server = ServiceProxy('../binding.wsdl', use_wsdl=False) print ' Sending: %s' % MESSAGE response = server.echo(MESSAGE) print 'Response: %s' % response if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/server/send_response/simple/no_typecode/server.py0000755000175100017510000000022610046173766024754 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch def echo(message): return message if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/server/send_response/simple/wsdl2py/0000755000175100017510000000000010712455110022147 5ustar zsizsiZSI-2.1-a1/doc/examples/server/send_response/simple/wsdl2py/.cvsignore0000644000175100017510000000002210046173766024157 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/server/send_response/simple/wsdl2py/README0000644000175100017510000000014310046173766023043 0ustar zsizsiTo run this example, do this: 1.) wsdl2py -f ../binding.wsdl 2.) ./server.py 3.) ./client.py ZSI-2.1-a1/doc/examples/server/send_response/simple/wsdl2py/client.py0000755000175100017510000000051710046173766024023 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy import sys MESSAGE = "Hello from Python!" def main(): server = ServiceProxy('../binding.wsdl', use_wsdl=True) print ' Sending: %s' % MESSAGE response = server.echo(Message=MESSAGE) print 'Response: %s' % response['Message'] if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/server/send_response/simple/wsdl2py/server.py0000755000175100017510000000041410046173766024047 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from Example_services import EchoResponseWrapper def echo(message): response = EchoResponseWrapper() response._Message = message return response if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/client/0000755000175100017510000000000010712455110014353 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/0000755000175100017510000000000010712455110017054 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/complex/0000755000175100017510000000000010712455110020523 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/complex/server/0000755000175100017510000000000010712455110022031 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/complex/server/ComplexTypes.py0000644000175100017510000000064210046172170025043 0ustar zsizsifrom ZSI import TC class User: def __init__(self, name=None, userId=None, age=-1): self.Name = name self.UserId = userId self.Age = age User.typecode = TC.Struct(User, [TC.String('Name', oname='Name'), TC.String('UserId', oname='UserId'), TC.Iinteger('Age', oname='Age')], 'User') ZSI-2.1-a1/doc/examples/client/send_request/complex/server/.cvsignore0000644000175100017510000000003510046172170024031 0ustar zsizsi*.pyc Registration_services* ZSI-2.1-a1/doc/examples/client/send_request/complex/server/server.py0000755000175100017510000000055310046172170023721 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch import ComplexTypes as MyComplexTypes from Registration_services import RegisterUserResponseWrapper def RegisterUser(user): response = RegisterUserResponseWrapper() response._Message = "OK" return response if __name__ == '__main__': dispatch.AsServer(port=8080, typesmodule=(MyComplexTypes,)) ZSI-2.1-a1/doc/examples/client/send_request/complex/binding.wsdl0000644000175100017510000000247110046172170023036 0ustar zsizsi Registration web service ZSI-2.1-a1/doc/examples/client/send_request/complex/manual/0000755000175100017510000000000010712455110022000 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/complex/manual/ComplexTypes.py0000644000175100017510000000065010046172170025011 0ustar zsizsifrom ZSI import TC class User: def __init__(self, name=None, userId=None, age=-1): self.Name = name self.UserId = userId self.Age = age User.typecode = TC.Struct(User, [TC.String('Name', oname='Name'), TC.String('UserId', oname='UserId'), TC.Iinteger('Age', oname='Age')], 'types:User') ZSI-2.1-a1/doc/examples/client/send_request/complex/manual/.cvsignore0000644000175100017510000000000610046172170023776 0ustar zsizsi*.pyc ZSI-2.1-a1/doc/examples/client/send_request/complex/manual/client.py0000755000175100017510000000072310046172170023637 0ustar zsizsi#!/usr/bin/env python from ComplexTypes import User from ZSI import ServiceProxy import sys def main(): user = User('john_doe', 'John Doe', 25) nsdict = { 'types' : 'http://pycon.org/types' } registration = ServiceProxy('../binding.wsdl', nsdict=nsdict, tracefile=sys.stdout) response = registration.RegisterUser(user) print response if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/send_request/complex/interface.wsdl0000644000175100017510000000160410046172170023361 0ustar zsizsi ZSI-2.1-a1/doc/examples/client/send_request/complex/types.xsd0000644000175100017510000000056710046172170022421 0ustar zsizsi ZSI-2.1-a1/doc/examples/client/send_request/complex/wsdl2py/0000755000175100017510000000000010712455110022127 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/complex/wsdl2py/.cvsignore0000644000175100017510000000002710046172170024130 0ustar zsizsiRegistration_services* ZSI-2.1-a1/doc/examples/client/send_request/complex/wsdl2py/client.py0000755000175100017510000000074210046172170023767 0ustar zsizsi#!/usr/bin/env python from Registration_services import * import sys def main(): user = ns1.User_Def() user._UserId = 'john_doe' user._Name = 'John Doe' user._Age = 25 locator = RegistrationServiceLocator() registration = locator.getRegistration(tracefile=sys.stdout) request = RegisterUserRequestWrapper() request._User = user response = registration.RegisterUser(request) print response._Message if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/send_request/simple/0000755000175100017510000000000010712455110020345 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/simple/server/0000755000175100017510000000000010712455110021653 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/simple/server/.cvsignore0000644000175100017510000000002210046172170023647 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/client/send_request/simple/server/server.py0000755000175100017510000000037710046172170023547 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from Example_services import * def echo(message): response = EchoResponseWrapper() response._Message = message return response if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/client/send_request/simple/ServiceProxy/0000755000175100017510000000000010712455110023007 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/simple/ServiceProxy/client.py0000755000175100017510000000050410046172170024643 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy MESSAGE = "Hello from Python!" def main(): server = ServiceProxy('../binding.wsdl', use_wsdl=True) print ' Sending: %s' % MESSAGE response = server.echo(Message=MESSAGE) print 'Response: %s' % response['Message'] if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/send_request/simple/README0000644000175100017510000000034010046172170021224 0ustar zsizsiTo run these examples, first get the server running. To do that, go into the server directory and follow the instructions in the README. Then go into each of the different client directories and review their instructions. ZSI-2.1-a1/doc/examples/client/send_request/simple/binding.wsdl0000644000175100017510000000247410046172170022663 0ustar zsizsi Example web service ZSI-2.1-a1/doc/examples/client/send_request/simple/interface.wsdl0000644000175100017510000000140710046172170023204 0ustar zsizsi ZSI-2.1-a1/doc/examples/client/send_request/simple/wsdl2py/0000755000175100017510000000000010712455110021751 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/simple/wsdl2py/.cvsignore0000644000175100017510000000002210046172170023745 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/client/send_request/simple/wsdl2py/README0000644000175100017510000000014110046172170022627 0ustar zsizsiTo walk through how this example works: 1.) wsdl2py -f ../binding.wsdl 2.) Examine client.py ZSI-2.1-a1/doc/examples/client/send_request/simple/wsdl2py/client.py0000755000175100017510000000074410046172170023613 0ustar zsizsi#!/usr/bin/env python import Example_services MESSAGE = "Hello from Python!" def main(): locator = Example_services.ExampleServiceLocator() port = locator.getExample() request = Example_services.EchoRequestWrapper() request._Message = MESSAGE try: print ' Sending: %s' % MESSAGE response = port.echo(request) print 'Response: %s' % response._Message except Exception, e: print e if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/send_request/simple/Binding/0000755000175100017510000000000010712455110021717 5ustar zsizsiZSI-2.1-a1/doc/examples/client/send_request/simple/Binding/client.py0000755000175100017510000000045510046172170023560 0ustar zsizsi#!/usr/bin/env python from ZSI import Binding MESSAGE = "Hello from Python!" def main(): binding = Binding(url='http://localhost:8080/server.py') print ' Sending: %s' % MESSAGE response = binding.echo(MESSAGE) print 'Response: %s' % MESSAGE if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/receive_response/0000755000175100017510000000000010712455110017713 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/complex/0000755000175100017510000000000010712455110021362 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/complex/server/0000755000175100017510000000000010712455110022670 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/complex/server/.cvsignore0000644000175100017510000000002710046172170024671 0ustar zsizsiRegistration_services* ZSI-2.1-a1/doc/examples/client/receive_response/complex/server/server.py0000755000175100017510000000064710046172170024564 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from Registration_services import GetUserResponseWrapper from Registration_services_types import ns1 def GetUser(user_id): user = ns1.User_Def() user._UserId = user_id user._Name = "John Doe" user._Age = 32 response = GetUserResponseWrapper() response._User = user return response if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/client/receive_response/complex/binding.wsdl0000644000175100017510000000245710046170307023701 0ustar zsizsi Registration web service ZSI-2.1-a1/doc/examples/client/receive_response/complex/manual/0000755000175100017510000000000010712455110022637 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/complex/manual/ComplexTypes.py0000644000175100017510000000064210046172170025651 0ustar zsizsifrom ZSI import TC class User: def __init__(self, name=None, userId=None, age=-1): self.Name = name self.UserId = userId self.Age = age User.typecode = TC.Struct(User, [TC.String('Name', oname='Name'), TC.String('UserId', oname='UserId'), TC.Iinteger('Age', oname='Age')], 'User') ZSI-2.1-a1/doc/examples/client/receive_response/complex/manual/.cvsignore0000644000175100017510000000000610046172170024635 0ustar zsizsi*.pyc ZSI-2.1-a1/doc/examples/client/receive_response/complex/manual/client.py0000755000175100017510000000071310046172170024475 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy import ComplexTypes as MyComplexTypes import sys def main(): server = ServiceProxy('../binding.wsdl', typesmodule=MyComplexTypes, tracefile=sys.stdout) user = server.GetUser('john_doe') print ' Age: %d' % user.Age print ' Name: %s' % user.Name print 'UserId: %s' % user.UserId if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/receive_response/complex/interface.wsdl0000644000175100017510000000155210046170307024222 0ustar zsizsi ZSI-2.1-a1/doc/examples/client/receive_response/complex/types.xsd0000644000175100017510000000056710046170307023260 0ustar zsizsi ZSI-2.1-a1/doc/examples/client/receive_response/complex/wsdl2py/0000755000175100017510000000000010712455110022766 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/complex/wsdl2py/.cvsignore0000644000175100017510000000002710046172170024767 0ustar zsizsiRegistration_services* ZSI-2.1-a1/doc/examples/client/receive_response/complex/wsdl2py/client.py0000755000175100017510000000074310046172170024627 0ustar zsizsi#!/usr/bin/env python import sys from Registration_services import * def main(): locator = RegistrationServiceLocator() service = locator.getRegistration(tracefile=sys.stdout) request = GetUserRequestWrapper() request._UserId = "john_doe" response = service.GetUser(request) print ' Age: %d' % response._User._Age print ' Name: %s' % response._User._Name print 'UserId: %s' % response._User._UserId if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/receive_response/simple/0000755000175100017510000000000010712455110021204 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/simple/server/0000755000175100017510000000000010712455110022512 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/simple/server/.cvsignore0000644000175100017510000000002210046172170024506 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/client/receive_response/simple/server/server.py0000755000175100017510000000041610046172170024400 0ustar zsizsi#!/usr/bin/env python from ZSI import dispatch from Example_services import EchoResponseWrapper def echo(message): response = EchoResponseWrapper() response._Message = message return response if __name__ == '__main__': dispatch.AsServer(port=8080) ZSI-2.1-a1/doc/examples/client/receive_response/simple/ServiceProxy/0000755000175100017510000000000010712455110023646 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/simple/ServiceProxy/client.py0000755000175100017510000000050410046172170025502 0ustar zsizsi#!/usr/bin/env python from ZSI import ServiceProxy MESSAGE = "Hello from Python!" def main(): server = ServiceProxy('../binding.wsdl', use_wsdl=True) print ' Sending: %s' % MESSAGE response = server.echo(Message=MESSAGE) print 'Response: %s' % response['Message'] if __name__ == '__main__': main() ZSI-2.1-a1/doc/examples/client/receive_response/simple/binding.wsdl0000644000175100017510000000247410046172170023522 0ustar zsizsi Example web service ZSI-2.1-a1/doc/examples/client/receive_response/simple/interface.wsdl0000644000175100017510000000140710046172170024043 0ustar zsizsi ZSI-2.1-a1/doc/examples/client/receive_response/simple/wsdl2py/0000755000175100017510000000000010712455110022610 5ustar zsizsiZSI-2.1-a1/doc/examples/client/receive_response/simple/wsdl2py/.cvsignore0000644000175100017510000000002210046172170024604 0ustar zsizsiExample_services* ZSI-2.1-a1/doc/examples/client/receive_response/simple/wsdl2py/README0000644000175100017510000000014110046172170023466 0ustar zsizsiTo walk through how this example works: 1.) wsdl2py -f ../binding.wsdl 2.) Examine client.py ZSI-2.1-a1/doc/examples/client/receive_response/simple/wsdl2py/client.py0000755000175100017510000000074410046172170024452 0ustar zsizsi#!/usr/bin/env python import Example_services MESSAGE = "Hello from Python!" def main(): locator = Example_services.ExampleServiceLocator() port = locator.getExample() request = Example_services.EchoRequestWrapper() request._Message = MESSAGE try: print ' Sending: %s' % MESSAGE response = port.echo(request) print 'Response: %s' % response._Message except Exception, e: print e if __name__ == '__main__': main() ZSI-2.1-a1/doc/guide.css0000644000175100017510000002306310712455110013072 0ustar zsizsi/* * The first part of this is the standard CSS generated by LaTeX2HTML, * with the "empty" declarations removed. */ /* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ .math { font-family: "Century Schoolbook", serif; } .math i { font-family: "Century Schoolbook", serif; font-weight: bold } .boldmath { font-family: "Century Schoolbook", serif; font-weight: bold } /* * Implement both fixed-size and relative sizes. * * I think these can be safely removed, as it doesn't appear that * LaTeX2HTML ever generates these, even though these are carried * over from the LaTeX2HTML stylesheet. */ small.xtiny { font-size : xx-small; } small.tiny { font-size : x-small; } small.scriptsize { font-size : smaller; } small.footnotesize { font-size : small; } big.xlarge { font-size : large; } big.xxlarge { font-size : x-large; } big.huge { font-size : larger; } big.xhuge { font-size : xx-large; } /* * Document-specific styles come next; * these are added for the Python documentation. * * Note that the size specifications for the H* elements are because * Netscape on Solaris otherwise doesn't get it right; they all end up * the normal text size. */ body { color: #000000; background-color: #ffffff; } a:link:active { color: #ff0000; } a:link:hover { background-color: #bbeeff; } a:visited:hover { background-color: #bbeeff; } a:visited { color: #551a8b; } a:link { color: #0000bb; } h1, h2, h3, h4, h5, h6 { font-family: avantgarde, sans-serif; font-weight: bold; } h1 { font-size: 180%; } h2 { font-size: 150%; } h3, h4 { font-size: 120%; } /* These are section titles used in navigation links, so make sure we * match the section header font here, even it not the weight. */ .sectref { font-family: avantgarde, sans-serif; } /* And the label before the titles in navigation: */ .navlabel { font-size: 85%; } /* LaTeX2HTML insists on inserting
elements into headers which * are marked with \label. This little bit of CSS magic ensures that * these elements don't cause spurious whitespace to be added. */ h1>br, h2>br, h3>br, h4>br, h5>br, h6>br { display: none; } code, tt { font-family: "lucida typewriter", lucidatypewriter, monospace; } var { font-family: times, serif; font-style: italic; font-weight: normal; } .Unix { font-variant: small-caps; } .typelabel { font-family: lucida, sans-serif; } .navigation td { background-color: #99ccff; font-weight: bold; font-family: avantgarde, sans-serif; font-size: 110%; } div.warning { background-color: #fffaf0; border: thin solid black; padding: 1em; margin-left: 2em; margin-right: 2em; } div.warning .label { font-family: sans-serif; font-size: 110%; margin-right: 0.5em; } div.note { background-color: #fffaf0; border: thin solid black; padding: 1em; margin-left: 2em; margin-right: 2em; } div.note .label { margin-right: 0.5em; font-family: sans-serif; } address { font-size: 80%; } .release-info { font-style: italic; font-size: 80%; } .titlegraphic { vertical-align: top; } .verbatim pre { color: #00008b; font-family: "lucida typewriter", lucidatypewriter, monospace; font-size: 90%; } .verbatim { margin-left: 2em; } .verbatim .footer { padding: 0.05in; font-size: 85%; background-color: #99ccff; margin-right: 0.5in; } .grammar { background-color: #99ccff; margin-right: 0.5in; padding: 0.05in; } .grammar-footer { padding: 0.05in; font-size: 85%; } .grammartoken { font-family: "lucida typewriter", lucidatypewriter, monospace; } .productions { background-color: #bbeeff; } .productions a:active { color: #ff0000; } .productions a:link:hover { background-color: #99ccff; } .productions a:visited:hover { background-color: #99ccff; } .productions a:visited { color: #551a8b; } .productions a:link { color: #0000bb; } .productions table { vertical-align: baseline; empty-cells: show; } .productions > table td, .productions > table th { padding: 2px; } .productions > table td:first-child, .productions > table td:last-child { font-family: "lucida typewriter", lucidatypewriter, monospace; } /* same as the second selector above, but expressed differently for Opera */ .productions > table td:first-child + td + td { font-family: "lucida typewriter", lucidatypewriter, monospace; vertical-align: baseline; } .productions > table td:first-child + td { padding-left: 1em; padding-right: 1em; } .productions > table tr { vertical-align: baseline; } .email { font-family: avantgarde, sans-serif; } .mailheader { font-family: avantgarde, sans-serif; } .mimetype { font-family: avantgarde, sans-serif; } .newsgroup { font-family: avantgarde, sans-serif; } .url { font-family: avantgarde, sans-serif; } .file { font-family: avantgarde, sans-serif; } .guilabel { font-family: avantgarde, sans-serif; } .realtable { border-collapse: collapse; border-color: black; border-style: solid; border-width: 0px 0px 2px 0px; empty-cells: show; margin-left: auto; margin-right: auto; padding-left: 0.4em; padding-right: 0.4em; } .realtable tbody { vertical-align: baseline; } .realtable tfoot { display: table-footer-group; } .realtable thead { background-color: #99ccff; border-width: 0px 0px 2px 1px; display: table-header-group; font-family: avantgarde, sans-serif; font-weight: bold; vertical-align: baseline; } .realtable thead :first-child { border-width: 0px 0px 2px 0px; } .realtable thead th { border-width: 0px 0px 2px 1px } .realtable td, .realtable th { border-color: black; border-style: solid; border-width: 0px 0px 1px 1px; padding-left: 0.4em; padding-right: 0.4em; } .realtable td:first-child, .realtable th:first-child { border-left-width: 0px; vertical-align: baseline; } .center { text-align: center; } .left { text-align: left; } .right { text-align: right; } .refcount-info { font-style: italic; } .refcount-info .value { font-weight: bold; color: #006600; } /* * Some decoration for the "See also:" blocks, in part inspired by some of * the styling on Lars Marius Garshol's XSA pages. * (The blue in the navigation bars is #99CCFF.) */ .seealso { background-color: #fffaf0; border: thin solid black; padding: 0pt 1em 4pt 1em; } .seealso > .heading { font-size: 110%; font-weight: bold; } /* * Class 'availability' is used for module availability statements at * the top of modules. */ .availability .platform { font-weight: bold; } /* * Additional styles for the distutils package. */ .du-command { font-family: monospace; } .du-option { font-family: avantgarde, sans-serif; } .du-filevar { font-family: avantgarde, sans-serif; font-style: italic; } .du-xxx:before { content: "** "; font-weight: bold; } .du-xxx:after { content: " **"; font-weight: bold; } /* * Some specialization for printed output. */ @media print { .online-navigation { display: none; } } ZSI-2.1-a1/doc/guide.ps0000644000175100017510000020432710712455101012730 0ustar zsizsi%!PS-Adobe-2.0 %%Creator: dvips(k) 5.95a Copyright 2005 Radical Eye Software %%Title: guide.dvi %%Pages: 28 %%PageOrder: Ascend %%BoundingBox: 0 0 612 792 %%DocumentFonts: Helvetica Helvetica-Oblique Times-Roman Times-Bold %%+ CMSY10 Times-Italic Helvetica-Bold Courier Courier-Oblique %%+ Times-BoldItalic %%DocumentPaperSizes: Letter %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -N0 -t letter -o guide.ps guide.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2007.11.01:2259 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: 8r.enc 0 0 % File 8r.enc TeX Base 1 Encoding Revision 2.0 2002-10-30 % % @@psencodingfile@{ % author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry, % W. Schmidt, P. Lehman", % version = "2.0", % date = "30 October 2002", % filename = "8r.enc", % email = "tex-fonts@@tug.org", % docstring = "This is the encoding vector for Type1 and TrueType % fonts to be used with TeX. This file is part of the % PSNFSS bundle, version 9" % @} % % The idea is to have all the characters normally included in Type 1 fonts % available for typesetting. This is effectively the characters in Adobe % Standard encoding, ISO Latin 1, Windows ANSI including the euro symbol, % MacRoman, and some extra characters from Lucida. % % Character code assignments were made as follows: % % (1) the Windows ANSI characters are almost all in their Windows ANSI % positions, because some Windows users cannot easily reencode the % fonts, and it makes no difference on other systems. The only Windows % ANSI characters not available are those that make no sense for % typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen % (173). quotesingle and grave are moved just because it's such an % irritation not having them in TeX positions. % % (2) Remaining characters are assigned arbitrarily to the lower part % of the range, avoiding 0, 10 and 13 in case we meet dumb software. % % (3) Y&Y Lucida Bright includes some extra text characters; in the % hopes that other PostScript fonts, perhaps created for public % consumption, will include them, they are included starting at 0x12. % These are /dotlessj /ff /ffi /ffl. % % (4) hyphen appears twice for compatibility with both ASCII and Windows. % % (5) /Euro was assigned to 128, as in Windows ANSI % % (6) Missing characters from MacRoman encoding incorporated as follows: % % PostScript MacRoman TeXBase1 % -------------- -------------- -------------- % /notequal 173 0x16 % /infinity 176 0x17 % /lessequal 178 0x18 % /greaterequal 179 0x19 % /partialdiff 182 0x1A % /summation 183 0x1B % /product 184 0x1C % /pi 185 0x1D % /integral 186 0x81 % /Omega 189 0x8D % /radical 195 0x8E % /approxequal 197 0x8F % /Delta 198 0x9D % /lozenge 215 0x9E % /TeXBase1Encoding [ % 0x00 /.notdef /dotaccent /fi /fl /fraction /hungarumlaut /Lslash /lslash /ogonek /ring /.notdef /breve /minus /.notdef /Zcaron /zcaron % 0x10 /caron /dotlessi /dotlessj /ff /ffi /ffl /notequal /infinity /lessequal /greaterequal /partialdiff /summation /product /pi /grave /quotesingle % 0x20 /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash % 0x30 /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question % 0x40 /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O % 0x50 /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore % 0x60 /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o % 0x70 /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef % 0x80 /Euro /integral /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl /circumflex /perthousand /Scaron /guilsinglleft /OE /Omega /radical /approxequal % 0x90 /.notdef /.notdef /.notdef /quotedblleft /quotedblright /bullet /endash /emdash /tilde /trademark /scaron /guilsinglright /oe /Delta /lozenge /Ydieresis % 0xA0 /.notdef /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron % 0xD0 /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown % 0xC0 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis % 0xD0 /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls % 0xE0 /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis % 0xF0 /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] def %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMSY10 %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 13 /circlecopyrt put readonly def /FontBBox{-29 -960 1116 775}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A 27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF 5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A 71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C 515DB70A8D4F6146FE068DC1E5DE8BC5703711DA090312BA3FC00A08C453C609 C627A8BFEF75B4DEFAF34B44B356A516B765AFCDD3F5475B1F928731D09D2170 B97E40F12CCEDF4F6BB3756C4734F6E98D74B7E942A954B1BAAB83D4AD727FF6 DF6DC50B2223BCB5568A73A112E4860AD490554E64E780073FF3399CB4688D33 9E8829667CD6EAEF25E0C7D2D44F2BBFA40E999325F9561514844221B50BC8FC 4C7AD68CA7220D69125C2AF06849A3E068D18733276F0C0A6A2936D3C2C87CDE 59CD1AF148C44F85784A5DAD569F5FF53C061056C067CE29AEF1E3BD1FD8B0B8 71A0A638CDAC6AEEDBD5337D4683C084BB60B1859E600F59CB4E19C5FC5C6327 EC544A68134496A9BD0B87D83AF6FDA3CB62FBF0B54FACE1F0E6A2D84B467AFF 0F62DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont TeXDict begin 40258431 52099146 1000 600 600 (guide.dvi) @start /Fa 138[46 23 32 1[42 42 3[23 5[28 37 1[37 16[55 9[65 3[60 22[28 45[{TeXBase1Encoding ReEncodeFont}13 83.022 /Times-BoldItalic rf /Fb 130[45 45 1[45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 1[45 1[45 45 45 45 45 45 45 2[45 45 45 45 45 45 45 45 45 2[45 45 45 45 45 45 45 45 45 2[45 45 45 1[45 1[45 45 45 45 45 45 45 45 45 45 45 45 45 1[45 45 45 45 3[45 45 34[{TeXBase1Encoding ReEncodeFont}77 74.7198 /Courier rf /Fc 107[37 28[44 1[33 18 26 26 1[33 33 33 48 3[18 33 33 1[29 33 29 33 33 8[41 4[33 4[44 55 37 17[22 6[33 33 33 33 18 17 4[22 22 40[{TeXBase1Encoding ReEncodeFont} 32 66.4176 /Times-Italic rf /Fd 134[33 33 48 1[33 18 26 22 1[33 33 33 52 18 33 1[18 33 1[22 29 33 29 1[29 11[48 41 14[41 1[44 22[17 41[37 2[{TeXBase1Encoding ReEncodeFont}26 66.4176 /Times-Roman rf /Fe 205[25 25 49[{TeXBase1Encoding ReEncodeFont} 2 49.8132 /Times-Roman rf /Ff 134[50 1[50 50 50 50 50 50 50 50 50 50 50 50 50 1[50 50 1[50 50 50 50 50 50 1[50 4[50 5[50 50 50 8[50 50 50 1[50 50 50 8[50 1[50 2[50 2[50 50 50 50 50 50 45[{TeXBase1Encoding ReEncodeFont}42 83.022 /Courier-Oblique rf /Fg 133[50 50 50 1[50 55 28 50 33 1[55 55 55 83 22 2[22 55 55 28 55 55 50 55 55 11[72 61 66 5[83 5[78 61 66 72 72 66 66 6[28 5[55 55 55 55 2[28 4[33 33 40[{TeXBase1Encoding ReEncodeFont}41 99.6264 /Helvetica rf /Fh 205[29 29 49[{TeXBase1Encoding ReEncodeFont}2 58.1154 /Times-Roman rf /Fi 133[60 60 1[86 60 66 33 60 40 1[66 66 66 100 27 2[27 66 66 33 66 66 60 1[66 8[80 113 2[73 80 86 1[80 93 86 100 66 3[86 93 73 1[86 86 80 80 12[66 66 66 66 2[33 46[{TeXBase1Encoding ReEncodeFont}43 119.552 /Helvetica rf /Fj 131[50 2[50 50 50 2[50 50 50 1[50 50 50 50 50 2[50 50 50 1[50 1[50 1[50 1[50 4[50 1[50 3[50 50 2[50 50 50 50 50 2[50 3[50 3[50 2[50 50 2[50 6[50 50 50 50 50 50 50 50 2[50 50 40[{ TeXBase1Encoding ReEncodeFont}44 83.022 /Courier rf /Fk 168[113 80 86 73 1[86 2[93 86 4[33 86 1[73 80 2[86 86 65[{TeXBase1Encoding ReEncodeFont}13 119.552 /Helvetica-Bold rf /Fl 64[42 29[32 10[42 1[46 46 24[32 37 37 55 37 42 23 32 32 42 42 42 42 60 23 37 23 23 42 42 23 37 42 37 42 42 6[46 46 51 69 1[60 46 42 51 1[51 60 55 69 46 55 37 28 60 60 51 51 60 55 51 51 1[42 1[56 2[28 4[42 42 42 42 42 42 23 21 28 21 1[42 28 28 28 35[42 42 2[{ TeXBase1Encoding ReEncodeFont}74 83.022 /Times-Italic rf /Fm 134[42 42 60 42 46 23 42 28 46 46 46 46 69 18 42 1[18 46 46 23 46 46 42 46 46 8[55 78 2[51 55 60 1[55 1[60 69 46 2[23 60 65 1[55 60 60 55 55 6[23 46 46 46 46 46 46 46 46 46 46 1[23 43[42 2[{TeXBase1Encoding ReEncodeFont}54 83.022 /Helvetica rf /Fn 242[83 13[{}1 83.022 /CMSY10 rf /Fo 107[37 25[37 42 42 60 42 42 23 32 28 42 42 42 42 65 23 42 23 23 42 42 28 37 42 37 42 37 6[51 60 60 78 60 60 51 46 55 60 46 60 60 74 51 60 1[28 60 60 46 51 60 55 55 60 5[23 23 42 42 2[42 42 42 42 42 42 23 21 28 21 2[28 28 28 36[46 2[{TeXBase1Encoding ReEncodeFont}70 83.022 /Times-Roman rf /Fp 104[83 28[37 42 42 60 1[46 28 32 37 1[46 42 46 69 23 2[23 46 42 28 37 46 37 46 42 7[60 60 83 1[60 55 46 60 1[51 65 60 78 55 2[32 65 65 51 55 60 60 55 60 3[47 2[28 42 1[42 1[42 42 42 42 42 1[23 1[28 21 2[28 28 37[46 2[{TeXBase1Encoding ReEncodeFont}59 83.022 /Times-Bold rf /Fq 137[37 3[25 2[42 2[17 1[17 1[42 42 21 42 2[42 33[76 17[21 46[{TeXBase1Encoding ReEncodeFont}12 74.7198 /Helvetica rf /Fr 137[50 3[33 2[50 1[78 7[44 2[50 19[72 22[50 4[50 50 50 3[25 44[{TeXBase1Encoding ReEncodeFont}12 99.6264 /Times-Roman rf /Fs 137[72 80 1[72 48 2[80 2[32 3[80 1[40 80 80 2[80 19[120 2[72 6[104 96 21[40 44[{ TeXBase1Encoding ReEncodeFont}16 143.462 /Helvetica rf /Ft 140[72 6[32 6[80 3[80 14[104 31[80 80 80 1[40 46[{ TeXBase1Encoding ReEncodeFont}9 143.462 /Helvetica-Oblique rf /Fu 134[103 103 149 1[115 57 103 69 1[115 115 115 172 46 2[46 115 1[57 115 115 103 115 115 6[126 2[195 1[149 126 138 2[138 161 149 4[57 149 161 1[138 1[149 1[138 6[57 7[115 10[46 39[{TeXBase1Encoding ReEncodeFont}37 206.559 /Helvetica rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: Letter letter %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 0 83 3901 9 v 652 446 a Fu(ZSI:)58 b(The)g(Zoler)n(a)e(Soap)h(Infr)n(astr)s(ucture)2717 695 y(User')-10 b(s)57 b(Guide)3015 925 y Ft(Release)38 b(2.1.0)2794 2068 y Fs(Joshua)g(Bo)n(v)l(erhof)l(,)3005 2250 y(Char)r(les)g(Moad)3109 4240 y Fr(No)o(v)o(ember)23 b(01,)i(2007)3282 5317 y Fq(jrbo)o(v)n(erhof@lb)o(l.go)o(v)p eop end %%Page: 1 2 TeXDict begin 1 1 bop 1694 83 a Fp(COPYRIGHT)0 230 y Fo(Cop)o(yright)380 227 y(c)357 230 y Fn(\015)20 b Fo(2001,)f(Zolera)g (Systems,)i(Inc.)0 330 y(All)g(Rights)f(Reserv)o(ed.)0 476 y(Cop)o(yright)380 473 y(c)357 476 y Fn(\015)g Fo(2002-2003,)d (Rich)j(Salz.)0 576 y(All)h(Rights)f(Reserv)o(ed.)0 723 y(Permission)27 b(is)h(hereby)d(granted,)i(free)g(of)g(char)o(ge,)g(to) g(an)o(y)f(person)g(obtaining)g(a)h(cop)o(y)f(of)h(this)h(softw)o(are)f (and)f(associated)h(docu-)0 823 y(mentation)20 b(\002les)j(\(the)e (\224Softw)o(are\224\),)g(to)g(deal)h(in)f(the)h(Softw)o(are)f(without) g(restriction,)g(including)f(without)g(limitation)i(the)f(rights)g(to)0 922 y(use,)k(cop)o(y)-5 b(,)24 b(modify)-5 b(,)23 b(mer)o(ge,)h (publish,)g(distrib)n(ute,)h(and/or)d(sell)k(copies)e(of)g(the)g(Softw) o(are,)g(and)g(to)h(permit)e(persons)h(to)g(whom)g(the)0 1022 y(Softw)o(are)i(is)i(furnished)c(to)j(do)f(so,)j(pro)o(vided)24 b(that)i(the)h(abo)o(v)o(e)e(cop)o(yright)f(notice\(s\))i(and)g(this)h (permission)f(notice)g(appear)f(in)i(all)0 1121 y(copies)g(of)g(the)g (Softw)o(are)g(and)g(that)g(both)f(the)i(abo)o(v)o(e)d(cop)o(yright)h (notice\(s\))g(and)h(this)g(permission)g(notice)f(appear)g(in)i (supporting)0 1221 y(documentation.)0 1368 y(THE)e(SOFTW)-10 b(ARE)26 b(IS)g(PR)m(O)l(VIDED)g(\224AS)g(IS\224,)h(WITHOUT)e(W)-10 b(ARRANTY)27 b(OF)f(ANY)g(KIND,)g(EXPRESS)g(OR)h(IMPLIED,)0 1468 y(INCLUDING)f(B)o(UT)h(NO)m(T)g(LIMITED)e(T)o(O)h(THE)g(W)-10 b(ARRANTIES)27 b(OF)h(MERCHANT)-8 b(ABILITY)d(,)26 b(FITNESS)g(FOR)i(A) f(P)-8 b(AR-)0 1567 y(TICULAR)29 b(PURPOSE)g(AND)f(NONINFRINGEMENT)g (OF)g(THIRD)h(P)-8 b(AR)j(TY)29 b(RIGHTS.)f(IN)h(NO)f(EVENT)g(SHALL)h (THE)0 1667 y(COPYRIGHT)19 b(HOLDER)g(OR)g(HOLDERS)g(INCLUDED)f(IN)h (THIS)g(NO)m(TICE)f(BE)h(LIABLE)f(FOR)i(ANY)e(CLAIM,)h(OR)g(ANY)0 1766 y(SPECIAL)25 b(INDIRECT)g(OR)h(CONSEQ)o(UENTIAL)f(D)m(AMA)m(GES,)f (OR)i(ANY)f(D)m(AMA)m(GES)f(WHA)-9 b(TSOEVER)25 b(RESUL)-8 b(TING)0 1866 y(FR)m(OM)27 b(LOSS)g(OF)g(USE,)f(D)m(A)-9 b(T)h(A)27 b(OR)g(PR)m(OFITS,)f(WHETHER)h(IN)f(AN)h(A)m(CTION)f(OF)h (CONTRA)m(CT)-6 b(,)27 b(NEGLIGENCE)f(OR)0 1966 y(O)m(THER)20 b(T)o(OR)-5 b(TIOUS)20 b(A)m(CTION,)g(ARISING)h(OUT)f(OF)h(OR)h(IN)e (CONNECTION)h(WITH)f(THE)g(USE)h(OR)g(PERFORMANCE)0 2065 y(OF)g(THIS)f(SOFTW)-10 b(ARE.)0 2212 y(Except)27 b(as)i(contained)d (in)i(this)g(notice,)h(the)f(name)f(of)h(a)g(cop)o(yright)e(holder)g (shall)j(not)e(be)h(used)g(in)g(adv)o(ertising)e(or)h(otherwise)g(to)0 2312 y(promote)18 b(the)j(sale,)f(use)h(or)f(other)f(dealings)g(in)i (this)g(Softw)o(are)e(without)h(prior)f(written)h(authorization)e(of)h (the)i(cop)o(yright)d(holder)-5 b(.)0 2459 y(Cop)o(yright)381 2456 y(c)358 2459 y Fn(\015)21 b Fo(\(c\))g(2003,)f(The)h(Re)o(gents)g (of)f(the)i(Uni)n(v)o(ersity)d(of)i(California,)g(through)e(La)o (wrence)g(Berk)o(ele)o(y)i(National)f(Laboratory)0 2558 y(\(subject)i(to)h(receipt)f(of)g(an)o(y)g(required)f(appro)o(v)n(als)g (from)h(the)g(U.S.)h(Dept.)32 b(of)23 b(Ener)o(gy\).)30 b(All)23 b(rights)f(reserv)o(ed.)31 b(Redistrib)n(ution)22 b(and)0 2658 y(use)e(in)g(source)e(and)h(binary)g(forms,)f(with)i(or)g (without)e(modi\002cation,)g(are)i(permitted)e(pro)o(vided)f(that)j (the)g(follo)n(wing)e(conditions)g(are)0 2758 y(met:)0 2904 y(\(1\))27 b(Redistrib)n(utions)h(of)f(source)h(code)f(must)h (retain)g(the)g(abo)o(v)o(e)e(cop)o(yright)g(notice,)j(this)f(list)i (of)d(conditions)g(and)g(the)h(follo)n(wing)0 3004 y(disclaimer)-5 b(.)37 b(\(2\))23 b(Redistrib)n(utions)h(in)g(binary)f(form)g(must)h (reproduce)e(the)i(abo)o(v)o(e)e(cop)o(yright)g(notice,)j(this)f(list)i (of)d(conditions)g(and)0 3104 y(the)i(follo)n(wing)e(disclaimer)h(in)h (the)g(documentation)c(and/or)j(other)g(materials)g(pro)o(vided)e(with) j(the)g(distrib)n(ution.)37 b(\(3\))24 b(Neither)h(the)0 3203 y(name)19 b(of)h(the)f(Uni)n(v)o(ersity)g(of)h(California,)e(La)o (wrence)h(Berk)o(ele)o(y)g(National)g(Laboratory)-5 b(,)17 b(U.S.)j(Dept.)k(of)c(Ener)o(gy)e(nor)h(the)g(names)h(of)0 3303 y(its)j(contrib)n(utors)c(may)j(be)f(used)h(to)g(endorse)e(or)h (promote)f(products)g(deri)n(v)o(ed)g(from)h(this)h(softw)o(are)f (without)g(speci\002c)h(prior)f(written)0 3403 y(permission.)0 3549 y(THIS)34 b(SOFTW)-10 b(ARE)34 b(IS)g(PR)m(O)l(VIDED)g(BY)g(THE)g (COPYRIGHT)g(HOLDERS)g(AND)g(CONTRIB)o(UT)o(ORS)g(\224AS)g(IS\224)g (AND)0 3649 y(ANY)c(EXPRESS)h(OR)f(IMPLIED)f(W)-10 b(ARRANTIES,)30 b(INCLUDING,)f(B)o(UT)i(NO)m(T)e(LIMITED)g(T)o(O,)g(THE)h(IMPLIED)f(W) -10 b(AR-)0 3749 y(RANTIES)24 b(OF)g(MERCHANT)-8 b(ABILITY)23 b(AND)h(FITNESS)g(FOR)g(A)g(P)-8 b(AR)j(TICULAR)25 b(PURPOSE)f(ARE)h (DISCLAIMED.)d(IN)0 3848 y(NO)g(EVENT)g(SHALL)g(THE)g(COPYRIGHT)h(O)m (WNER)g(OR)g(CONTRIB)o(UT)o(ORS)f(BE)h(LIABLE)f(FOR)h(ANY)f(DIRECT)-6 b(,)22 b(INDI-)0 3948 y(RECT)-6 b(,)26 b(INCIDENT)-8 b(AL,)25 b(SPECIAL,)h(EXEMPLAR)-5 b(Y)-11 b(,)25 b(OR)h(CONSEQ)o (UENTIAL)g(D)m(AMA)m(GES)f(\(INCLUDING,)f(B)o(UT)j(NO)m(T)0 4048 y(LIMITED)15 b(T)o(O,)g(PR)m(OCUREMENT)i(OF)f(SUBSTITUTE)g(GOODS)g (OR)h(SER)-7 b(VICES;)17 b(LOSS)g(OF)f(USE,)h(D)m(A)-9 b(T)h(A,)15 b(OR)i(PR)m(OFITS;)0 4147 y(OR)26 b(B)o(USINESS)g(INTERR)m (UPTION\))e(HO)m(WEVER)i(CA)-5 b(USED)26 b(AND)f(ON)h(ANY)f(THEOR)-5 b(Y)25 b(OF)h(LIABILITY)-11 b(,)24 b(WHETHER)0 4247 y(IN)g(CONTRA)m(CT) -6 b(,)24 b(STRICT)g(LIABILITY)-11 b(,)23 b(OR)i(T)o(OR)-5 b(T)24 b(\(INCLUDING)f(NEGLIGENCE)g(OR)i(O)m(THER)-5 b(WISE\))23 b(ARISING)h(IN)0 4346 y(ANY)k(W)-10 b(A)h(Y)28 b(OUT)g(OF)g(THE)f(USE)h(OF)g(THIS)g(SOFTW)-10 b(ARE,)28 b(EVEN)f(IF)h(AD)m(VISED)f(OF)h(THE)f(POSSIBILITY)h(OF)g(SUCH)0 4446 y(D)m(AMA)m(GE.)0 4593 y(Y)-9 b(ou)24 b(are)h(under)e(no)i (obligation)d(whatsoe)n(v)o(er)h(to)i(pro)o(vide)e(an)o(y)h(b)n(ug)g (\002x)o(es,)i(patches,)f(or)g(upgrades)e(to)i(the)g(features,)g (functionality)0 4693 y(or)c(performance)d(of)i(the)h(source)f(code)h (\(\224Enhancements\224\))c(to)k(an)o(yone;)f(ho)n(we)n(v)o(er)m(,)e (if)k(you)e(choose)g(to)h(mak)o(e)f(your)g(Enhancements)0 4792 y(a)n(v)n(ailable)j(either)g(publicly)-5 b(,)23 b(or)g(directly)g(to)g(La)o(wrence)g(Berk)o(ele)o(y)f(National)h (Laboratory)-5 b(,)22 b(without)g(imposing)h(a)h(separate)f(written)0 4892 y(license)f(agreement)e(for)h(such)h(Enhancements,)d(then)j(you)e (hereby)h(grant)g(the)g(follo)n(wing)g(license:)28 b(a)22 b(non-e)o(xclusi)n(v)o(e,)d(ro)o(yalty-free)0 4991 y(perpetual)d (license)i(to)g(install,)h(use,)f(modify)-5 b(,)16 b(prepare)g(deri)n (v)n(ati)n(v)o(e)g(w)o(orks,)i(incorporate)d(into)j(other)f(computer)f (softw)o(are,)h(distrib)n(ute,)0 5091 y(and)j(sublicense)f(such)h (Enhancements)e(or)i(deri)n(v)n(ati)n(v)o(e)e(w)o(orks)i(thereof,)f(in) h(binary)f(and)h(source)f(code)h(form.)p eop end %%Page: 2 3 TeXDict begin 2 2 bop 0 5549 3901 4 v 0 5649 a Fm(ii)p eop end %%Page: 3 4 TeXDict begin 3 3 bop 2764 747 a Fu(CONTENTS)0 1594 y Fp(1)83 b(Intr)o(oduction)3281 b(1)125 1694 y Fo(1.1)110 b(Acron)o(yms)19 b(and)g(T)-6 b(erminology)51 b(.)42 b(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)143 b(1)125 1793 y(1.2)110 b(Ov)o(ervie)n(w)40 b(.)h(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(2)125 1893 y(1.3)110 b(Not)21 b(Co)o(v)o(ered)63 b(.)41 b(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(2)125 1993 y(1.4)110 b(References)58 b(.)41 b(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g (.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)143 b(3)0 2175 y Fp(2)83 b Fl(wsdl2py)19 b(basics)3233 b(5)125 2275 y Fo(2.1)110 b(Modules)74 b(.)41 b(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(5)125 2374 y(2.2)110 b(Generated)19 b(T)-7 b(ypeCodes)67 b(.)41 b(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(8)0 2557 y Fp(3)83 b(Security)3396 b(13)125 2657 y Fo(3.1)110 b(HTTP)21 b(Basic)g(Authorization)28 b(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(13)125 2756 y(3.2)110 b(HTTP)21 b(Digest)f(Authorization)58 b(.)42 b(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g (.)h(.)f(.)g(.)g(.)102 b(13)125 2856 y(3.3)110 b(Message)21 b(Security)k(.)41 b(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g (.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(13)0 3039 y Fp(4)83 b(SO)m(AP)19 b(Headers)3158 b(15)0 3221 y(5)83 b(T)-6 b(ype)20 b(Substitution)3064 b(17)0 3404 y(A)65 b(wsdl2py)20 b(scr)o(pt)3202 b(19)125 3504 y Fo(A.1)92 b(Command)19 b(Line)h(Flags)82 b(.)41 b(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g (.)102 b(19)0 3686 y Fp(B)70 b(Example:)25 b(W)-6 b(olframSear)o(ch) 2763 b(21)125 3786 y Fo(B.1)97 b(Code)20 b(Generation)f(from)g(WSDL)i (and)f(XML)g(Schema)39 b(.)j(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(21)p 0 5549 3901 4 v 3845 5649 a Fm(iii)p eop end %%Page: 4 5 TeXDict begin 4 4 bop 0 5549 3901 4 v 0 5649 a Fm(iv)p eop end %%Page: 1 6 TeXDict begin 1 5 bop 0 83 3901 9 v 3503 230 a Fm(CHAPTER)3641 427 y Fk(ONE)p 0 515 V 2821 978 a Fu(Introduction)0 1457 y Fj(ZSI)p Fo(,)18 b(the)g(Zolera)g(SO)m(AP)h(Infrastructure,)d(is)j(a) f(Python)f(package)g(that)i(pro)o(vides)d(an)i(implementation)e(of)i (the)g(SO)m(AP)i(speci\002cation,)0 1556 y(as)h(described)e(in)h Fl(SO)-5 b(AP)20 b(1.1)g(Speci\002cation)p Fo(.)0 1703 y(This)k(guide)f(demonstrates)g(ho)n(w)g(to)h(use)g(ZSI)g(to)g(de)n(v)o (elop)e Fl(W)-8 b(eb)25 b(Service)e Fo(applications)g(from)g(a)h Fl(W)-8 b(eb)25 b(Services)f(Description)f(Lan-)0 1803 y(gua)o(g)o(e)c Fo(document.)0 1950 y(This)g(document)f(is)i(primarily) d(concerned)g(with)j(demonstrating)c(and)j(documenting)d(ho)n(w)j(to)g (use)h(a)f Fl(W)-8 b(eb)20 b(Service)f Fo(by)g(creating)f(and)0 2049 y(accessing)27 b(Python)f(data)g(for)h(the)g(purposes)f(of)g (sending)g(and)h(recei)n(ving)e(SO)m(AP)j(messages.)46 b(T)-7 b(ypecodes)25 b(are)i(used)g(to)g(marshall)0 2149 y(Python)19 b(datatypes)g(into)h(XML,)g(which)g(can)g(be)g(included)e (in)i(a)h(SO)m(AP)g(En)m(v)o(elope.)i(The)c(typecodes)g(are)h (generated)e(from)i(informa-)0 2249 y(tion)25 b(pro)o(vided)d(in)k(the) f(WSDL)h(document,)e(and)g(generally)g(describe)g(SO)m(AP)i(and)f(XML)g (Schema)f(data)h(types.)40 b(F)o(or)24 b(a)i(lo)n(w-le)n(v)o(el)0 2348 y(treatment)19 b(of)h(typecodes,)f(and)g(a)i(description)e(of)h (SO)m(AP-based)f(processing)g(see)i(the)f(ZSI)g(manual.)0 2676 y Fi(1.1)121 b(Acron)n(yms)33 b(and)h(T)-14 b(er)s(minology)42 2894 y Fo(SO)m(AP)208 2994 y(Usually)16 b(refering)g(to)h(the)g (content)f(and)h(format)e(of)i(a)h(message)f(ultimately)f(sent)h(and)g (recei)n(v)o(ed)e(by)i(a)g Fl(W)-8 b(eb)18 b(Service)p Fo(,)f(see)h Fl(SO)-5 b(AP)208 3094 y(1.1)19 b(Speci\002cation)42 3260 y Fo(WSDL)208 3359 y(A)h(document)e(describing)h(a)i Fl(W)-8 b(eb)20 b(Service)p Fo(')-5 b(s)21 b(interf)o(ace,)e(see)i Fl(W)-8 b(eb)20 b(Services)h(Description)e(Langua)o(g)o(e)42 3525 y Fo(XMLSchema)208 3625 y(Standard)f(for)i(modeling)e(XML)j (document)d(structure.)24 b(See)c Fl(XML)h(Sc)o(hema)e(Speci\002cation) 42 3791 y Fo(schema)g(document)208 3891 y(a)h(\002le)h(containing)d(a)j (schema)f(de\002nition.)42 4057 y(schema)f(\(instance\))208 4156 y(The)g(set)i(of)f(rules)g(or)g(components)e(contained)h(in)h(the) g(assemblage)g(of)g(one)f(or)h(more)g(schema)g(documents.)42 4322 y(Element)f(Declaration)208 4422 y(A)e(schema)g(component)e(that)j (associates)g(a)g(name)e(with)i(a)g(type)f(de\002nition.)23 b(e)o(g.)g Fl(\241element)18 b(name=\224a)o(g)o(e\224)e (type=\224xsd:int\224\277,)42 4588 y Fo(GED)208 4688 y Fl(Global)j(Element)h(Declar)o(ation,)e(an)i(element)g(declar)m(ed)f (at)i(the)f(top-le)o(vel)f(of)h(a)g(sc)o(hema.)42 4854 y Fo(Comple)o(xT)-7 b(ype)208 4953 y(The)19 b(parent)h(of)g(all)g(type) g(de\002nitions)f(that)i(can)f(specify)f(attrib)n(utes)h(and)g (children.)42 5119 y(SimpleT)-7 b(ype)208 5219 y(A)20 b(simple)g(data)g(type)g(lik)o(e)h(a)f(string)g(or)g(inte)o(ger)-5 b(.)24 b(The)c Fl(XML)h(Sc)o(hema)e(Speci\002cation)e Fo(de\002nes)j(man)o(y)f(b)n(uilt-in)h(types.)p 0 5549 3901 4 v 3854 5649 a Fm(1)p eop end %%Page: 2 7 TeXDict begin 2 6 bop 42 83 a Fo(The)19 b(XML)i(Schema)e(type)h (library)208 183 y(The)c Fj(http://www.w3.org/2001/XMLSchema)c Fo(namespace,)k(which)h(contains)f(de\002nitions)g(of)h(v)n(arious)f (primiti)n(v)o(e)208 282 y(types)21 b(lik)o(e)g(string)g(and)f(inte)o (ger)m(,)g(as)i(well)g(as)g(a)f(compound)e(type)h Fl(comple)n(xT)-6 b(ype)20 b(used)h(to)h(cr)m(eate)f(a)o(g)o(gr)m(e)m(gate)e(types.)28 b(Con)m(ven-)208 382 y(tionally)19 b(the)h Fo(xsd)g Fl(pr)m(e\002x)g (is)h(used)f(to)g(map)g(to)g(this)h(sc)o(hema.)42 548 y(doc/liter)o(al)208 648 y(document)d(style)j(with)g(liter)o(al)f (encoding)42 814 y(rpc/enc)208 913 y(rpc)g(style)h(with)g(speci\002ed)e (encoding)o(,)f(not)i(compatible)f(with)h Fo(Basic)i(Pro\002le)e (\(WS-Interop\))42 1079 y Fl(rpc/liter)o(al)208 1179 y(rpc)g(style)h(with)g(liter)o(al)f(encoding)o(.)0 1506 y Fi(1.2)121 b(Ov)m(er)t(vie)n(w)0 1739 y Fo(The)24 b(ZSI)g Fl(W)-8 b(eb)25 b(Service)p Fo(tools)f(are)g(for)g(top-Do)n(wn)e Fl(W)-8 b(eb)25 b(Service)p Fo(de)n(v)o(elopment,)c(using)j(an)g(e)o (xisting)g(WSDL)h(Document)d(to)j(create)0 1839 y(client)d(and)g(serv)o (er)f(applications)f(\(see)j(1.3\).)29 b(A)23 b Fl(W)-8 b(eb)22 b(Service)p Fo(,)g(in)g(the)g(conte)o(xt)f(of)h(this)g (document,)f(e)o(xposes)g(a)h(WSDL)h(Document)0 1938 y(describing)28 b(the)i(service')-5 b(s)30 b(interf)o(ace,)g(this)h (document)c(is)k(typically)e(a)n(v)n(ailable)g(at)h(a)g(published)e (URL)j(\(see)f Fl(Uniform)f(Resour)m(ce)0 2038 y(Locator)p Fo(\).)h(The)21 b(WSDL)i(document)d(de\002nes)i(SO)m(AP)h(bindings)d (for)i(communicating)d(with)j(the)g(service.)30 b(These)22 b(bindings)f(will)i(be)0 2138 y(used)d(to)g(e)o(xchange)e(SO)m(AP)j (messages,)f(the)g(contents)f(of)h(these)g(messages)h(must)f(adhere)f (to)h(the)g(document)e(structure)h(speci\002ed)h(by)0 2237 y(the)25 b(schema.)38 b(The)24 b(schema)g(is)i(either)e(included)f (in)i(the)g(WSDL)g(Document,)f(imported)f(by)i(it,)h(or)e(represented)f (by)h(the)h(a)n(v)n(ailable)0 2337 y(b)n(uilt-in)20 b(types)g(\(such)f (as)i Fl(xsd:int,)f(xsd:string)o(,)f(etc)p Fo(\).)1536 2307 y Fh(1)0 2622 y Fg(1.2.1)100 b(soap)29 b(bindings)0 2825 y Fo(The)h(tw)o(o)g(styles)g(of)g(SO)m(AP)g(bindings)f(are)h Fl(rpc)g Fo(and)f Fl(document)p Fo(.)52 b(The)30 b(use)g(of)f Fl(liter)o(al)i(encoding)c(is)k(encour)o(a)o(g)o(ed)d(and)h(the)g(r)m (ec-)0 2924 y(ommended)23 b(way)i(to)f(de)o(velop)f(ne)o(w)i Fo(W)-7 b(eb)25 b(Service)p Fl(applications)d(\(see)j Fo(Basic)g(Pro\002le)g(\(WS-Interop\))p Fl(\).)35 b(The)25 b(SO)-5 b(AP)24 b(encoded)f(sup-)0 3024 y(port)32 b(is)g(maintained)e (for)i(use)g(with)g(older)g(applications,)g(and)f(other)h(SO)-5 b(AP)31 b(toolkits)h(r)m(estricted)g(to)g(rpc/encde)o(velopment.)56 b(A)0 3124 y(doc/liter)o(alservice)22 b(is)i(typically)e(described)g (as)h(an)f(e)n(xc)o(hang)o(e)f(of)i(documents,)e(while)i(a)g(rpc/encor) f(rpc/liter)o(alservice)h(is)g(thought)0 3223 y(of)33 b(in)g(terms)g(of)g(r)m(emote)g(pr)l(ocedur)m(e)f(calls.)62 b(Whether)33 b(this)g(distinction)f(of)h(purpose)e(is)j(meaningful)d (or)i(useful)f(is)i(debatable)o(.)0 3323 y Ff(ZSI)p Fl(supports)19 b(all)i(thr)m(ee)f(types,)g(b)n(ut)g(rpc/liter)o(aland)f(doc/liter)o (alar)m(e)g(the)h(focus)g(of)h(ongoing)d(de)o(velopment.)0 3605 y Fg(1.2.2)100 b(p)m(ython)29 b(tools)0 3807 y Fm(wsdl2p)n(y)0 4009 y Fl(The)22 b Fp(wsdl2py)g Fl(script)g(g)o(ener)o(ates)f(python)f (code)h(r)m(epr)m(esenting)g(the)g(various)h(components)d(de\002ned)h (in)i(a)g(WSDL)g(Document.)28 b(Most)0 4109 y(of)20 b(the)h(r)m (emaining)e(guide)g(focuses)h(on)g(how)g(to)g(use)h(this)f(tool)g(and)g (under)o(stand)e(its)j(output.)0 4433 y Fi(1.3)121 b(Not)34 b(Co)n(v)m(ered)104 4664 y Fl(1.)41 b(How)20 b(to)g(cr)m(eate)h(a)f (WSDL)g(document)104 4830 y(2.)41 b(How)20 b(to)g(write)i(XML)f(Sc)o (hema)104 4997 y(3.)41 b(Inter)l(oper)o(ability)104 5163 y(4.)g(How)20 b(to)g(use)h(W)-8 b(eb)21 b(Services)f(without)g(WSDL)p 0 5217 1560 4 v 90 5273 a Fe(1)120 5296 y Fd(The)c(xsd)h(pre\002x)h (refers)g(to)f(namespace)i Fc(\224http://www)-5 b(.w3.or)n (g/2001/XMLSc)o(hema\224)p 0 5549 3901 4 v 0 5649 a Fm(2)2981 b(Chapter)23 b(1.)52 b(Introduction)p eop end %%Page: 3 8 TeXDict begin 3 7 bop 0 87 a Fi(1.4)121 b(Ref)l(erences)104 304 y Fl(1.)41 b(W)-8 b(eb)49 b(services)h(de)o(velopment)d(patterns)h Ff(http://www-)t(128.ibm.com/developerworks/websph)o(ere/)208 404 y(library/techarticles/0511)p 1463 404 25 4 v 25 w(flurry/0511)p 2038 404 V 29 w(flurry.html)p 0 5549 3901 4 v 0 5649 a Fm(1.4.)k(Ref)n(erences)3241 b(3)p eop end %%Page: 4 9 TeXDict begin 4 8 bop 0 5549 3901 4 v 0 5649 a Fm(4)p eop end %%Page: 5 10 TeXDict begin 5 9 bop 0 83 3901 9 v 3503 230 a Fm(CHAPTER)3623 427 y Fk(TW)n(O)p 0 515 V 2517 978 a Fu(wsdl2p)-6 b(y)58 b(basics)0 1467 y Fl(The)32 b Fp(wsdl2py)h Fl(script)g(is)g(used)f(to)g (g)o(ener)o(ate)f(all)i(the)f(code)f(needed)g(to)i(access)f(a)g(W)-8 b(eb)33 b(Service)f(thr)l(ough)f(an)h(e)n(xposed)f(WSDL)0 1566 y(document,)18 b(usually)i(this)h(description)e(is)i(available)e (at)h(a)g(URL)h(whic)o(h)f(is)h(pr)l(o)o(vided)e(to)i(the)f(script.)0 1713 y Fp(wsdl2py)g Fl(will)i(g)o(ener)o(ate)d(a)h(client,)g(types,)g (and)g(service)h(module)o(.)i(F)-5 b(r)l(om)21 b(the)f(the)h(WSDL)f(SO) -5 b(AP)20 b(Bindings,)f(the)h(client)h(and)e(service)0 1813 y(modules)g(ar)m(e)i(cr)m(eated.)j(The)d(types)f(module)f (contains)g(typecodes)g(for)i(the)f(sc)o(hema)g(de\002ned)e(by)i(the)g (WSDL.)0 2138 y Fi(2.1)121 b(Modules)0 2385 y Fg(2.1.1)100 b(client)28 b(stub)g(module)0 2587 y Fm(classes)0 2789 y Fl(The)20 b(service)h(item)g(in)f(the)g Fo(W)-7 b(eb)21 b(Services)f(Description)f(Language)g Fl(de\002nition)f(contains)h(one) h(or)g(mor)m(e)h(port)f(items.)0 3055 y Fm(locator)83 b Fl(De\002nes)22 b(a)g(factory)g(method)g(for)g(eac)o(h)g(port)g (item,)h(and)e(stor)m(es)i(the)g(service')m(s)f(addr)m(ess.)31 b(Use)23 b(to)g(gr)o(ab)e(a)h(client\(port\))f(to)0 3154 y(the)f Fo(W)-7 b(eb)21 b(Service)p Fl(.)236 3393 y Fb(#)45 b(Example)f(Locator)236 3484 y(class)g (WhiteMesaSoapRpcLitTestSvcLocator:)416 3575 y (SoapTestPortTypeRpc_address)c(=)45 b ("http://www.whitemesa.net/test-rpc-l)o(it")416 3667 y(def)f(getSoapTestPortTypeRpcAddress\(self\):)595 3758 y(return)g(WhiteMesaSoapRpcLitTestSvcLocator.Soa)o(pTestP)o(ortTyp)o (eRpc_a)o(ddress)416 3849 y(def)g(getSoapTestPortTypeRpc\(self,)c (url=None,)2343 3862 y(**)2433 3849 y(kw\):)595 3941 y(return)k(Soap11TestRpcLitBindingSOAP\(url)39 b(or)45 b(WhiteMesaSoapRpcLitTestSvcLocator.Soap)o(TestPo)o(rtType)o(Rpc_ad)o (dress,)5302 3954 y(**)5392 3941 y(kw\))236 4032 y(})0 4438 y Fm(por)s(t)83 b Fl(Eac)o(h)20 b(port)g(item)h(will)h(be)e(r)m (epr)m(esented)g(by)h(a)f(single)h(class)g(de\002nition,)d(gr)o(ab)i(a) g(port)h(thr)l(ough)e(one)h(of)h(the)f(locator')m(s)g(factory)0 4537 y(methods.)236 4775 y Fb(loc)45 b(=)f (WhiteMesaSoapRpcLitTestSvcLocator\(\))236 4867 y(port)g(=)h (loc.getSoapTestPortTypeRpc\(tracefile=sy)o(s.stdo)o(ut\))0 5272 y Fm(message)83 b Fl(classes)20 b(that)f(r)m(epr)m(esent)h(the)f (SO)-5 b(AP)20 b(and)e(XML)i(Sc)o(hema)e(data)h(types.)25 b(A)20 b(Messa)o(g)o(e)f(instance)g(is)i(serialized)f(as)f(a)h(XML)0 5372 y(instance)o(.)j(A)c(Messa)o(g)o(e)g(passed)g(as)g(an)f(ar)m (gument)f(to)i(a)g(port)f(method)g(is)h(then)g(serialized)g(into)f(a)h (SO)-5 b(AP)18 b(En)m(velope)f(and)h(tr)o(ansported)p 0 5549 3901 4 v 3854 5649 a Fm(5)p eop end %%Page: 6 11 TeXDict begin 6 10 bop 0 83 a Fl(to)25 b(the)g Fo(W)-7 b(eb)25 b(Service)p Fl(,)h(the)e(client)h(will)h(then)f(wait)g(for)g (an)g(e)n(xpected)f(r)m(esponse)o(,)i(and)d(\002nally)h(the)h(SO)-5 b(AP)25 b(r)m(esponse)f(is)i(mar)o(shalled)0 183 y(bac)n(k)20 b(into)g(the)g(Messa)o(g)o(e)h(r)m(eturned)e(to)i(the)f(user)-9 b(.)236 421 y Fb(msg)45 b(=)f(echoBooleanRequest\(\))236 512 y(msg.InputBoolean)e(=)j(True)236 603 y(rsp)g(=)f (port.echoBoolean\(msg\))0 1024 y Fg(2.1.2)100 b(types)28 b(module)0 1226 y Fl(De\002nes)e(typecodes)f(for)i(all)f(components)f (of)h(all)h(sc)o(hema)e(speci\002ed)h(by)g(the)g(tar)m(g)o(et)g(WSDL)h (Document)e(\(not)h(including)e(b)n(uilt-in)0 1326 y(types\).)46 b(Eac)o(h)26 b(sc)o(hema)g(component)f(declar)m(ed)h(at)h(the)h(top-le) o(vel,)f(the)g(immediate)g(c)o(hildr)m(en)f(of)h(the)g(sc)o(hema)g(ta)o (g)o(,)h(ar)m(e)g(global)d(in)0 1425 y(scope)c(and)f(by)i(importing)e (the)i(\224types\224)f(module)g(an)g(application)e(has)i(access)h(to)f (the)h(GEDs)g(and)e(global)g(type)h(de\002nitions)f(either)0 1525 y(dir)m(ectly)g(or)h(with)g(the)f(unique)f(\(namespace)o(,name\))d (combination)i(thru)i(con)m(venience)e(functions.)0 1791 y Fm(classes)0 1993 y(Global)h(T)-10 b(ype)17 b(De\002nition)879 2084 y Fb(class)44 b(ns1:)1058 2175 y(..)1058 2267 y(..)1058 2358 y(class)g(HelpRequest_Def\(ZSI.TCcompound.ComplexTy)o(pe,)39 b(TypeDefinition\):)1237 2449 y(schema)44 b(=)h ("http://webservices.amazon.com/AWSEComm)o(erceSe)o(rvice/)o(2006-1)o (1-14")1237 2541 y(type)g(=)f(\(schema,)g("HelpRequest"\))1237 2632 y(def)h(__init__\(self,)d(pname,)i(ofwhat=\(\),)f (attributes=None,)f(extend=False,)h(restrict=False,)5003 2645 y(**)5093 2632 y(kw\):)1417 2723 y(..)0 3133 y Fm(Global)19 b(Element)g(Declar)o(ation)1082 3225 y Fb(class)44 b(ns1:)1261 3316 y(..)1261 3407 y(..)1261 3499 y(class)g (Help_Dec\(ZSI.TCcompound.ComplexType,)39 b(ElementDeclaration\):)1440 3590 y(literal)44 b(=)h("Help")1440 3681 y(schema)f(=)h ("http://webservices.amazon.com/AWSECom)o(merceS)o(ervice)o(/2006-)o (11-14")1440 3773 y(def)g(__init__\(self,)2292 3786 y(**)2382 3773 y(kw\):)1620 3864 y(..)0 4273 y Fm(helper)24 b(functions)0 4475 y(Global)19 b(T)-10 b(ype)17 b(De\002nition)1058 4567 y Fb(klass)44 b(=)h(ZSI.schema.GTD\(\\)1237 4658 y("http://webservices.amazon.com/AWSECommerc)o(eServi)o(ce/200)o (6-11-1)o(4",)1237 4749 y("HelpRequest"\))1058 4841 y(typecode)f(=)g (klass\("Help"\))p 0 5549 3901 4 v 0 5649 a Fm(6)2914 b(Chapter)24 b(2.)52 b Fl(wsdl2py)19 b(basics)p eop end %%Page: 7 12 TeXDict begin 7 11 bop 0 83 a Fm(Global)19 b(Element)g(Declar)o(ation) 1261 174 y Fb(typecode)43 b(=)i(ZSI.schema.GED\(\\)1440 266 y("http://webservices.amazon.com/AWSECommer)o(ceServ)o(ice/20)o (06-11-)o(14",)1440 357 y("Help"\))0 644 y Fl(Eac)o(h)20 b(module)f(le)o(vel)i(class)h(de\002ntion)d(r)m(epr)m(esents)i(a)g (unique)e(namespace)o(,)g(the)n(y')n(r)m(e)h(simply)h(wr)o(apper)o(s)g (of)g(individual)e(namespaces.)0 743 y(In)k(the)g(e)n(xample)g(abo)o (ve)o(,)g(the)g(two)h(inner)f(classes)h(of)g Ff(ns1)f Fl(ar)m(e)h(the)f(typecode)f(r)m(epr)m(esentations)g(of)i(a)f(global)f (type)h(de\002nition)f Fa(Hel-)0 843 y(pRequest)p 319 843 25 4 v 30 w(Def)p Fl(,)g(and)f(a)h(global)e(element)i(declar)o (ation)e Fa(Help)p 1814 843 V 29 w(Dec)p Fl(.)30 b(In)22 b(most)g(cases)g(a)g Ff(TypeCode)f Fl(instance)g(r)m(epr)m(esents)h (either)g(a)0 943 y(global)d(or)i(local)e(element)h(declar)o(ation.)0 1089 y(In)e(the)g(e)n(xample)g Ff(GED)g Fl(r)m(eturns)h(a)f Ff(Help_Dec)g Fl(instance)f(while)i Ff(GTD)f Fl(r)m(eturns)h(the)f (class)h(de\002nition)d Ff(HelpRequest_Def)p Fl(.)22 b(Why)0 1189 y(this)e(asymmetry?)25 b(The)19 b(element)h(name)e(is)j (serialized)f(as)g(the)f(XML)h(ta)o(g)g(name)o(,)f(while)h(the)f(type)g (de\002nition)f(describes)i(the)f(contents)0 1289 y(\(c)o(hildr)m(en,)g (te)n(xt)i(node\).)0 1436 y(In)j(the)g(g)o(ener)o(ated)e(code)i(an)f (element)h(declar)o(ation)e(either)j(de\002nes)e(all)h(its)h(content)e (in)h(its)h(contructor)e(or)i(it)g(subclasses)f(a)g(global)0 1535 y(type)c(de\002nition,)e(whic)o(h)i(is)h(another)e(g)o(ener)o (ated)g(class.)0 1818 y Fg(2.1.3)100 b(ser)s(vice)28 b(module)0 2019 y Fl(sk)o(eleton)22 b(class,)g(normally)f(subclassed)g (and)g(in)m(vok)o(ed)g(by)g(implementation)f(code)o(.)29 b(The)22 b(sk)o(eleton)g(de\002nes)f(a)g(callbac)n(k)g(method)g(for)0 2119 y(eac)o(h)e(oper)o(ation)g(de\002ned)f(in)j(the)f(SO)-5 b(AP)20 b(Binding.)j(These)e(methods)e(mar)o(shal/unmar)o(shall)g(XML)h (into)g(python)f(types.)0 2385 y Fm(e)n(xample:)29 b(DateSer)r(vice)0 2587 y(ser)r(v)n(er)17 b(sk)n(eleton)h(code)837 2678 y Fb(class)44 b(simple_Date_Service\(ServiceSOAPBinding)o(\):)1016 2769 y(..)1016 2861 y(..)1016 2952 y(def)g(soap_getCurrentDate\(self,)d (ps\):)1195 3043 y(self.request)i(=)i (ps.Parse\(getCurrentDateRequest.typecode)o(\))1195 3135 y(return)f(getCurrentDateResponse\(\))1016 3317 y (soapAction['urn:DateService.wsdl#getCurr)o(entDat)o(e'])39 b(=)44 b('soap_getCurrentDate')1016 3409 y (root[\(getCurrentDateRequest.typecode.nsp)o(name,g)o(etCurr)o(entDat)o (eReque)o(st.ty)o(pecode)o(.pname)o(\)])39 b(=)45 b ('soap_getCurrentDate')p 0 5549 3901 4 v 0 5649 a Fm(2.1.)52 b(Modules)3351 b(7)p eop end %%Page: 8 13 TeXDict begin 8 12 bop 0 83 a Fm(ser)r(v)n(er)17 b(implementation)j (code)1092 174 y Fb(DS)45 b(=)f(simple_Date_Service)1092 266 y(class)g(Service\(DS\):)1271 357 y(def)h (soap_getCurrentDate\(self,)40 b(ps\):)1451 448 y(response)j(=)i (DS.soap_getCurrentDate\(self,)40 b(ps\))1451 540 y(response.Today)i(=) j(today)f(=)h(response.new_today\(\))1451 631 y(self.request.Input)1451 722 y(dt)f(=)h(time.localtime\(time.time\(\)\))1451 814 y(today.Year)e(=)i(dt[0])1451 905 y(today.Month)e(=)h(dt[1])1451 996 y(today.Day)f(=)i(dt[2])1451 1088 y(today.Hour)e(=)i(dt[3])1451 1179 y(today.Minute)e(=)h(dt[4])1451 1270 y(today.Second)f(=)h(dt[5]) 1451 1362 y(today.Weekday)e(=)j(dt[6])1451 1453 y(today.DayOfYear)d(=)j (dt[7])1451 1544 y(today.Dst)e(=)i(dt[8])1451 1636 y(return)f(response) 0 2082 y Fi(2.2)121 b(Gener)o(ated)36 b(T)-14 b(ypeCodes)0 2313 y Fl(The)18 b(g)o(ener)o(ated)f(inner)h(typecode)e(classes)j(come) f(in)g(two)h(\003avor)o(s,)f(as)g(mentioned)e(abo)o(ve)o(.)23 b(element)18 b(declar)o(ations)f(can)g(be)h(serialized)0 2412 y(into)h(XML,)h(g)o(ener)o(ally)e(type)h(de\002nitions)f(cannot.) 1460 2382 y Fh(1)1516 2412 y Fl(Basically)-5 b(,)19 b(the)h(name)e (attrib)n(ute)h(of)h(an)f(element)g(declar)o(ation)e(is)j(serialized)g (into)0 2512 y(an)g(XML)h(ta)o(g)o(,)f(b)n(ut)g(type)g(de\002nitions)e (lac)n(k)j(this)g(information)d(so)j(the)n(y)f(cannot)e(be)i(dir)m (ectly)h(serialized)f(into)g(an)g(XML)h(instance)o(.)0 2659 y(Most)33 b(element)f(declar)o(ations)f(declar)m(e)g(a)i(type)f (attrib)n(ute)o(,)j(this)d(must)h(r)m(efer)m(ence)f(a)h(type)f (de\002nition.)59 b(Considering)31 b(the)i(abo)o(ve)0 2759 y(scenario,)h(a)d(g)o(ener)o(ated)g(T)-6 b(ypeCode)30 b(class)i(r)m(epr)m(esenting)f(an)g(element)h(declar)o(ation)d(will)k (subclass)f(the)f(g)o(ener)o(ated)f(T)-6 b(ypeCode)0 2858 y(class)21 b(r)m(epr)m(esenting)e(the)h(type)g(de\002nition.)0 3141 y Fg(2.2.1)100 b(special)29 b(handling)h(of)e(instance)h(attr)q (ib)n(utes)0 3342 y Fl(The)23 b(attrib)n(utes)f(discussed)h(below)f(ar) m(e)h(common)e(to)h(all)h(T)-6 b(ypeCodes,)22 b(for)h(mor)m(e)g (information)e(see)i(the)g(ZSI)f(manual.)30 b(I'm)23 b(r)m(eintr)l(o-)0 3442 y(ducing)i(them)i(to)g(point)f(out)g(certain)h (con)m(ventions)d(adher)m(ed)h(to)i(in)g(the)g(g)o(ener)o(ated)e(code)o (,)i(necessary)g(for)g(r)m(eliably)g(dealing)e(with)0 3542 y(WSDL)c(and)e(various)h(messa)o(ging)f(patterns)h(and)f(usa)o(g)o (es.)0 3807 y Fm(p)n(yclass)0 4009 y Fl(All)24 b(instances)f(of)h(g)o (ener)o(ated)e(T)-6 b(ypeCode)22 b(classes)j(will)f(have)f(a)h(pyclass) f(attrib)n(ute)o(,)h(instances)f(of)h(the)g(pyclass)f(can)g(be)g(cr)m (eated)g(to)0 4109 y(stor)m(e)f(the)g(data)f(r)m(epr)m(esenting)g(an)g (element)h(declar)o(ation.)1706 4079 y Fh(2)1737 4109 y Fl(.)30 b(The)22 b(pyclass)g(itself)g(has)g(a)g(typecode)e(attrib)n (ute)o(,)j(whic)o(h)e(is)i(a)f(r)m(efer)m(ence)0 4209 y(to)e(the)h(T)-6 b(ypeCode)19 b(instance)g(describing)h(the)g(data,)f (thus)h(making)f(pyclass)h(instances)g(self-describing)o(.)0 4355 y(When)k(par)o(sing)g(an)g(XML)i(instance)e(the)g(data)g(will)i (be)e(mar)o(shalled)g(into)h(an)f(instance)g(of)g(the)h(class)g (speci\002ed)f(in)h(the)f(typecode')m(s)0 4455 y(pyclass)c(attrib)n (ute)o(.)416 4693 y Fb(typecode)43 b(=)i(ZSI.schema.GED\(\\)595 4785 y("http://webservices.amazon.com/AWSECom)o(merceS)o(ervice)o (/2006-)o(11-14")o(,)595 4876 y("Help"\))416 4967 y(msg)f(=)h (typecode.pyclass\(\))p 0 5195 1560 4 v 90 5250 a Fe(1)120 5274 y Fd(The)16 b Fc(pname)i(can)g(be)f(set)g(to)h(None)f(when)h(a)f (XML)f(ta)o(g)i(name)g(is)f(not)g(needed)i(\(e)m(g)o(.)i(attrib)o (utes\).)90 5331 y Fe(2)120 5355 y Fd(Exceptions)d(include)h(the)f (Union)g(T)-5 b(ypeCode,)17 b(may)g(need)h(multiple)h(p)o(yclasses)g (to)f(mak)o(e)f(it)h(w)o(ork)p 0 5549 3901 4 v 0 5649 a Fm(8)2914 b(Chapter)24 b(2.)52 b Fl(wsdl2py)19 b(basics)p eop end %%Page: 9 14 TeXDict begin 9 13 bop 0 83 a Fm(aname)0 285 y Fl(The)18 b(aname)e(is)j(a)e(T)-6 b(ypeCode)17 b(instance)g(attrib)n(ute)o(,)h (its)h(value)e(is)h(a)g(string)g(r)m(epr)m(esenting)f(the)g(attrib)n (ute)h(name)f(used)g(to)h(r)m(efer)m(ence)f(data)0 384 y(r)m(epr)m(esenting)k(an)g(element)g(declartion.)28 b(The)21 b(set)i(of)e(XMLSc)o(hema)f(element)i(names)f(is)h(NCName,)h (this)f(is)g(a)g(super)o(set)g(of)f(or)m(dinary)0 484 y(identi\002er)o(s)f(in)g(python.)k(K)m(e)n(ywor)m(ds)c(lik)o(e)h(r)m (eturn)f(and)g(class)g(ar)m(e)h(le)m(gal)e(NCNames.)0 631 y Fo(Namespaces)h(in)g(XML)236 869 y Fb(From)44 b(Namespaces)g(in)g (XML)236 960 y(NCName)89 b(::=)44 b(\(Letter)g(|)h('_'\))f (\(NCNameChar\))1987 973 y(*)236 1052 y(NCNameChar)88 b(::=)45 b(Letter)e(|)i(Digit)f(|)h('.')f(|)h('-')f(|)h('_')f(|)h (CombiningChar)d(|)j(Extender)236 1234 y(From)f(Python)g(Reference)g (Manual)f(\(2.3)i(Identifiers)d(and)j(keywords\))236 1326 y(identifier)e(::=)i(\(letter|"_"\))e(\(letter)g(|)i(digit)f(|)g ("_"\))2478 1339 y(*)236 1508 y(Default)g(set)g(of)h(anames)236 1600 y(ANAME)f(::=)h(\("_"\))f(\(letter)f(|)i(digit)f(|)h("_"\))1941 1613 y(*)0 2008 y Fm(tr)o(ansf)n(or)r(m)82 b Fl(NCName)22 b(into)e(an)f(AN)n(AME)104 2213 y(1.)41 b(pr)m(epr)m(end)19 b(\224)p 578 2213 25 4 v 30 w(\224)104 2375 y(2.)41 b(c)o(har)o(acter) 19 b(not)g(in)i(set)g(\(letter)f Fj(|)h Fl(digit)f Fj(|)h Fl(\224)p 1463 2375 V 30 w(\224\))f(c)o(hang)o(e)f(to)h(\224)p 1977 2375 V 30 w(\224)0 2640 y Fm(Attr)q(ib)n(ute)25 b(Declar)o(ations:)k(attrs)p 1011 2640 V 29 w(aname)0 2841 y Fl(The)36 b(attr)o(s)p 317 2841 V 30 w(aname)f(is)h(a)g(T)-6 b(ypeCode)35 b(instance)g(attrib)n(ute)o(,)k(its)e(value)e(is)h(a)g (string)g(r)m(epr)m(esenting)f(the)g(attrib)n(ute)h(name)f(used)g(to)0 2941 y(r)m(efer)m(ence)h(a)h(dictionary)-5 b(,)39 b(containing)c(data)g (r)m(epr)m(esenting)h(attrib)n(ute)g(declar)o(ations.)72 b(The)37 b(k)o(e)n(ys)f(of)h(this)g(dictionary)e(ar)m(e)i(the)0 3041 y Fj(\(namespace,name\))18 b Fl(tuples,)i(the)g(value)f(of)i(eac)o (h)e(k)o(e)n(y)h(r)m(epr)m(esents)g(the)h(value)e(of)i(the)f(attrib)n (ute)o(.)0 3305 y Fm(Mix)n(ed)j(T)-10 b(e)n(xt)22 b(Content:)29 b(mix)n(ed)p 980 3305 V 30 w(aname)0 3507 y Fl(Its)21 b(value)e(r)m(epr)m(esents)i(the)f(attrib)n(ute)g(name)g(used)g(to)g (stor)m(e)h(te)n(xt)g(content)e(that)h(some)g(Comple)n(xT)-6 b(ype)20 b(de\002nitions)e(allow)-6 b(.)0 3787 y Fg(2.2.2)100 b(Metaclass)28 b(Magic:)35 b(p)m(yclass)p 1460 3787 30 4 v 36 w(type)0 3989 y Fl(The)21 b(\226comple)n(xT)-6 b(ype)19 b(\003a)o(g)i(pr)l(o)o(vides)g(many)f(con)m(veniences)f(to)i (the)g(pr)l(o)o(gr)o(ammer)-9 b(.)27 b(This)21 b(option)f(is)i(tested)f (and)f(r)m(eliable)o(,)h(and)f(highly)0 4089 y(r)m(ecommended)e(by)i (the)h(author)o(s.)0 4236 y(When)e(\226comple)n(xT)-6 b(ype)18 b(is)i(enabled)e(the)h Fj(__metaclass__)f Fl(attrib)n(ute)h (will)i(be)e(set)i(on)e(all)g(g)o(ener)o(ated)f(pyclasses.)25 b(The)20 b(metaclass)0 4335 y(will)28 b(intr)l(ospect)f(the)h(typecode) d(attrib)n(ute)i(of)h(pyclass,)g(and)f(cr)m(eate)g(a)g(set)h(of)f (helper)g(methods)g(for)g(eac)o(h)f(element)h(and)g(attrib)n(ute)0 4435 y(declar)m(ed)21 b(in)h(the)h(comple)n(xT)-6 b(ype)21 b(de\002nition.)29 b(This)23 b(option)d(simply)j(adds)f(wr)o(apper)o(s) g(for)g(dealing)f(with)i(content,)e(it)i(doesn')n(t)e(modify)0 4535 y(the)f(g)o(ener)o(ation)f(sc)o(heme)o(.)0 4681 y(Use)k(help)f(in)g(a)h(python)e(interpr)m(eter)h(to)h(vie)o(w)g(all)f (the)g(pr)l(operties)h(and)e(methods)h(of)g(these)h(typecodes.)30 b(Looking)21 b(at)i(the)f(g)o(ener)o(ated)0 4781 y(code)e(is)h(not)e (very)i(helpful.)0 5001 y Fp(Getters/Setters)40 b Fl(A)22 b(g)o(etter)h(and)f(setter)h(function)f(is)h(de\002ned)e(for)i(eac)o(h) e(element)h(of)h(a)g(comple)n(x)f(type)o(.)31 b(The)23 b(functions)e(ar)m(e)i(named)208 5101 y Fj(get_element_ANAME)g Fl(and)i Fj(set_element_ANAME)f Fl(r)m(espectively)-5 b(.)42 b(In)26 b(this)h(e)n(xample)o(,)g(variable)e(msg)h(has)g(func-) 208 5201 y(tions)d(named)f Fj(get_element__Options)e Fl(and)i Fj(set_element__Options)p Fl(.)31 b(In)23 b(addition)f(to)h (elements,)h(g)o(etter)o(s)208 5300 y(and)g(setter)o(s)i(ar)m(e)f(g)o (ener)o(ated)f(for)h(the)g(attrib)n(utes)g(of)g(a)g(comple)n(x)g(type)o (.)39 b(F)-9 b(or)25 b(attrib)n(utes,)h(just)f(the)g(name)g(of)g(the)g (attrib)n(ute)g(is)208 5400 y(used)19 b(in)i(determining)e(the)h (method)f(names,)h(so)g(g)o(et)p 1729 5400 25 4 v 30 w(attrib)n(ute)p 2044 5400 V 29 w(N)n(AME)h(and)e(set)p 2555 5400 V 30 w(attrib)n(ute)p 2870 5400 V 29 w(N)n(AME)i(ar)m(e)f(cr) m(eated.)p 0 5549 3901 4 v 0 5649 a Fm(2.2.)52 b(Gener)o(ated)24 b(T)-10 b(ypeCodes)2834 b(9)p eop end %%Page: 10 15 TeXDict begin 10 14 bop 0 83 a Fp(F)n(actory)18 b(Methods)42 b Fl(If)17 b(an)g(element)g(of)g(a)h(comple)n(x)e(type)i(is)g(a)f (comple)n(x)g(type)g(itself)o(,)i(then)d(a)i(con)m(veniece)d(factory)i (method)f(is)i(cr)m(eated)208 183 y(to)i(g)o(et)g(an)g(instance)g(of)g (that)g(types)g(holder)g(class.)25 b(The)c(factory)e(method)h(is)h (named,)e Fj(newANAME)p Fl(.)0 349 y Fp(Pr)o(operties)40 b Fo(Python)26 b(class)h(properties)f Fl(ar)m(e)h(cr)m(eated)f(for)h (eac)o(h)f(element)h(of)g(the)g(comple)n(x)f(type)o(.)44 b(The)n(y)27 b(ar)m(e)g(initialized)f(with)i(the)208 448 y(corr)m(esponding)21 b(g)o(etter)k(and)e(setter)i(for)g(that)e (element.)37 b(T)-8 b(o)24 b(avoid)g(name)f(collisions)h(the)g(pr)l (operties)g(ar)m(e)g(named,)g Fj(PNAME)p Fl(,)208 548 y(wher)m(e)17 b(the)g(\002r)o(st)h(letter)g(of)f(the)g(type')m(s)g (pname)f(attrib)n(ute)h(is)h(capitalized.)k(In)17 b(our)g(running)f(e)n (xample)o(,)h(msg)g(has)g(class)h(pr)l(operty)-5 b(,)208 648 y Fj(Options)p Fl(,)32 b(whic)o(h)e(calls)h(functions)f Fj(get_element__Options)d Fl(and)j Fj(set_element__Options)e Fl(under)i(the)208 747 y(hood.)0 1013 y Fm(e)n(xample)0 1215 y(schema)83 b Fl(T)-8 b(ak)o(en)20 b(fr)l(om)h(the)f(W)-8 b(olfr)o(amSear)m(c)o(h)19 b(WSDL.)236 1453 y Fb()326 1544 y()416 1636 y()416 1727 y()326 1818 y()326 1910 y()236 2001 y()236 2092 y()326 2184 y()416 2275 y()505 2366 y()416 2458 y()326 2549 y()236 2640 y()0 3049 y Fm(help)84 b Fl(\(W)-8 b(olfr)o(amSear)m(c)o(hRequest\))p 0 5549 3901 4 v 0 5649 a Fm(10)2868 b(Chapter)24 b(2.)52 b Fl(wsdl2py)19 b(basics)p eop end %%Page: 11 16 TeXDict begin 11 15 bop 236 174 a Fb(Help)44 b(on)h (WolframSearch_Holder)c(in)k(module)f(WolframSearchService_types)c (object:)236 357 y(class)k(WolframSearch_Holder\(__builtin__.object\)) 281 448 y(|)90 b(Methods)43 b(defined)h(here:)281 540 y(|)281 631 y(|)90 b(__init__\(self\))281 722 y(|)281 814 y(|)g(get_element_Options\(self\))281 905 y(|)281 996 y(|)g(new_Options\(self\))281 1088 y(|)269 b(returns)44 b(a)g(mutable)g(type)281 1179 y(|)281 1270 y(|)90 b (set_element_Options\(self,)40 b(value\))281 1362 y(|)281 1453 y(|)90 b(------------------------------------)o(------)o(------)o (------)o(------)o(------)o(----)281 1544 y(|)g(Properties)43 b(defined)g(here:)281 1636 y(|)281 1727 y(|)90 b(Options)281 1818 y(|)269 b(property)43 b(for)i(element)e(\(None,Options\),)g (minOccurs="0")f(maxOccurs="1")h(nillable="False")281 1910 y(|)281 2001 y(|)269 b()44 b(=)h(get_element_Options\(self\)) 281 2092 y(|)281 2183 y(|)269 b()44 b(=)h (set_element_Options\(self,)40 b(value\))281 2275 y(|)0 2679 y Fm(request)360 2771 y Fb(from)k(WolframSearchService_client)c (import)2153 2784 y(*)360 2862 y(msg)k(=)h(WolframSearchRequest\(\))360 2953 y(#)g(get)f(an)g(instance)g(of)g(a)h(Options)f(holder)g(class)f (using)h(factory)g(method)360 3045 y(msg.Options)f(=)i(opts)f(=)g (msg.new_Options\(\))360 3227 y(#)h(assign)e(values)h(using)g(the)h (properties)e(or)h(methods)360 3318 y(opts.Query)f(=)i('Newton')360 3410 y(opts.set_element_Limit\(10\))360 3592 y(#)g(don't)f(forget)f (the)i(attribute)360 3684 y(opts.set_attribute_timeout\(1.0\))0 4184 y Fm(in)n(v)n(ok)n(e)318 4275 y Fb(port)f(=)g (WolframSearchServiceLocator\(\).getWolframS)o(earchm)o(yPortT)o (ype\(\))318 4367 y(rsp)g(=)h(port.WolframSearch\(msg\))318 4458 y(print)f('SearchTime:',)e(rsp.Result.SearchTime)0 4867 y Fm(XML)84 b Fl(XML)21 b(appr)l(oximation)c(of)k(our)f(W)-8 b(olfr)o(amSear)m(c)o(hRequest)17 b(instance)o(.)p 0 5549 3901 4 v 0 5649 a Fm(2.2.)52 b(Gener)o(ated)24 b(T)-10 b(ypeCodes)2788 b(11)p eop end %%Page: 12 17 TeXDict begin 12 16 bop 281 174 a Fb()371 266 y()460 357 y(Newton)460 448 y(10.0)371 540 y()281 631 y()p 0 5549 3901 4 v 0 5649 a Fm(12)2868 b(Chapter)24 b(2.)52 b Fl(wsdl2py)19 b(basics)p eop end %%Page: 13 18 TeXDict begin 13 17 bop 0 83 3901 9 v 3503 230 a Fm(CHAPTER)3495 427 y Fk(THREE)p 0 515 V 3151 978 a Fu(Secur)s(ity)0 1506 y Fi(3.1)121 b(HTTP)33 b(Basic)g(A)l(uthor)r(ization)0 1738 y Fl(auth=dict\(style=ZSI.A)l(UTH.httpbasic,)15 b(user=USERN)n(AME,)20 b(passwor)m(d=P)-7 b(ASSW)n(ORD\))0 2062 y Fi(3.2)121 b(HTTP)33 b(Digest)h(A)l(uthor)r(ization)0 2293 y Fl(auth=dict\(style=ZSI.A)l(UTH.httpdig)o(est,)16 b(user=USERN)n(AME,,)j(passwor)m(d=P)-7 b(ASSW)n(ORD\))0 2618 y Fi(3.3)121 b(Message)34 b(Secur)r(ity)p 0 5549 3901 4 v 3808 5649 a Fm(13)p eop end %%Page: 14 19 TeXDict begin 14 18 bop 0 5549 3901 4 v 0 5649 a Fm(14)p eop end %%Page: 15 20 TeXDict begin 15 19 bop 0 83 3901 9 v 3503 230 a Fm(CHAPTER)3561 427 y Fk(FOUR)p 0 515 V 2492 978 a Fu(SO)l(AP)56 b(Headers)p 0 5549 3901 4 v 3808 5649 a Fm(15)p eop end %%Page: 16 21 TeXDict begin 16 20 bop 0 5549 3901 4 v 0 5649 a Fm(16)p eop end %%Page: 17 22 TeXDict begin 17 21 bop 0 83 3901 9 v 3503 230 a Fm(CHAPTER)3634 427 y Fk(FIVE)p 0 515 V 2304 978 a Fu(Type)58 b(Substitution)p 0 5549 3901 4 v 3808 5649 a Fm(17)p eop end %%Page: 18 23 TeXDict begin 18 22 bop 0 5549 3901 4 v 0 5649 a Fm(18)p eop end %%Page: 19 24 TeXDict begin 19 23 bop 0 83 3901 9 v 3480 230 a Fm(APPENDIX)3814 427 y Fk(A)p 0 515 V 2603 978 a Fu(Wsdl2p)-6 b(y)57 b(scr)6 b(pt)0 1506 y Fi(A.1)120 b(Command)35 b(Line)f(Flags)0 1754 y Fg(A.1.1)100 b(Gener)o(al)29 b(Flags)0 1934 y Fp(-h,)20 b(\227help)42 b Fl(Display)20 b(the)g(help)g(messa)o(g)o(e)g (and)g(available)e(command)h(line)h(\003a)o(gs)g(that)g(can)g(be)g (passed)g(to)g(wsdl2py)-5 b(.)0 2083 y Fp(-f)20 b(FILE,)h (\227\002le=FILE)43 b Fl(Cr)m(eate)21 b(bindings)d(for)j(the)f(WSDL)h (whic)o(h)f(is)h(located)e(at)h(the)h(local)e(\002le)i(path.)0 2233 y Fp(-u)g(URL,)f(\227url=URL)43 b Fl(Cr)m(eate)20 b(bindings)f(for)i(the)f(r)m(emote)g(WSDL)h(whic)o(h)e(is)j(located)d (at)h(the)g(pr)l(o)o(vided)g(URL.)0 2382 y Fp(-x,)g(\227schema)41 b Fl(J)m(ust)21 b(pr)l(ocess)f(a)h(sc)o(hema)e(\(xsd\))h(\002le)g(and)f (g)o(ener)o(ate)g(the)i(types)f(mapping)e(\002le)o(.)0 2532 y Fp(-d,)i(\227deb)n(ug)42 b Fl(Output)19 b(verbose)h(deb)n(ug)o (ging)e(messa)o(g)o(es)j(during)e(code)h(g)o(ener)o(ation.)0 2681 y Fp(-o)g(OUTPUT)p 441 2681 25 4 v 30 w(DIR,)g (\227output-dir=OUTPUT)p 1510 2681 V 30 w(DIR)41 b Fl(Write)22 b(g)o(ener)o(ated)c(\002les)j(to)f(OUTPUT)p 2852 2681 V 30 w(DIR.)0 2957 y Fg(A.1.2)100 b(T)-12 b(ypecode)29 b(Extensions)g(\(Stab)n(le\))0 3136 y Fp(-b,)20 b(\227complexT)-6 b(ype)20 b(\(mor)o(e)f(in)i(section)f(\))42 b Fl(Gener)o(ate)19 b(con)m(venience)f(functions)h(for)i(comple)n(xT)-6 b(ypes.)25 b(This)c(includes)e(g)o(etter)o(s,)i(set-)208 3236 y(ter)o(s,)g (factory)f(methods,)f(and)g(pr)l(operties.)25 b(**)20 b(Do)g(NO)m(T)h(use)g(with)f(\226simple-naming)e(**)0 3511 y Fg(A.1.3)100 b(De)m(v)n(elopment)29 b(Extensions)g(\(Unstab)n (le\))0 3690 y Fp(-a,)20 b(\227addr)o(ess)41 b Fl(WS-Addr)m(essing)18 b(support.)25 b(The)20 b(WS-Addr)m(essing)f(sc)o(hema)g(must)i(be)f (included)e(in)j(the)f(corr)m(esponding)e(WSDL.)0 3840 y Fp(-w)-5 b(,)21 b(\227twisted)41 b Fl(Gener)o(ate)19 b(a)h(twisted.web)h(client.)k(Dependencies:)e(python)p Fj(>=)p Fl(2.4,)17 b(T)-6 b(wisted)p Fj(>=)p Fl(2.0.0,)18 b(T)-6 b(wistedW)e(eb)p Fj(>=)p Fl(0.5.0)0 4115 y Fg(A.1.4)100 b(Customizations)29 b(\(Unstab)n(le\))0 4295 y Fp(-e,)20 b(\227extended)41 b Fl(Do)20 b(e)n(xtended)f(code)h(g)o(ener)o(ation.)0 4444 y Fp(-z)g(AN)n(AME,)i(\227aname=AN)n(AME)42 b Fl(Use)21 b(a)f(custom)g(function,)e(AN)n(AME,)i(for)h(attrib)n(ute)f(name)g(cr)m (eation.)0 4594 y Fp(-t)g(TYPES,)h(\227types=TYPES)42 b Fl(Dump)20 b(the)g(g)o(ener)o(ated)f(type)h(mappings)e(to)j(a)f (\002le)g(named,)f(\223TYPES.py\224.)0 4743 y Fp(-s,)h (\227simple-naming)42 b Fl(Simplify)20 b(the)g(g)o(ener)o(ated)f (naming)o(.)0 4893 y Fp(-c)h(CLIENTCLASSSUFFIX,)i (\227clientClassSuf\002x=CLIENTCLASSSUFFIX)43 b Fl(The)f(suf)o(\002c)e (to)h(use)g(for)h(service)g(client)208 4992 y(class.)25 b(\(default)19 b(\223SO)-5 b(AP\224\))0 5142 y Fp(-m)21 b(PYCLASSMAPMODULE,)g(\227pyclassMapModule=PYCLASSMAPMODULE)43 b Fl(Use)28 b(the)g(e)n(xisting)g(e)n(xisting)g(type)208 5241 y(mapping)14 b(\002le)j(to)g(determine)f(the)h(\223pyclass\224)g (objects)f(to)h(be)g(used.)23 b(The)17 b(module)f(should)g(contain)f (an)h(attrib)n(ute)o(,)h(\223mapping\224,)208 5341 y(whic)o(h)i(is)j(a) e(dictionary)f(of)h(form,)h(sc)o(hemaT)-6 b(ypeName:)23 b(\(moduleName)o(.py)-5 b(,)17 b(className\).)p 0 5549 3901 4 v 3808 5649 a Fm(19)p eop end %%Page: 20 25 TeXDict begin 20 24 bop 0 5549 3901 4 v 0 5649 a Fm(20)p eop end %%Page: 21 26 TeXDict begin 21 25 bop 0 83 3901 9 v 3480 230 a Fm(APPENDIX)3814 427 y Fk(B)p 0 515 V 1553 978 a Fu(Example:)71 b(W)-6 b(olfr)n(amSearch)0 1506 y Fi(B)n(.1)120 b(Code)35 b(Gener)o(ation)g (from)e(WSDL)h(and)h(XML)e(Schema)0 1738 y Fl(This)18 b(section)f(co)o(ver)o(s)g(wsdl2py)-5 b(,)18 b(the)f(second)g(way)g (ZSI)g(pr)l(o)o(vides)g(to)h(access)f(WSDL)g(services.)25 b(Given)17 b(the)h(path)e(to)h(a)g(WSDL)h(service)o(,)0 1837 y(two)23 b(\002les)h(ar)m(e)e(g)o(ener)o(ated,)g(a)h(')m(service') g(\002le)f(and)g(a)h(')n(types')f(\002le)o(,)i(that)e(one)g(can)h(then) f(use)h(to)g(access)g(the)g(service)o(.)33 b(As)24 b(an)e(e)n(xample)o (,)0 1937 y(we)k(will)h(use)f(the)f(sear)m(c)o(h)g(service)i(pr)l(o)o (vided)d(by)i(W)-8 b(olfr)o(am)25 b(Resear)m(c)o(h)g(Inc.)2247 1934 y Fo(c)2225 1937 y Fn(\015)o Fl(,)i Ff (http://webservices.wolfram.com/)0 2036 y(wolframsearch/)p Fl(,)d(whic)o(h)h(pr)l(o)o(vides)g(a)g(service)h(for)g(sear)m(c)o(hing) d(the)i(popular)f(MathW)-8 b(orld)25 b(site)o(,)i Ff(http://mathworld.) 0 2136 y(wolfram.com/)p Fl(,)19 b(among)f(other)o(s.)236 2374 y Fb(wsdl2py)44 b(--complexType)f (http://webservices.wolfram.com/servi)o(ces/Se)o(archSe)o(rvices)o (/Wolfr)o(amSear)o(ch2.ws)o(dl)0 2661 y Fl(Run)24 b(the)h(abo)o(ve)f (command)g(to)h(g)o(ener)o(ate)f(the)h(service)h(and)e(type)h(\002les.) 40 b(wsdl2py)25 b(uses)g(the)g(name)g(attrib)n(ute)g(of)g(the)g (wsdl:service)0 2761 y(element)h(to)g(name)g(the)g(r)m(esulting)g (\002les.)43 b(In)26 b(this)h(e)n(xample)o(,)g(the)f(service)h(name)f (is)h(W)-8 b(olfr)o(amSear)m(c)o(hService.)41 b(Ther)m(efor)m(e)26 b(the)g(\002les)0 2860 y(W)-8 b(olfr)o(amSear)m(c)o(hService)p 760 2860 25 4 v 27 w(services.py)20 b(and)g(W)-8 b(olfr)o(amSear)m(c)o (hService)p 2075 2860 V 27 w(services)p 2369 2860 V 30 w(types.py)20 b(should)f(be)h(g)o(ener)o(ated.)0 3007 y(The)k(')m(service')f(\002le)h(contains)e(locator)-9 b(,)24 b(portT)-6 b(ype)o(,)24 b(and)e(messa)o(g)o(e)i(classes.)37 b(A)24 b(locator)f(instance)g(is)h(used)g(to)g(g)o(et)f(an)h(instance)f (of)g(a)0 3107 y(portT)-6 b(ype)23 b(class,)h(whic)o(h)f(is)i(a)e(r)m (emote)h(pr)l(oxy)f(object.)34 b(Messa)o(g)o(e)24 b(instances)f(ar)m(e) g(sent)h(and)f(r)m(eceived)g(thr)l(ough)f(the)h(methods)g(of)h(the)0 3206 y(portT)-6 b(ype)19 b(instance)o(.)0 3353 y(The)32 b(')n(types')e(\002le)h(contains)g(class)h(r)m(epr)m(esentations)e(of)i (the)f(de\002nitions)f(and)h(declar)o(ations)e(de\002ned)h(by)i(all)f (sc)o(hema)g(instances)0 3453 y(imported)20 b(by)g(the)g(WSDL)g (de\002nition.)k(XML)c(Sc)o(hema)f(attrib)n(utes,)h(wildcar)m(ds,)g (and)f(derived)h(types)h(ar)m(e)f(not)g(fully)g(handled.)0 3735 y Fg(B)n(.1.1)100 b(Example)29 b(Use)f(of)g(Gener)o(ated)i(Code)0 3937 y Fl(The)e(following)e(shows)i(how)g(to)f(call)h(a)f(pr)l(oxy)g (method)g(for)h(W)-8 b(olfr)o(amSear)m(c)o(h.)45 b(It)28 b(assumes)f(wsdl2py)g(has)h(alr)m(eady)e(been)h(run)g(as)0 4037 y(shown)20 b(in)g(the)h(section)e(abo)o(ve)o(.)24 b(The)c(e)n(xample)g(will)i(be)e(e)n(xplained)f(in)h(gr)m(eater)g (detail)g(below)-6 b(.)p 0 5549 3901 4 v 3808 5649 a Fm(21)p eop end %%Page: 22 27 TeXDict begin 22 26 bop 236 174 a Fb(#)45 b(import)f(the)g(generated)f (class)h(stubs)236 266 y(from)g(WolframSearchService_client)d(import) 2029 279 y(*)236 448 y(#)k(get)f(a)h(port)f(proxy)g(instance)236 540 y(loc)h(=)f(WolframSearchServiceLocator\(\))236 631 y(port)g(=)h(loc.getWolframSearchmyPortType\(\))236 814 y(#)g(create)f(a)g(new)h(request)236 905 y(req)g(=)f (WolframSearchRequest\(\))236 996 y(req.Options)f(=)i (req.new_Options\(\))236 1088 y(req.Options.Query)d(=)j('newton')236 1270 y(#)g(call)f(the)g(remote)g(method)236 1362 y(resp)g(=)h (port.WolframSearch\(req\))236 1544 y(#)g(print)f(results)236 1636 y(print)g('Search)g(Time:',)g(resp.Result.SearchTime)236 1727 y(print)g('Total)g(Matches:',)f(resp.Result.TotalMatches)236 1818 y(for)i(hit)f(in)g(resp.Result.Matches.Item:)416 1910 y(print)g('--',)g(hit.Title)0 2196 y Fl(Now)21 b(eac)o(h)e (section)h(of)h(the)f(code)f(abo)o(ve)g(will)j(be)e(e)n(xplained.)236 2434 y Fb(from)44 b(WolframSearchService_client)d(import)2029 2447 y(*)0 2721 y Fl(W)-8 b(e)21 b(ar)m(e)e(primarily)h(inter)m(ested)g (in)f(the)h(service)g(locator)f(that)h(is)g(imported.)k(The)c(binding)e (pr)l(oxy)h(and)g(classes)i(for)f(all)f(the)h(messa)o(g)o(es)0 2821 y(ar)m(e)g(additionally)e(imported.)25 b(Look)20 b(at)g(the)g(W)-8 b(olfr)o(amSear)m(c)o(hService)p 2051 2821 25 4 v 27 w(services.py)20 b(\002le)h(for)f(mor)m(e)h (information.)236 3059 y Fb(loc)45 b(=)f (WolframSearchServiceLocator\(\))236 3150 y(port)g(=)h (loc.getWolframSearchmyPortType\(\))0 3437 y Fl(Using)20 b(an)g(instance)f(of)h(the)g(locator)-9 b(,)19 b(we)i(fetc)o(h)f(an)f (instance)h(of)g(the)g(port)g(pr)l(oxy)g(whic)o(h)g(is)h(used)e(for)i (in)m(voking)d(the)i(r)m(emote)g(methods)0 3537 y(pr)l(o)o(vided)j(by)g (the)h(service)o(.)35 b(In)24 b(this)g(case)f(the)h(default)f(location) f(speci\002ed)g(in)i(the)g(wsdlsoap:addr)m(ess)e(element)h(is)i(used.) 34 b(Y)-8 b(ou)24 b(can)0 3636 y(optionally)29 b(pass)h(a)h(url)f(to)h (the)f(port)h(g)o(etter)f(method)g(to)g(specify)h(an)f(alternate)f (location)h(to)g(be)g(used.)56 b(The)30 b(portT)-6 b(ype)30 b(-)g(name)0 3736 y(attrib)n(ute)g(is)h(used)f(to)g(determine)g(the)g (method)f(name)h(to)g(fetc)o(h)g(a)g(port)g(pr)l(oxy)g(instance)o(.)53 b(In)30 b(this)h(e)n(xample)o(,)h(the)e(port)g(name)g(is)0 3836 y(W)-8 b(olfr)o(amSear)m(c)o(hmyP)h(ortT)h(ype,)17 b(hence)j(the)g(method)f(of)i(the)f(locator)f(for)i(fetc)o(hing)e(the)h (pr)l(oxy)g(is)h(g)o(etW)-8 b(olfr)o(amSear)m(c)o(hmyP)h(ortT)h(ype.)0 3982 y(The)19 b(\002r)o(st)h(step)f(in)g(calling)g(W)-8 b(olfr)o(amSear)m(c)o(h)17 b(is)j(to)f(cr)m(eate)g(a)g(r)m(equest)g (object)f(corr)m(esponding)f(to)i(the)g(input)g(messa)o(g)o(e)g(of)g (the)g(method.)0 4082 y(In)h(this)h(case)o(,)f(the)g(name)g(of)g(the)g (messa)o(g)o(e)g(is)i(W)-8 b(olfr)o(amSear)m(c)o(hRequest.)22 b(A)e(class)h(r)m(epr)m(esenting)e(this)i(messa)o(g)o(e)f(was)h (imported)f(fr)l(om)0 4182 y(the)g(service)h(module)o(.)236 4420 y Fb(req)45 b(=)f(WolframSearchRequest\(\))236 4511 y(req.Options)f(=)i(req.new_Options\(\))236 4602 y(req.Options.Query)d (=)j('newton')0 4889 y Fl(Once)21 b(a)f(r)m(equest)h(object)f(is)i(cr)m (eated)e(we)i(need)e(to)h(populate)e(the)h(instance)g(with)i(the)f (information)e(we)j(want)e(to)h(use)g(in)g(our)g(r)m(equest.)0 4989 y(This)26 b(is)h(wher)m(e)f(the)g Fj(--complexType)e Fl(option)g(we)j(passed)e(to)h(wsdl2py)f(will)i(come)e(in)h(handy)-5 b(.)41 b(This)26 b(caused)f(the)h(cr)m(eation)e(of)0 5088 y(functions)j(for)h(g)o(etting)g(and)f(setting)h(elements)g(and)f (attrib)n(utes)h(of)g(the)g(type)o(,)i(class)f(pr)l(operties)f(for)g (eac)o(h)f(element,)j(and)d(con)m(ve-)0 5188 y(nience)c(functions)g (for)h(cr)m(eating)e(ne)o(w)i(instances)f(of)h(elements)g(of)g(comple)n (x)f(types.)35 b(This)24 b(functionality)e(is)j(e)n(xplained)d(in)i (detail)f(in)0 5288 y(subsection)c(A.1.2.)p 0 5549 3901 4 v 0 5649 a Fm(22)2373 b(Appendix)24 b(B)n(.)47 b(Example:)29 b(W)n(olfr)o(amSearch)p eop end %%Page: 23 28 TeXDict begin 23 27 bop 0 83 a Fl(Once)19 b(the)h(r)m(equest)f (instance)g(is)h(populated,)d(calling)h(the)i(r)m(emote)f(service)h(is) h(easy)-5 b(.)25 b(Using)19 b(the)h(port)f(pr)l(oxy)g(we)h(call)g(the)f (method)g(we)0 183 y(ar)m(e)i(inter)m(ested)g(in.)28 b(An)21 b(instance)g(of)g(the)g(python)f(class)i(r)m(epr)m(esenting)e (the)h(r)m(eturn)h(type)f(is)h(r)m(eturned)e(by)i(this)f(call.)28 b(The)21 b(r)m(esp)h(object)0 282 y(can)e(be)g(used)g(to)g(intr)l (ospect)g(the)g(r)m(esult)h(of)g(the)f(r)m(emote)g(call.)236 520 y Fb(resp)44 b(=)h(port.WolframSearch\(req\))0 807 y Fl(Her)m(e)29 b(we)g(see)h(that)e(the)h(r)m(esponse)f(messa)o(g)o(e)o (,)j(r)m(esp,)f(r)m(epr)m(esents)f(type)g(W)-8 b(olfr)o(amSear)m(c)o (hReturn.)47 b(This)30 b(object)e(has)g(one)g(element,)0 907 y(Result)20 b(whic)o(h)g(contains)f(the)h(sear)m(c)o(h)g(r)m (esults)h(for)g(our)f(sear)m(c)o(h)g(of)g(the)g(k)o(e)n(ywor)m(d,)g Fj(newton)p Fl(.)236 1145 y Fb(print)44 b('Search)g(Time:',)g (resp.Result.SearchTime)236 1236 y(...)0 1523 y Fl(Refer)21 b(to)f(the)g(wsdl)h(for)g(W)-8 b(olfr)o(amSear)m(c)o(hService)18 b(for)i(mor)m(e)h(details)f(on)g(the)g(r)m(eturned)f(information.)p 0 5549 3901 4 v 0 5649 a Fm(B)n(.1.)53 b(Code)23 b(Gener)o(ation)h (from)f(WSDL)h(and)g(XML)g(Schema)1844 b(23)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF ZSI-2.1-a1/doc/zsi.pdf0000644000175100017510000107655610712455103012605 0ustar zsizsi%PDF-1.4 3 0 obj << /Length 418 /Filter /FlateDecode >> stream xÚM‘Moœ@ †ïó+æV‚kÏ0_=Eé—’C¥v9%ʰ¤¬Â.ØDí¯¯g «Šò|¼¯Û$‘?’NñBÙn'/‚¶e Xåâõ/ñðˆrÏÏîBVË·¨2x’GQZÿoÓ‹ø~q)8EáµÓÑé¦ï¿(+U Î;’Õ³$ƒ ŒÒZ †öÙýîöC^(糪k×à~èÛ)'Ìêu¿êqnOÏëżLyA&;7ËyjóÇêN’÷PºH¡xïB²ÿÔæ³×\™¬í‡±Þå³yµûz>쓘A$ŠLAƒd>~&±³Ó¶oëyCT@€›Òþ¯TœV,%]B©qÓšn«¥îÿ\%ÞÂ:ð¥Ñœ… óéåÇn-ì0/ÃØq’ê¦?Ÿš\aö²å ’XdŒŠ9¹«:$#­A£^s~röy¿öø”œ¸r¤«5PˆîR€çùÛÄoAyñ•æn’JVÓÌÔ×ûz©ÇdúgÀŽlÍp\ÛOàƒ×±p<‡$|ŠÌöë1Îâ÷Ò '¦ŸQ&>Wâ/ÿ¡Fendstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 13 0 R >> endobj 1 0 obj << /Font << /F26 6 0 R /F27 9 0 R /F29 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 16 0 obj << /Length 2059 /Filter /FlateDecode >> stream xÚÍMw£Èñ>¿Âïå‚Þ³Í7¹aY$²¤´Þ™MÚ<@£õüúTu5ú2Ù\rØSUÕõÝÝU<Æ_ÆSøóTÏÖí»øíNw,Uw5ëÎašªŽqg¿)“åêë:|žÅ£ÅOuïbǃ®´å9ª­›&m©êÓ”&ßu¸íδTËvÝ;M54ä¦$™WòTÇö컇 ¾jÌPÍtÕ´À|M0éšÆîGº¥)ߪ‚7 ÁÑGÛñ}+)a™ªÂš µt´š©žeéB†_Ä·F³[ ó–7?FÌRxF›µ?¯:^3î{sÓt7)~þÿ=\ñfŸ·m^•£Ã0”¼¥uǾý ø½IÊŽg`‘a™Ê[Ã9âM¥z#zºKšs•w.YºŠI‰š¥”š7m¯¥ÚvI^æå»ä#y©Œ¶ä‘Ò»]oS[½uGäHÞ+ÈhkÒ¶Uš'`%²*=<œü½ˆÒž—]Ò wuÛœhzÁ1X¶ –Öí¸¤èº](Äo`…è0á"²e<)hw.Ež$DWæ"æ˜w»êÐÃÛ®ÉS´EÊÌË´8d"*7ÜŽRäûül¸}ÖÒôÙFÕÕµËL¸|hE^˜~°m)Å”}•åog„ºÈ%|ׇm‘·;Éžåhôv¤kÊ¡ëY ãª{zV`ŸŽ´uíéiŸdï=Xx ;ÛC]WM‡gd ÒñÔŸøÍug Žx`µYJ´œÆ¯#uì¯ÊVˆH«õÈÔ”å®Ï_Â§à‰°xþý¨çÄ/¬ƒ)¯a<[nb¢ô"×þ"þJ—SZýÅWâù{¸xº'\ðëjDRïr-¥¿¬æa,) “ùæ)\%ªèd"•èᢗGÄà—“´hæÏçb8â|î‹tCSfËùSVëôöŒ‹IyÁx# Uã ÖJºÌM8 ˆò(×yè?Îâ™ö’E¥ f2÷×{B^‡î¹U0 }tJsAÿS¸&è­æP]v²\DÁ?DÅ@$NÌOh™ÿâãòD÷„¥MެÚÏl„|ù#ÏB-!¼RTôfŽÉ‰±NŠ`Jì… r¾¤B2OÅ·‰‚{ÂRR!JQ2®i•'ª1’^gdTÖ£¨@úýŠÜ“8\..õ™˜x-‰#Çì‹|<ÏÃç`1 NZO‰:¡'“Gª2\n"ž5ßKÄ:ŒÄ)Æq{`*W)LÔ¬`à"†ã7^9t𵉂뽫` õâ£ùCfO©A”%Šýåå8Ø+¿§¼Æ ބ׺¥5­JlåÄÓhtOZÞðÑŽ!µû×øÊdω.&ØË»~K€wWoˆÜîð­ë°•2¡ÏÉÓ[‘dôLÁƒÑR³‰ ¥(xÚxsÌ[¹û¶w¢0Á㿯:N¢î€6)¸ìϭĉWK ö† V¶â¢?Rr‰¹isnùà£nò^è±É»ŽKɘšügß Z²¿º´ð&Œˆ’a´,E¥)äjDé1eSû¤$˜zU›¼Ç½$–"< Ç–0" >o†Òài*³tSê–þJ­?†Ò`ª®É>¥eÿALÕv ³½HEÜ4\•18WïîŠðФ¬~çjÉ»1\oÿæi׎ë#ß¶?Ò¡ÒÔ™¥2ï²4e±÷„«»?õxÝÓhÓjÀœФ)>ˆt¾.†/ÀöÁÔ¼ÏG&E‰|ôƒ/b¾Uµ”>© äuˆ$ŒØ@¸tÏTuÓ(ÛŸ vè÷ÌuÊi”PîA}Á»Ž^ÀZ™ÍQ]ÝÔ> endobj 14 0 obj << /Font << /F33 19 0 R /F29 12 0 R /F14 22 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 28 0 obj << /Length 970 /Filter /FlateDecode >> stream xÚVMoã6½çWè(ÍO}lOY R ØâÓv{ eÆ"KªH%õ¿ïŒHkåÈM÷bÓ3Ãá›7CÞÞm~"*I™ñ,Ú>G¼È‰ÌdIQ’Œsm÷Æ;ë]¹ä¯íï°A-6¤œ)¿#å9QEΦßž=˜— 0ËI)xÑ sŸ¤‚òØ .Xü­kÌ ½ñéK"TüðÕ{ÛçAC cåÆÁà>&ãÚz¨ö˜¯gwìZoêuõ¢!¬;jÌC—0¿Ö{c½O‡ õ©oÌÉ´N»Úaq÷|+•“±Vêö0e¡bmñžQz¹ZÊ)•âÓ áœj¨wfŸ¤¼dqÝ"öî×í hÄ"ÆÉ9º)%´ <ªNw””2¢DÉ ô2ƒÓ.៧"fKšWQ1™-òŒiÀ…”¿þb„á‚ÆO½©êï”òÊ“ð.U.¡y®®S ÎE’3nä•Öñ0I’¤Rp(¸O®×ƒ««±ÑC")f­¿Œ: ’º-;NIÁË,` ¦Åúc|݆ÒL ÚsÞN5G§¯¹±÷Ñ„M°i½¢¨ÌàBÌI½$¸T„e¥¸Ö„{3¦dÜÑ W!€·Í2†õ^ƒÏý$V¨Øt.ÚŠ„_ö ²ýˆâGçÕ¤lÜÔØÎ›vá„ÑšÇ]< §ñX7Á¬û¾©½lØ’¤,¶ *øð^2—„‰¬ŒDQÆÕ‡ žÁé½ð*&÷C¶˜ÒX“„Ñø€&t¡¤<Ä_RþV»#Ô¦(ãçt…l±Ùíª%tƒ¢"y†¥+þCã3.]×_Çó¿!c’KUþ¯Š»`púá¾s.`6·¶ïçM­ÁÒ€GÞ£$Ë Xp]O@´tmsö+í¿ì4 ýúqó%ø.öµíµ«0•Oü†E膗_°CæP§nªîš¢„›Ò‚]ti»fô3ûðrKçgmm½«›Ú…ÄqP£Ïƒ0ÛöžÑá¾c‹ŒBfòî'{0ÄG|‰vzgм8h3´aˆÀƒ2$¬€ÙrUð§)·wÉú±¡$ɳ|þA]Q‡(ë‰bX²a5¶{3X×uû{opÇ: OúìÕQ·sK‰tzË2^kQr!'ƒù{¬θL0\s"ü¢üw3vÀ>&á²!P8SÎ/Õ:1¬C³€þt^Çîdz_´„ŒÝú“qÂÕÜ€GçúO›M~3;ûZYbŸIkÜæ–:¤€¿?|VG˜(ÿVDWòendstream endobj 27 0 obj << /Type /Page /Contents 28 0 R /Resources 26 0 R /MediaBox [0 0 612 792] /Parent 13 0 R /Annots [ 29 0 R 33 0 R 34 0 R ] >> endobj 29 0 obj << /Type /Annot /Border [0 0 0] /Rect [123.7217 397.9233 235.0775 406.8995] /Subtype/Link/A<> >> endobj 33 0 obj << /Type /Annot /Border [0 0 0] /Rect [474.1369 385.9682 540 394.9194] /Subtype/Link/A<> >> endobj 34 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 374.013 141.1503 382.9891] /Subtype/Link/A<> >> endobj 26 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 37 0 obj << /Length 8 /Filter /FlateDecode >> stream xÚendstream endobj 36 0 obj << /Type /Page /Contents 37 0 R /Resources 35 0 R /MediaBox [0 0 612 792] /Parent 13 0 R >> endobj 35 0 obj << /ProcSet [ /PDF ] >> endobj 40 0 obj << /Length 2077 /Filter /FlateDecode >> stream xÚí[I“Û6¾÷¯ÐQ:ƒ}9º½Tœò8K+•Ter %ÚͲ$*;Iç×çAI@¶—©š)Ù²[_ß{üðº]Üüë•ʑҊLï'3$%É0bLÒÉbõëôùwo/ß.îf¿-¾½y¹¸! ÿÉDщ )¢Ød¹¹ÁÈð F‚?þØÃ怛ûÀ[;0cƒŒ„ña\ÿIvD2›Œñôõ¶ÙψžÖ«‡eSÕÛS„„ –!÷¡Ç Çex&§Õ)›“aµSùD‰”o]2Þaç>ø805ÞÀ§O<‹¬˜ÀÓoêÓ?gs ?4u{ý±,Vî7÷Õ¡½{Q/6å¶9%L©DXR>÷SËÐ¥Œ fŒ £Ù\ÀK»^ì…(*§42e¸áHsžŸ2>0:ez€u>uSæå_Åf·.gSÍ…Òáø‘©Òá2ã÷S%`ÁS…kŠ´6㦊NN•t4¾Ÿ*wåþÓrßΈ»jU¶w)ÇPŒ‘ÔR†#s£ÃeøQ¬‘Ñœ„ ¯“bÔ„IêGj'Ÿ›Vôâ¡N<Ïו ž#…CŒAÄ‹L¨v™Ø ÚU£T£ba–ˆOPÁd쌇Ùи.Ì.Ë-IÎeÁâÌ„"²p°Ìø 1ÌY³˜*„ABy‹=`Üâ`ÇâÎ⟚j]5U,³`D¸Í>Xfq¸ ÁdŸI†"à±ŒŽ‹ 8:ÐÑü>µ¼i«°ù›Ò^Û,³nCDÚ7 OIEÈ2$.Ã@²ÅP¥‡¯¡à‰Aê܈ @ùÌ0D©ÈÏ!C=À¾ áæÐâ¾´ƒÚ©Ì¾Sjo±ßûC¹º«‹ƒú–¬¤º¾hí²Ô(UíÝ»âP-ÛÛMy8â¾Ø®ÖÕöéٌ0eʉñçíqãûù¸€ˆ˜»ôXɼ»=`ÜÝÀŽ%ŸàîÅã®|^¯Êˆ³ôÀ„p\®‹Ã¡<œz{U4E{·„þ”c0”Ÿ‡Xn Ê†@!CÃ#µf‡Ë>¸Ú7Ÿ˜D¨d &è¸2Ê'Ce:ºçEá6 ëÜýùb¥ÒHbˆmÍH¬ìpŠ8 ©EHò?#d&…ÅbFËÁ>8-¬Ô ‹ŽÖ³íc È4¼|¨›ZØ0q›ûrˆ—nZ×ïݤ~Ü›.ˆ6»HÔ¤Š!e( mMe‡ËØM5à0Ü–ÿßKЦ׈ó‘‹k>8-©ÔJŠ‘Ô]e[?±Î+; ÿB¢±ÊÎá2$ûÊ. y >Ÿ¢©T«À(ô\ZšqšòÀiMu VS¼[…jö2ÑåjeH$±\mqzBŠ i\•ð.ܘ¨ºÔu‚#jœºœ–Lj%£œd^M×[·3¹˜11­6‘u1eà%KÒ‹õz—¡Ö÷z¹«>>CP2%(%”r\¯çƒÓ‚ê@­ ´Ôm]¯Ë"²ço÷¨) ‰Ä2œÃeHô. qUÂ×ÍpIuIhƒ ×öùà´º:P«.ãÔõ˿ߜïÜpd4S!‰ØÖÃeØ2^1ÅB Wi|-eS) x)¶¼%0œXrk x6×v3¹¶K¶Nÿk1Óx[C,OHE×á2„ˆ"ü¸)]óÅrbRTÌ ñ¸ÖϧEÕœ¨H+ª»fÿ°lÎTîÜŸG,p9\†Ã¸|W!üW—NiŒ*¤ížÐ(yà´Æ:Óm5öl¿/#Çàï…iÄ$ÖÂ2 †¢Ëçp•È×-º’Ò"iƒGöˆ8-­ä¤Åœ´vŲÛv~±hbIQCð¡:$šƒeø ¡Ï誔ÏH‚&²‘O CFÑüF¾Œnä÷ûžÔ6ò퉉Ÿ÷USî?ñÜÄ¡ÜWźúÛnö [ûgÛ~™9±8¶íçp‹ûüÀn;ßE…†ª»¬=`ÜÇÀŽ¥ŸàãWÅú‰¸—QÄ”–Ý{<È_îê}Ó;¸Ü·§û#‹Š¼a$ ޏ¹ÃeŒÜì›ÎbG€ˆÀ¯TÞË.îd÷¹È<ÁÇûòP¯ÿp ­§fHDµ6ýü¾l–÷½‹[¯oꦼ ie!…öÂ7=âëvÙôÁÕžXìô=jN‰ÉÑôq_w€ãñܬÕaWø¾è—%_uꑽ}r´”Èalo×á2 —ø> endobj 41 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 528.5779 141.0106 535.5815] /Subtype /Link /A << /S /GoTo /D (page001) >> >> endobj 42 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 516.6228 226.0513 523.5565] /Subtype /Link /A << /S /GoTo /D (page002) >> >> endobj 43 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 492.817 128.4578 501.7085] /Subtype /Link /A << /S /GoTo /D (page003) >> >> endobj 44 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 480.7323 200.6866 489.6836] /Subtype /Link /A << /S /GoTo /D (page003) >> >> endobj 45 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 468.7772 199.1919 477.7284] /Subtype /Link /A << /S /GoTo /D (page007) >> >> endobj 46 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 446.9889 133.439 455.8804] /Subtype /Link /A << /S /GoTo /D (page011) >> >> endobj 47 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 426.9141 120.1487 433.9626] /Subtype /Link /A << /S /GoTo /D (page013) >> >> endobj 48 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 415.0038 191.0625 421.9376] /Subtype /Link /A << /S /GoTo /D (page013) >> >> endobj 49 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 391.1981 313.8912 400.0896] /Subtype /Link /A << /S /GoTo /D (page015) >> >> endobj 53 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 369.893 270.1456 378.1718] /Subtype /Link /A << /S /GoTo /D (page019) >> >> endobj 54 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 357.7883 178.6003 366.1468] /Subtype /Link /A << /S /GoTo /D (page019) >> >> endobj 55 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 345.2404 273.7922 354.1916] /Subtype /Link /A << /S /GoTo /D (page021) >> >> endobj 56 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 333.878 190.5555 342.2365] /Subtype /Link /A << /S /GoTo /D (page023) >> >> endobj 57 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 321.3301 141.0806 330.2813] /Subtype /Link /A << /S /GoTo /D (page023) >> >> endobj 58 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 309.3749 144.7868 318.3261] /Subtype /Link /A << /S /GoTo /D (page024) >> >> endobj 59 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 297.4197 208.8757 306.371] /Subtype /Link /A << /S /GoTo /D (page025) >> >> endobj 60 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 287.482 179.4563 294.4158] /Subtype /Link /A << /S /GoTo /D (page026) >> >> endobj 61 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 275.5269 146.0521 282.4606] /Subtype /Link /A << /S /GoTo /D (page026) >> >> endobj 62 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 263.4919 134.9837 270.5055] /Subtype /Link /A << /S /GoTo /D (page027) >> >> endobj 63 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 249.5991 168.9064 258.5503] /Subtype /Link /A << /S /GoTo /D (page027) >> >> endobj 64 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 239.6614 136.6473 246.5951] /Subtype /Link /A << /S /GoTo /D (page028) >> >> endobj 65 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 225.6887 139.955 234.64] /Subtype /Link /A << /S /GoTo /D (page028) >> >> endobj 66 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 213.7336 181.728 222.6848] /Subtype /Link /A << /S /GoTo /D (page029) >> >> endobj 67 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 191.9453 279.8392 200.8368] /Subtype /Link /A << /S /GoTo /D (page031) >> >> endobj 68 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 170.0275 253.9963 178.919] /Subtype /Link /A << /S /GoTo /D (page033) >> >> endobj 69 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 148.1097 296.6264 157.0012] /Subtype /Link /A << /S /GoTo /D (page035) >> >> endobj 70 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 126.1919 196.6216 135.0834] /Subtype /Link /A << /S /GoTo /D (page037) >> >> endobj 71 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 114.1072 160.9958 123.0584] /Subtype /Link /A << /S /GoTo /D (page037) >> >> endobj 72 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 102.152 312.7359 111.1032] /Subtype /Link /A << /S /GoTo /D (page040) >> >> endobj 73 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 80.3637 142.7143 89.2552] /Subtype /Link /A << /S /GoTo /D (page043) >> >> endobj 38 0 obj << /Font << /F26 6 0 R /F33 19 0 R /F29 12 0 R /F39 52 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 98 0 obj << /Length 992 /Filter /FlateDecode >> stream xÚí™MoÚ0†ïù9’C<Û®›ZMÚ&¸U=T4“Pié([·?'vbÇ마C€¼"oâÇΠêÊ΂Aòå}¢9Œ6»ï2dc¥Î•nðt‘}øDH®€â˜ç‹Þ'-n¯f'E)„œ}¾(JÌàl¾Ü®wæùÉv{ó·¸^\fç‹îˆc ˜T~!»Ó©ÒåF 1Òì¥~-*ö+¹>išs%”G/ƒÍ–n¸92VΑ÷?±¹%BXÎ.vÛÍÁÉ 0¢È¯1pòmn¤‚ŽQŸ³W%ƒpÚ¼jC• îC‹bz‹°H#¬Ï†³Ã¶|íϸ}ÒX¿Íhm,Þq Óo¹]&NÞ³¢„¾üÉ4¤œp˜©6d "ªåzU=ØÕ{W=ÙgOÄ Q~¹Âll¤ @Źßlbä5 ŸQ‚Š×÷ž¸N9á0TmÈ@E-Tó¯a³“o¦Eýb{³¬Å@(ì ˆA)¥!SéךÈx?°´r õýD[Û˜eºÁAËìõ¨¥$dØ2ç»í¯åáêÄ ¨^OÜFC4ÙÜH£N3½^Œ„&–€P’8¹œpxrµ¡æzÍ”dL3ÝQÍŒVè5Ó-1Í…chf1Ä‘’¥!æ„ȵ!ƒ¶ˆ%›¦[(ªšÑ2½kºu&ZÞX6Ã\A (Ñã”Ä•sÕ† WÄrõ"ÙtËÅd3Ú«—M·ÙÄÈ«€ÑTLa@…LûÙÅ ¡êB*j¡ú_ÙôŠÅd3^ª“M¯ÖDÆû¥‘ M‘žÂ£²ée³ Ô£vfÒÜÜ?®«]eHú²)œ=ÛUØìwýNµ6oÿ¹©ãû-µ]ˆô»rÖåFºvê5f,4혲Äiç„ÃÓ® 5W*QC½1 Wè4Ô+1Í’£hh1ÊO“Ð>ÆËD \­€.7·‡ 8Ñ .ãØ=þY6=6"`Θ{ô ‹w¦* .=2\Q•†—Ö† bä¥Úà‹jC´T¯ n­ ž7Ó5¤ ¨ƵÁ kC¨Gí£Ñ†ÇÕòn]m HÕ° ¦ïöD*¿ÊÐWf›©Ò[[ˆ£Ð¬‚HŒg•Ϫ6Ô\ˆÄÿ@½Q+ˆVè­À-1M‚cXA1*%<ñÏ7D¬ ÄÚ¿A£nൈÙA¼Aç^‡ ‘#Â!hõòKä¢ù²ð3»º†ù­åKÍQ’åÏõ¤ô]ø>£\¶/ÖÙ<û¾·Ð÷dFŸûë<Å@ÃfVÕÕªmò¹ÃÕ,endstream endobj 97 0 obj << /Type /Page /Contents 98 0 R /Resources 96 0 R /MediaBox [0 0 612 792] /Parent 13 0 R /Annots [ 99 0 R 100 0 R 101 0 R 102 0 R 103 0 R 104 0 R 105 0 R 106 0 R 107 0 R 108 0 R 109 0 R 110 0 R 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R ] >> endobj 99 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 708.01 162.7589 716.9016] /Subtype /Link /A << /S /GoTo /D (page047) >> >> endobj 100 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 697.9677 132.2141 704.8766] /Subtype /Link /A << /S /GoTo /D (page047) >> >> endobj 101 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 683.9702 156.2934 692.9214] /Subtype /Link /A << /S /GoTo /D (page047) >> >> endobj 102 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 672.015 175.939 680.9662] /Subtype /Link /A << /S /GoTo /D (page048) >> >> endobj 103 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 662.0773 162.7792 669.0111] /Subtype /Link /A << /S /GoTo /D (page048) >> >> endobj 104 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 638.2716 163.3166 647.1631] /Subtype /Link /A << /S /GoTo /D (page053) >> >> endobj 105 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 628.2043 132.2141 635.1381] /Subtype /Link /A << /S /GoTo /D (page053) >> >> endobj 106 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 614.2317 156.2934 623.1829] /Subtype /Link /A << /S /GoTo /D (page053) >> >> endobj 107 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 602.2765 175.939 611.2278] /Subtype /Link /A << /S /GoTo /D (page054) >> >> endobj 108 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 592.3388 162.7792 599.2726] /Subtype /Link /A << /S /GoTo /D (page054) >> >> endobj 109 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 568.5331 214.7138 577.4246] /Subtype /Link /A << /S /GoTo /D (page055) >> >> endobj 110 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 558.4658 132.2141 565.3996] /Subtype /Link /A << /S /GoTo /D (page055) >> >> endobj 111 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 546.5107 131.6562 553.4445] /Subtype /Link /A << /S /GoTo /D (page055) >> >> endobj 112 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 534.4757 162.7792 541.4893] /Subtype /Link /A << /S /GoTo /D (page059) >> >> endobj 113 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 510.7498 154.7389 519.6413] /Subtype /Link /A << /S /GoTo /D (page061) >> >> endobj 114 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 500.6825 132.2141 507.6163] /Subtype /Link /A << /S /GoTo /D (page061) >> >> endobj 115 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 488.7274 131.6562 495.6611] /Subtype /Link /A << /S /GoTo /D (page061) >> >> endobj 96 0 obj << /Font << /F33 19 0 R /F29 12 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 125 0 obj << /Length 3071 /Filter /FlateDecode >> stream xÚ­ZÛ’Û6}Ÿ¯Ð£¦jDW’Ù'çâS›Ø›™TªçCA#f(R!!+“¯ßn4@‘{·¶\5A\ºÑݧOƒf‹þ±EÆK“TdbQîoþ¸ùõ·t±¹IßݤIQh±8ÁCšÈ"g‹ýÔy|¨oîoþ}ÃÂ:+Xh5^顛õk®ERhøyØ.dÁQäÅBCC2^,6¿.¿úöÕ»‡o~¼ýíá»õk)L&BjŽ˜N°.‰N¹þö‡opèÍ7ÃÖ°³VyÂtúPa¼RTË$Ë3æu e^¨È“è,˽Po×µ›c骶!E„)¾"§Y+•%2S~Ò/÷oh,Äy,Ë’Bpй»]q®—ng±‘-ikÛê¼{+ÔòÕ;zó¦Ùv¦wqì,ÎlYõ4ÔИw/nú®ƒ)ŸÍSXÖíŒ Ý]{ËÔòCµ±=½3aBµ?Ôvog¼–¾¯ÝÆùvN¦þ`Ëê}šòÒϹCu«¨áб¤PŠÌj`7öeW=Ú =VÍ¥±™P‰Š-” —™FC™%ØTI?èùlÑaôj<ÜÛUŒ]ózUêÕB1@-EjáK6äò~ªß¥¨°N’¥ùTÒðn$cv-âÄ1®VC “Û•J%Ÿ$;˜ÎUå±6Ý­L—w3®¨9„TÝkÞ9KR«0Öìm°Ži‚]žl~è¨_ŽÌŽ/÷¶ïÁµzpBN8L*áˆ@¬è`¶s=¹WE )¦þðhÝÉZt3•.8Þ[®ÂLê|ÚNùrð ~ClŒ¼žúðÝ?“™CI½Sjèó7§Ï… §ÒÙ?ŽUw G¶£ßΩCÿI‚Âa¡Éžèjׂa¨d…ø{kárŽÁZ]û»-íìÃ_˽©@õª±á\Lx߻ҾÆSaYf½£0bF q¦5 [íœ;|±^^Nö±ÿPöI¿Mëæ0Mêå2žÝœ T¢>å•=«pò›ª/}ï5¹£Ζñ/Àùs™ó©§ô·+V¨eo»U‰&Å'8³ºjžè¡®z‡'“j@ƾš=/Ä gƒóà\ü1oÛîÉâQ¯ÿ[5Ûö|€+ æ¥3õóŒú«¸ÁDx×ß>>n’]8t´ðŠ ަíñp è ži{çO^U ý{¯9qƒ_ЉAÁËsµ=õ›š^f¤Ãg9‹ãÚ¶¦zk/ן2…„¥2úÃO`™[JÒÜ!9Íì¥R`°Ì9E *:š؃–0´ùÆB_µ·xJLsÔá³üîZŸS¸gdãyÚ׺H´N³©…Êv\1`f}t‹:™ÜÌUHª9úÀ‡STêoÃcÊÔ0‘&ËÅÇÜAäƒ;ˆlêðÊ»üz½«žv+8›ˆë°Âѵ]eÂSIü0ÝèZž‚¬ŒŸ w‘¦Qg‚tXþ´»UËh@]ì÷‡ÙP§ÆCY\MD’‚ú`’¬çñV•Q|:ÂyJ }\j=5ñŸû:)Ûýúp|\›õ©_s ëT¯_÷­9$;·¯çT„D˲tä±è§®r.f¾Çúý±*w³MýWðŸ˜`Âþ1½ÄU'6©põh,3޹à.Ä:Ui *‹øý#éBü—Ày‚¢$‡Ä¬-Le_„på°3D®pu*X2›n LðS<ŽgYÄ^óŒ!â›Ðž2QkÛµ{l)Ïô±§jGGM((¬ÙScðªÀ®Ê³[ôPmû9€é©,žk…)U¨lFô¿ý|ýöûè­(ç¡ô„ -ÔAâKÃÐg°§ÁÇKÎTe<…Hp™úÎ;Ügsq;£cŠˆ²í#r-ðy­Øò  %82rlZ@Tl ònìÛ›ß1l±éù(”Œ%=Zª®zšàÕ€^C?#‚ /Á¦Wï¡ÒŠ;Ïaš_â*ú·ÖlÀKg2µJr=ä´Ì$;ONBA¬8(;ós¾l7sj÷‚¥b rÖ•à)$þ$P BÎD €!’Dþ–€ölð8¿÷P$6‡C]•1ËbŽo£+NܶWd,†ïŽNÅO8@ín4B— …2¨¿ uδ+ ö}ë¥/ĸèEÔÑjJE‚D¾U·¥GO˜<ö`œyÔ§»â¢á9¢74£‚ÿ@zž*‰;ŸÝŠƒ‹ø”ý‘ëÚ̲}Áþ;ÇA«B0<|ÆúŠ#tbÖÂnrehPJÃÕ1úüjtO>1rÕ™O0ƒ U¸`iždšeS³¶[bh™\B`=ÂH_lt¾ÔÉT 1’HŒè /T”zèòë€à…—'>_?¯¥ßÇ PN(EÒ†ý½­·«pG ²ÜÍ‘ÏáîáìPÈþL¤ôs/Ôº(¢]6/Ù/˜±Ÿ†úCäCvíñiwqåA–Á ¨íùÍu´æE"²¡Ôyø*yÕÌVðy"”ŽÃÊÚô},4Ò'd-ò#ä$#cQ6ñè'>—”õ¦iLÊ!%¢íw³Î,¡X¿.hy7Ú¸kP™ºÐAÞÑC¤i»MìŠ+lÂoåÁ†8Š„Â€N *5Ûî9¹Íü+Iˆñ* &*ê—Þ^¬sQ´ækpvq§S…„±7¡Rðè8ç5 °T ÜçíÞô+gî‘´ÆCæS«©±Õ„̦Vâog«¦á?Jƒúg(eg9Ðh~.³«Suwö×ÅÐ }âŽAŒª©œ¿k£Ñ…¡[ú…°±à4q)à=]5È×Ý L9SŽWù‚3)ŠA9y+ìtªÜn®h(’¬È³O¤rð¤‚ËÑw‰ 5‹óân¾ˆ0X çqþàC ’g*¹žæÛ)Ð ùmr;˜îöçKî¢çÒYfˆ»ˆŠ£5+LؽÏ0mƒüìã¦Ï‚éß\^5.E7E`sv“tÊéý<Ìn¥=ç}_ÍDXž'p"1Ï¿6ÇÚÍSf‘åzR£^ç ⤦‚zân 3ñ Âeöì^úÔÁ9–b㋊Zgé{ÿžx­€L•‰âÓŸ†[Ü*|`Bviz¼¼¡¯I=BOì?4¥ñC“¼øˆ‰ƒ[í‚ï ýôÝóâË7ë·á]\à\áÓ¶X¡œEÈÿˆ‚þõÞ—~ô˳…[¼Kö}»¢Ó,Ñ"SS˜©±Lô=£×µ/½>;k!#­ñZ„›j,ïÊú¸¡ Q,¾ÿú_azÛÖaŒ‚™}ÉTãùô¾Lò,ÏÏ÷^Ìsx …TCÑ.þ.ìTõƒø¤ßYÏA‡ÜèT]¹—0{§Ù™oý Ò¾†ß«Oý¢ÈUøÔÏLÅOýþaæSÿh¡ëÿ¬ @Q©¡š‘> endobj 129 0 obj << /Type /Annot /Border [0 0 0] /Rect [135.6351 531.0908 247.708 540.0669] /Subtype/Link/A<> >> endobj 74 0 obj << /D [124 0 R /XYZ 72 744.9066 null] >> endobj 123 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F33 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 133 0 obj << /Length 1408 /Filter /FlateDecode >> stream xÚ…WI³Û6 ¾ûWèVy&f¸ˆZŽI_Ó&“LÚ>wÒi’-ñÙšh«$çåýû%ËKš‹‚ @|Øè—ÛÕóW2 2–Å2¶A"ƒDpÆU¢‚mñ14]W•¹˶Yo¤áqX‹°löëÏÛ7Ï_)½<Ë™ÔqpwòŸû×$s¦_$,S2õ2Œt¾ðËA·Ù[bufmßø [Û~-ÒpoŸ!# MSÐNÞÖõtµ‹»òð¡7µ]K>®ÛþËà{KuÛ{{Ǧ°ý0¶má,Äáx(½tmžÐ‘`“¦L¤Yl„`™Ö¹L³·ÌIpØJX,#í¶>¬#– ¯£õ¤RÇaÑæÇÚ6ã³(f‚ñ,¡ ¸FQr%ФTz¶ õf˜ Z"ºÞ~â\~£ÕCۓܼ¿@î§5¬§óÆ£>Òº8‡Îä. zŠÂÉh´}í}Š—÷M–™ö7¶•Eïo8¦Ó2N¼\o (ÞDKAˆ”†ìjŠ‚¤4E!Þ½GÄdÁ-š¶°ì×ÂŒ1Å-BÌTÆd¦(œ‚‰õFpÎÃßÚµÀÌÙÈ$Eëîû§5…çP0ºóÁ¼á(—˜ð:qÊñ´sH)5`ÙaÄ )%CÌä¬.G~¸¿{K›idåU ¦ââ­ùhwD ¶ÿZæv€ø(­N§ÆC;ØÉÌh›b6Ñ6ž]wÙ¼s¥tNñî;CI—ÆN~-Âö­HrÈ ™&áph•—wÁ%Ò¡›R>^'H9SI4¥û_öîrÎüz, {z ‡")O&‚L~\BÁ]–ø£¢Òß¿pã+za«¶›½ bpX #­î߯•_üN+WHÊT©8KDœž#FU†’‰]%ÆL7Wd ˆÊgHS·G—Ðq¶^®¬½ ¾»5¶Ñ²:é2ôqÑt–¦hºUÙ@Æþ˜ÇÞ뚃tOùô¹n$ð`%ýý•ûR~ž¥‡¯&ŽÛ]¾SÑDs„À¨Tž*÷-Ô§QúVL€ÝBᎋ)÷ ê¦ÊÌ!S—Uiz/­š¨¿ß½%â>?ØÚø“MñÂu£0¿Ñ &å„Ð;!&·W›æh*¢]¹¹®c×Åi˜%áv–~,+/Ûõ®}Å\w H‘š”ûkÏ6íq˜”C—¯§YˆZ¿1út5;[Ü?Ù/]¬¡…VÔM ;ä}¹£Yîèf.6Mе=¸˜<‘Dn"†/eGÛ™]õtÉ_$¬¤·ÐxSð.¹1/ç¡ýϳCB_OÅôì8à€TÒ×4¹éÌra|ÂuBøZøv,±Gà8mJWÊÄ¢^ „K$¦äA}Sº{aF|#² àÚ«_¶+ý<A§LcßÓR±4QQ×+ÎàÂ™ŽœÐ—Yx3Ko–â/ñwÖM¯µ""Û ˆëL†®ó£ËÎc2ö–™qçÜè(ÑT¬Ã·ð:¬®=þØK·D,™Â‰¨QH¥sËo.šå6KÁ—W/Vk–%ð\Å܃€Ò™á4bœGÙ¹áïá9K_›¿˜N—ZÑ<$Á}Ž5àS ŽáeÁ/oIÍR©A1ËýŠk}x÷òqW …ímc{3ZbOÍ¡ÀÚ4DZÅΑ› *4v})†×Þ+ô ÑËOŸuÜì¤÷æ8‡jM½7Ë> endobj 134 0 obj << /Type /Annot /Border [0 0 0] /Rect [468.5746 521.7166 540 530.6927] /Subtype/Link/A<> >> endobj 135 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 509.7614 162.3357 518.7375] /Subtype/Link/A<> >> endobj 136 0 obj << /Type /Annot /Border [0 0 0] /Rect [184.0049 509.7614 250.8593 518.7375] /Subtype/Link/A<> >> endobj 75 0 obj << /D [132 0 R /XYZ 72 744.9066 null] >> endobj 131 0 obj << /Font << /F29 12 0 R /F35 25 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 139 0 obj << /Length 1769 /Filter /FlateDecode >> stream xÚ­]Û6òÝ¿B×>œ|sù)Q)ò° 6×Å%×Ý…yÐÊt,Ô–TIÎvï×w†CÊòF´E±XÎ7çK ‡?‘ä2Ég\å*©Ž«_VïÞód»âÉ·+Ί"SÉ8Ó…Éq¥3‡Õíê?+øl€ÑfÎéë»ÕÕ+™%+2Xîv‰.$S…-’ 6ZÈ"¹Û¾K_~sýöîæûõû»o¯^iÍ”Î$ÀV ›%©XÆ¥G¿ûïZòô ¢¯nî&ñ =3–‰ŒÿfÌ9E3¤f¹Í…·C &¬ÉЉeyn½b7¿–Çîà2Œ;¾Q¦ Š pÖ¹5dʾÖÅmZíËnt}8´ÍXÖ¿*Ò’€ÍéxÚ­n-L¥zä±¥›aß®¥I&|8¢¡=º ìUUf¦ªÌ2V Þñ*þxûzÁ‘³BɈó÷µ1i0dçÊñÔ»­7ÚšôõHàhç}ßþ¼ë= '•8]ߢAeðagó$Ø(4ÙB쨂ÉB O&™Xoç<½¥°H?¢ê¸—¹Moɰ{–À::pl$è%­Š<Ï\½áÄ­=±Y0™ ¶½ÉCÝ|:Ѹw >Òœ)ȇ³‹Ø¶ºr¬ö ÌsÅ !¢?íötpøŽ`j=’Œ-\‡¨± <À5Ž{ÿŠp·;5½£?–a}p÷ÄT]ùP–E‘Þ” àá¥øºYkÿã[ ]o)un.C÷¡²2-Üï.©›î4Ò¶+ûòè 4 t:WÕ?q.»'ªº˜ˆ)u¦œÈ훵2éõ["èÝ/'7Œ`UÎÚ ‡ ÑGPy8N½ƒTnHLïŸhyvžj2)ey´—â¼Y—‡ú.$ß}YýL;ÿV¸îCÎ’_Ñáx:Œ5½«ág CÂVeHÉû€pÖÙCçPŠK¬Aà ø²IÙœeRÇÂØíÚÃJÔD\µ±¶Ä"t¡Âêw1CeÂ(z>e‚…àδ/“\cucÆ*JÂ/ÿvuú«C[•‡«ûº¹ê|ÌBÜ4…†f,5Ï/×› ³õ >/î®û¾|Œ˜@„ö´u;ÂØ;°é'n8ü ¯VxFê’59hÞ}ñ R=£ÓCÛ¶_¼•9Ò. sÕÞËò¸Úb;{±Hÿð7†©¼°É ^ö†³‚%T¢âÿkˆø¿G¡át<ë£`XÁñâë#3f ¸ºÐx“´ð¥Ûµ=ÝÖa™ð|Ò‘6ÿ|Q]¼ü®÷(?º¾üà&dš“Æç×üŒROÙ?$ˆØ\Ñrp 2‹wÁZè·è.­Ýõmp 6`òà±kû‘öóvóÔ©ñŽ]/ÿõö]õâ®?9¯ÐÂh7%1tg}fAß,D1¯’xÚ:¬Ý –/<–´œ 4žBÆ.Ç5T‚Âdâ×ÑÏŒ¸ª¾îÆp`05ŽÐO°þyþ—rÀ¢9i°¨ÄÑ Ä |•ÅÍ}@C£Œ±Š•ãbá÷²b?‚ñ2ýáûïpcBDPÛçR£6ˆÉÃ$à‹ØÒlUà˜‡‹g Œ 9| –§%.8up=q)ºz¿¤VÆ„œæ½] 5|É| ž –žoNPGgKãêyÖ¦>kypò-vv@ª'¹•Ÿ #Ô¼sÿ¸~öhÔ8,H‰mq÷³á aÎrU òJã&ÖÜÇÛÜüûåóûÔÝÚòô± <}ð6• <öuåG$ ! Ë~؇'’±½ :2¨ÃŒf½¥!\Éð‡z—B cRå" Mªá£¨¶”xlÑY¤ôšcünA]]T!»È,Ërc#Ïë®s ýWâq½ËãB(ê@Ý 3Ìp?CøAJOƒÔ‚Ñ(P›Ï$Á§H¡cÂøÊ¥d>ÕgÿÍ#áCѺ¤(¬\#(¥èm€Ñì‰À’³ €; žæNp¯ÑêìÞ³ ÿ-± tà1£"–!¥dH)€„”Ör„„xò3†ÑŒg°~ò+†*¬ ¿bˆ¾¶â¯þ°ð+ƌѧ¿Å)ã6ÑPW…¤Z­¢:¿¬¢—endstream endobj 138 0 obj << /Type /Page /Contents 139 0 R /Resources 137 0 R /MediaBox [0 0 612 792] /Parent 130 0 R >> endobj 76 0 obj << /D [138 0 R /XYZ 72 744.9066 null] >> endobj 137 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F29 12 0 R /F35 25 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 142 0 obj << /Length 1271 /Filter /FlateDecode >> stream xÚ¥WKoÛF¾ëW¨î…LÃÕ>ùƒmØsH]X@:9¬Å•E˜"™%eÅ(òß;û’¨Zv_awÉy|;3œot6ŸÌ.™˜¨Hi:/§f#Ì26—·ÑJÕu™œ]Òb$Ç(bYžN±•ZnšÅPµMœP£ªwë}S=ÆDDÊ¿’9=ùƒŽIÝoÖªú·îY«½¥[‡•rÞP’4E„ŠÌ»—JË{u&çˆ1–ýk˜niÚ&©šA™W÷JÇBDÈ8™&”S”³|š ¥”skþƒÒ IêLÃ*›.`®dŒ3ß享½Ô]Lq´ÜaÓWͽÛÞü3^'ŸÎßÝ z³ð2UÓ²Y¨ÞÜ®ªÅÊ; ž×R÷+Yת *C뤻˜àèiXÁõŸ”å)b„†@•¸|Mš"œbî…vhLê(ƒTÁµmt81ÕÁ„‡ Bjåû…®ºÁÇ¢ªÛÒ6(Ÿ†m5¬^Í9aˆsæ/ê ª}’kU^K-×gUSš>GM8(¦Ô+¢8aˆK“ŒPlëÖ†ÏâZ¶z-÷EÒ«€%›Ä˜Ì…·yÚu ¼s*gÇê0E§b‡!\/‰”‰„åQÏjêÇf›^Ïêv!ëÙ]ÕÌ:›BЏ 5i !Î '')ÆP@§×~çªÇ‹RÈÉr—bµt"ö ÿŒ†ygEAN‚ÚÖjØèÆéüqò(ë:ywòÁh¿uO·­®Ë“ïþ 6Ž:U‹•õieyŽ8É9¸C"-ˆ•|óƾ™(ÒéèÍÃv4a*‘g/#}Øþ8ýf½GàûAgû/h(¢€8@¶“÷nÁÇ·4¥hÞV~ÙÁG6Òý>A°Ûüô>è^óo3¾¿Z¾©îâ’r$D–¿—ìŸdšK&Q•Qù¿x%ãë—·þþ_¼ïÏjÕ c«Gkg©[Ÿ‚ßo®|Ö]«o±ê;9@{>’ìðöç?_oº[¼Ÿë >¡{ÀCï„æ@sÄ84ŠDñµCA4ÓàHÚ0t ,€`FZSµ{Ô·²s»N·Ð³=ÛÀÙÊzZzÞ¸Lu‡òÂõðßâ>^Pä¦a×µÛ5­qµu‡~µ?ˤ|×aa·h§ÁŸ9´K·J§®[G’ýà}ª;ïEéÇjá•*£o¦ËzFÛ‹&±›@©Îj-Ÿ›' §ÑU—†$-#ì½7ßt›]3šYð¨söì¾Br;Ù”~£µ|r[{;XGC…aO†Å^Ü•kïîƈ ƒ›QÌW À9§¸±çÅ;­úëÆ­½²cOpµlÍLgräŠ`ì§Tç•j•$nîJOÞÙzs€<¥ž:ú%ذº h«œ'ñ׌ ŸqËúa Ûçv4¥ùj%ïêa¡gš D)ÍÒóùqzÎÒÝlág> endobj 143 0 obj << /D [141 0 R /XYZ 72 744.9066 null] >> endobj 140 0 obj << /Font << /F35 25 0 R /F29 12 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 146 0 obj << /Length 1186 /Filter /FlateDecode >> stream xÚµW[oÛ6~÷¯°ÛCÌJ´(KòàÉKÜØEfAÀHtÌM·‘Tï×ïð"Ûr•6Á¶û<×ï\H½[ ÞœO‰£$ŠBoµößGÓèYà#:›z«ìf´U1žD¾?ú²¼°/êJ¨ñíêƒGȟͰ7 ‰’ÀHülN&ö(ð& šÆIlŽœ¤Ñ"·Ò0ú 죄ĉa¹¸<±çWŸV–8Ýñ#©2^žtÖU£úÔ(±}kö1x$¸{ZËŽê’eËŠÖ¿ûÄ¿¸„ßÀÑ+ÍžRV«Ñ3³Á«Ö5öÓz\1mêœ6¹:„Û} O4—Ë«ùB¯õrçÕQ¨öÄ•æ ^áúk¼þɲYfž3KÖ¢J™”¼|øÅ¹*eS8š«¡ƒ—ö_mÜць Ô]?^]°\ÁI0‹ƒÿÜÆ$QVª ŸÕ°ëpQ• Š–Y -·ŽHU% •°ÿE#Õ§ D\2rV°RÉ“>çC²jÁæyëÛ=W‚ ž;{k˜%ïiú§àjs”5ëέ’u“¸®š2ëMí´Q-Ñç Usâ\°…`bhSѧ€¯­hÎL&©æ{uóƒFüÆ¿ýŸ§húBý 2w±OÝ+"-š„ÚîÊ:¯Rš—´m£Ó¶h Ø—7ÌeÕ–XU?{ôÿ[èÞœãÄKà>Á‘¾O&a‚âˆÌ¼É4„+ FrµáPþCù²Tw°]d`ÝÇ%sg¦.5Qꆱâ¶ï™zd̉,¶jcădTÝÿÚ—i¢Ž–åÕxJFó…³EmõnÇ+h) ®`¼¡ñd ¸\3À%o5Qå”§i%2-Ö“‚loèHLZäcV²f)×q¦ÔÍ]½{½xo ^Ö²¤ ¸Þö›Âi-ª æƒã Òý;J4©jC6%+Çú†'àô E8 ÓiSÚÝf9Ý2ñªÌ˜+ã»;^ruw§ @²|mçTàc„ƒ(êy4Á+à`ŸŠ¹o‚ý{¡¯kv£¶;Y³+D\ö*ø†.›G‹?Ó>F` 9fò[‘à­•™„Sx!Ť+jÑCj i† uÄWïÑÒdF{o]ûÝXäf$<‚ÛJA±i©¡c¨£î½€w.ÝÖ‹R±&†';ën§mlw0´‘¶|0ç”\e§+Ѱgmݶâ¿25ÿÊ}°ŽYpúc9(3'rXgÓי͆Õpz —Õ©I¨ãïfÔí=ŸPçç 2ê8_–ÒƒT éz/…úšÉº*åòãÁ‹á%O|¿ò’ÃÉ ‹Z¿`åÑÜ2£Èͧš‰u%ŠcÌ9·ƒlÏLF_LJ‹;f“«í8"£“£Á&™à4çcZ¸èÌüœ­@â{Ÿ$D~ÿi1økpsë{ÙÀ÷> à»%Ü=ÂÂGAP Â(nù`9ø¸S3ÑŸ+ŠÞé!n쇺Û9$ÜÆ£%új€@!0MãY> endobj 147 0 obj << /D [145 0 R /XYZ 72 744.9066 null] >> endobj 144 0 obj << /Font << /F35 25 0 R /F29 12 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 150 0 obj << /Length 1921 /Filter /FlateDecode >> stream xÚÍMoã6öî_!ÌÉîÖŒHŠ ‡twí Å¤ˆ‹;;(‹ ‘-U’ãqýïû%K‰’N'—½Hù¾ù>õíjvñFªÀ°Dë(Xm†LF°ŽyÈBË`•½Ÿ·õérñaõ6œ)žÈ` §‰2‰;­ŠôdëÅR‡áüzU »NëÆþ'Táµ;fí©²ë2Ã-îh-'‰ÙOk[µDåõ}ZÒÖ¾v{y¹ÿšöí3¼ûyÅŽuÞ:ÖoÒCѾ©ËÝ¿o¾ï‰à“‚]57ï®®ñ?{ÁÂ1ÅæÔ0û)oŽOH‹„Çæ3 Õ–mZŒìN1ܔޘ¨¾¥e¾÷†%cÞ¬ËÚ6—´÷˜ì`çCRÌ€ Øh„}uoëô£3à€Ð½ ë 8’ãYëG´oÊ´ú¯§îÌ>Ä[çi‘ÿáÄ !¿‰÷Ø¡Y%ùàS0#oiZ'Tséónúb÷û¦'ú7ùßú·|¿);]Þ‹/õà‹7" |¡1ð—QÂŒVq°”“†+‡ù=¸ “y»µ„ÉâŒ#4ÓPBâ2¼±'¸hÃŒHŒÇX§EAôÓÛrÁÕü¨¿Òñt‡ \ó>£u•Öéζ˜nð3oðm楳^Z8ÔhÞäûõ¤ÀaÌDر÷®ÿXJ ù0â‰# £·E¾oÚéçÍs2S lI”¼çNZlÉ•Nàâ (%È@EÚ4 “P!°Ïh1ÍI)fL9õ12Á21ŒKááÓ¶­óÛ…ç‡ÖT»cG‹Ž–ûrI NFâ-Ó0ÏO½6 #W 'ã&&ãL.À_1´Nlæ»2C³×«À<ýx(ƒˆð8L‚õnöûìý‡0Èfaðve+1*8ÂGÈx’ˆ`7“L­»ïbv3û©'¸ì).‡$¿ÅŠ8–›CdÈ®¦‡sEo!Ãù©Ý–{’Ùâ÷§tW“÷ÇDc) º¢„T_¡i#À»ªÒ5­9*(&}É0­÷7`¿UÄ"ÌÀЙÔ%5;L Ý9Á¶m«Ë‹‹ãñÈ€:geýq‚$‹zDìN»»µYCŠ\{ëàþ1o·¹_·´vIVr ÙR™Îÿy—R(%Ô ¥æ #»œ$Ÿ—u†i@õŽÞ?Uô=Ha€™¡¡óN Ô®PìmF§¹g@)Î{gÍSy ÍŠòÂC‹â¬Â#¸2W6²Êq›;ÑŒžCá+B͈ibŸMá`)¯øù/€9`ÿÖÒ÷P^Øvò"u:%i!j –Q®q4÷ÅÉS«óõÇlèM È™@$—2‘ ÿ  ËÎ/$ôA-!u %{G‘TЮhsVÀU÷]UÖí#e!\â$Rÿ‡ÊjíÿKmcx!ùXÛΊ2ͼt~ñë?ø†ÐaŽR±ÝCíÏ÷ÑQ ¹ƒ÷£ÇJártŽÝnûl×mã²u~ç| sšÒ £3¯ëÂáÓYYߥuyp@8aá,žäeÞ9©á¬ÊÛ ¢B@yòØý¼í8h®š¬>ä K Þ7ЃÈu’@ƒƒ6r hC¡ÇüÈzà\+ŠÎU]BÙ”]”(m¹^’Š„T½.±_h=ñqëºäþœniÿ^ËüÐõ°XAÇÕ¶¨GÕÂÖý´}lN壾‡-¡¢èÆ÷@aü¤I7ïRͯ®/:Lç8®ëø³ZŸH?倿êæë³Y`?‚æ† gí‚BÆJzSýs›Vî—Ú §¡T½¦JÙt‚ÿEÊHendstream endobj 149 0 obj << /Type /Page /Contents 150 0 R /Resources 148 0 R /MediaBox [0 0 612 792] /Parent 130 0 R >> endobj 151 0 obj << /D [149 0 R /XYZ 72 744.9066 null] >> endobj 148 0 obj << /Font << /F35 25 0 R /F29 12 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 154 0 obj << /Length 1843 /Filter /FlateDecode >> stream xÚ¥ÙrÛ6ð]_¡¶¦: €à•Ž’&¤§;öLgšd< Ilx•c«_ß]%Ë­Ó>ØX€{a±§^ÞÌ.¿óƒyL’0ó›ÍœQJ|pÄ(¡~äÏoòwÞ¦kªÅ2¤Ôûýú­Šªm:eà¼èÛTe»Å‡›ïçt¾Ò$ˆ“ÒªÉoÛ½Ú5õCi›f;éè9# ‹bM?Åúiÿ&­óRvç{ƒµ2Ëí­!½½}Oz!ë¬É‹zÛ“Amnã‹gk[6ë´ìþ˜=-›ìáá…–ê3N(OBN‚0aZö×úS@ü(‰ç“ó $×ß–>‹ˆ ‰øJ³ðv-ÿ»â¾OÇŸ­¸ÞÁãðøYr¹1ÌwæEPd'ÿD²çš–øÇ×uŽB^ôot`„¡”ý áñ‰ŸM.ŒÙ«¬î¤ÍV7Ý G5Oœ¡“jèê©o‘_~@ÄËïx8g}œ£¿/EBâ0ˆæËÀ'qÀŒ¿sÂÀˆ¿- Yƒûñ(ö®‹\èõ}Zµ ò#˜&4Gôß-6²"Ì2».ꈅá!$!0² PÁ„kqFL2A┄ ´¥§íš ¼O `ìÃÄSw F½Æl4œîí§MÓ!{©ÙgîŠHf)ŠZÉ.ÍT±àÀyK˪P;Yê^væ{÷|±ôEä©Ý¹Kñ€$‰UøeQ£_Ÿ¹˜$à,¶xMw†>t…åç´’ùUÚ¥ÕãL„%ÉÊ´·Æg3n.|tÿÖ½%`ž¿  C§À5X ÈäU×ÜïÏÈŽ ¹/¦¢ÉÅy7;4jB½÷”ò®Ç'H˜Wôæpèåf( |·“µùªMÓ©¢©-º~9X×Ò²©‚ÂÓq@ýˆï/sƒv–CÝX‰¹Dj‡PÔfýíúÕA;ŒSC[+NH˜8S™”ÑÔåÐÀzçæ_Ù„pžªTí[í¢°5Š7Í¿A0~ÌÞ'Qðds3ÈR'/ R²Ôª±žˆ5¶¬mÚõö£½JL*ù$ÃÆ0Mm6 }xCˆxF¡Ÿ17Xkˆ%ϰÍe‰žN™ZÌ'áSa9ÞÍðTÀlμóe“£™ãÏ­u>MNkÝAtÖÔ5jzè›rÎ!¬«FIÛù%I|’Ëz§YJvÐWTîÔ¬c"ãÕ“Í ±ôèK¹aþÕ—Cß]®‹úRÖŸLÿfg†3]Þt6è÷ý3UTòŸgh¦ˆëwNg‡Æ5íco?_Ml~:¥¬ºøCjèÊÕÅN©öùå%㱊°Ël[,ñ–}“¶à,C¦\c?ý ®Dz•C¼>Öæ¶Û­ö_¾‘eÙ<·ËkMvxêæcñ:Û=ä áÔ`žÕ—4ýÎ}ÛË´[qJC»o‹•O˜p÷€ÇXá?²­pqJ³'€0¥ZEi¤`¢¬ÍY5è„s“êaÔÂÜÑYmKúéÌ„úƒ ŸI‚AJ„ë“"A¹Å9$☛”¾ˆO;¶“~lì½:Ù·à¥-go¤«sºqÇìgû9W7Log‡$´ö²7=@ óO)±sïP]‡ÍŒ6›éPvw\™´W>©('4‰Üý_´­„¼toH^kˆ"â3îÆÊqšŸ½¾™18¤s6n´M!¬Y5ûsöîç3:ÿ~F‰ŸÄÁü6âpÃj&ÂØmÊÙõìבÍè—F/ñ§(>UÎÌÎŒ³1b à8ÂL>‡éžˆºº¹Kü ‘ 3endstream endobj 153 0 obj << /Type /Page /Contents 154 0 R /Resources 152 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 77 0 obj << /D [153 0 R /XYZ 72 744.9066 null] >> endobj 152 0 obj << /Font << /F35 25 0 R /F26 6 0 R /F29 12 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 158 0 obj << /Length 1278 /Filter /FlateDecode >> stream xÚ­WmoÛ6þî_a`(ì1M‘z KÐ)°¢[ X²D[ÂdQé$ޯߑGÙ’+wºO:RwÇç^øœt·š,?ð`“$ ýéj3õ(%Ü9LB£6ó/ó¬J•ºZ„”Î?‹VÉúæêiõ”I$ÑtBĉÕÍÅ5ŸŸËºÔÏÏ_i@•¨6׸]§;qûIÖ­ӭ¸¥ ãõ}†CŸÆœC4¹=y²6tDÜ”ÍÚè.˜G/áVH¼(¶&чFd2Z®îÉ£n÷™6 âµuuôÔ?ü ª—õÖ¨Ï Æ™‰M£$Z€ÁC-ëOb›êòE<ÔZlEk­´5~BëŘùlwø¹in˜ÕþNœ?aH»>_Å%Ú—2sqë"Õ(µBïÛÚU>ÅG&wM%ÞœM̾­Ã±¶B#<”ÉÈy¹ÏZhÓ a-gïi°PM™ýY‰™k¡w§~p;³ö”‰3Tª¡RÉ47lšSúŽÀ~ }i–‰FÿpúTú"Nùk:éÉà îU?¯óˆNˆœE/‡ôÉ*©¬I§³üÀ’iìÃBÃ> ž†>á±Xè§Ñ\¶¹hÏ7²Es ¯“y@‰ÇàXcôÇãÃÈ ð$Üw:Z¢cݦµjÒVÔº:àV. ¦eZ• E8:&AÌ9¶ÿ®‘­ãWuP£DÓÊ*@sJ ¬ûƽæ»ìà—Ã=òõ ¬¾urº³ÆGT¬ì3©ß·Õí¬Ðº¹Y.+™¥U!•^j¡4_"§¶¤9t£ ¨)›²·,Q:—{}‘‘LÿÜÓØ˜eE[*-›B´s^’j8@ÖäÒcñcá|ø` ,ÜÈRl}:òáĦf5`S«gØôjáÍ«à݇Žã:òÆgêü8J±iÉm¢¶YØ¿Ó!ƒ±áudc®²rt:BL ‰)‹œîµq›ôçG‡®›ðI!H¯Cßñ•»ZÜÐãñ /Dí®ˆÀVµ‹aŽ `kžÓ‚³l_Œ*ð†O-ÜŔΪ–n£‚P*mCoôÍ™ßnÜX7cIå,!>;2åIª¥‚ÉûÕÄT„N½)NàjÈ'ÛMþš|y¢Ó|B§'ð¯’ÄÁô0ú“„MwßLJ\T“ÇɯG7 C^=Gwæç‡õAþ½Í`Ķ:<‚é  ä¾Hdá(ž3L!Ìà÷o©©‰ê€ÿÃgŽ€endstream endobj 157 0 obj << /Type /Page /Contents 158 0 R /Resources 156 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 159 0 obj << /D [157 0 R /XYZ 72 744.9066 null] >> endobj 156 0 obj << /Font << /F35 25 0 R /F29 12 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 162 0 obj << /Length 640 /Filter /FlateDecode >> stream xÚÝU[oÚ0~ϯ°*M¦U1¶Iœ‰—¢NZ¥MÈÓibJDn³]Q4í¿ÏΚж‡=ìɱÏåûÎùŸ›Ð}{ @œ1„+@0Fc×|3Îös˜,i^•R_ƵS—Ëð`0$q/ào\>ïfe^eâ9ÜUâ¨÷J–yãûmþ ÅY*Š6öež/Q.’ûHFùMZ$iñØGª5ß·Ç×;s:‡÷(œuA” Nü Úlë´Y~Â'™Á \k]MF£¬Œ£l]*=ÒBéñ¨JãM&$ªv°åµŒb±J3'¦kHé¤|Ò¿Žñ{è!í ûŽ=\»ûß3AÈcœÔ1WWµÉ¤ñ=ÍÖ’Ú: ˜‘ѧ}8©ªàzú^HU²0}ŸÂx-S¥Ëj-$Üç{Å;RJtMÔFlm’×îM—[­’4Ö][Äs%b}óàÏa˜Ü Ø…Ë´Dá²-¥­¥Ç»ƒÜʲƒ«šèc‚¿£‚-Nåeò”‰iÿz_×™(õ cúŽBì”BtÌO(ù¥*-”ŽŠ¸êÐÌëc¿.Ú’Ö¾¿‘¦oáã>Öki;´fW®šõƒ‚íÇI´¶3Æi‘þD"â!Âið75êºýjãÌôöðRYJK59Ý"Ë2.Ñ«"œ¡¹–mVÛ‹3]8s=:>onÈwKœÛÐ!¦ 0Ïœç"ÌÌçÎg±Ä q0¸sÌPã¶fƒÍ%àäŽË‚n“9sçë>ÍÐ>—/ÝØ)IàfJšÅLIsîRDìOk ¢ˆ"ÕÒÁ¬dÔóÔªl¿nŸ#Ë¿™„.£ÈeØ`×±¼+â7Mê­endstream endobj 161 0 obj << /Type /Page /Contents 162 0 R /Resources 160 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 163 0 obj << /D [161 0 R /XYZ 72 744.9066 null] >> endobj 160 0 obj << /Font << /F35 25 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 166 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶û÷³Zs„ºej j(^Ÿ’Œ„œørâ¾S’ŒÒÙ¨+,59oxaœ„ n½ïèEXÝ6”ÚÿÊŠîÐ]Óä¾ù]§›Uröšˆç÷¨«šR,ãAå8Å€kà\x¿endstream endobj 165 0 obj << /Type /Page /Contents 166 0 R /Resources 164 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 167 0 obj << /D [165 0 R /XYZ 72 744.9066 null] >> endobj 164 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 170 0 obj << /Length 1218 /Filter /FlateDecode >> stream xÚÝWKÛ6¾ûWèhÇøêmÓ:Ø Ðf›õ©i²ÌÕÊÒV¢ãî¿ïP$eÉ« v¢‡Â0HŠCÎ73ß I’`ø‘DÒDŒ0“,)‹¿Ÿ¿àd·ÀɇFZ –œ`€Q¦I‹L¨8¨w‹_$ì“ÂFéx§w›ÅÛ÷T$iÍæ>É4EL+èd„êd³û¼üñúêv³þ´ú²ùðö}–%$C,Ô-H ÂDª$¥ L{ñÍõ§õÚ /Ö›A9è\!"ð¿`Äx§hÍT’ôV…¤2DZÕÃZÿ]˜[6uç aldx ù5)H‰ŒôkL\–豯(RJI@å$»»YO…éX8%iE?!Hsî=õ.ïÌ*¥/‹*ï:ß½oZßÉ«Êw`oß9›ðÆ(mhÃÚÜ7ÝqkÂÖͽoí>|¸}´ûÁ"> “HâhÑ÷ÌQ4ñ’=x4ëUÖbÊ{ûî¼Î«·yÛ™ Èó~u{ šD$át^¯RFù²ÍK×µ{çH×3+—ƒ^ø$–§}Y¹¢5¹-ë¯~”Ïà"B 3Fvìîšüa—`C<Š6Û?LaÑ*åŒ/o¬×aå¾âë.¾¼™B1¢Œ²Ò”I‚*ú“ŒœR-–›žFX-;Ûö.p}àìÁ÷z¶A;ëÌQÆô÷‚;A£8’\ʉcüî¤@ÙÙîRgßTemÆr¹?ò:… íòm欱 fÝ„=l4o›Ú6/z§‚;4°GËlJ´sÞQ¼ü¶r*+§ã"?OeÌåmLø¦.rkjøïÂ9l@$L9‹ÇeNc!¦ µ‰©}ßTUã`œ|hÜvâ´uøŽÖDmw.I›ºzüa&qT½­õ¤M;—Y¨‘o®‚ÁMS—k¾å±bÕ»Ò9 */‹”iÛXO+röÎÎX`AôYY_,»û¸‚´¹º}¦ºQ:­ëçŒa 1§›3•9˜Ú¢ÿ¤Œ08¢ˆœòâ•.ŠT yÕ[Û½a|áΗ³ÀfI2ù¥È”#S⌠f€œ6/ëaœ{‘sÖøõMh{Ü0?ÂfÀÉM_qÈ!ô­y&xËbT~iêYSÜ.b…ï9–þ™Gð±n¬ï<4]W†Œ…:Ћ½’§½©+ÚP¨”ˆb,§urÂÔÇ_MmÚ)Ó¤d¼ü _Ë«#”ƒ×ß¡ƒ˜¾<³i,…©®<@]nýG0pÆ©p/¦ZòŸMpßU‚qÁŒŽxµ}¹{ªËqy`é3wŒQ‘î>7`ÃpWéM :µÄ}‚œ\e8D³õ'²5ödLpɸBBÜDæRFMyœOSDê†[£gjwóGÿ/ޤÿY©}‚l¨£o¦—ƒ€r¸3l·ÊGüü|˜»$}%½#ÿÐÌkŽg hŸ<æàýÈÃcŽhM‡Ç\?˜yÌ6zú åT!MህrAõô$$âùŽRÕTendstream endobj 169 0 obj << /Type /Page /Contents 170 0 R /Resources 168 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 78 0 obj << /D [169 0 R /XYZ 72 744.9066 null] >> endobj 168 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F33 19 0 R /F39 52 0 R /F29 12 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 173 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶û÷³Zs„ºej j(^Ÿ’Œ„œørâ¾S’ŒÒÙ¨+,59oxaœ„ n½ïèEXÝ6”ÚÿÊŠîÐ]Óä¾ù]§›Uröšˆç÷¨«šR,ãAí8Å€kà\ŠÁendstream endobj 172 0 obj << /Type /Page /Contents 173 0 R /Resources 171 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 174 0 obj << /D [172 0 R /XYZ 72 744.9066 null] >> endobj 171 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 177 0 obj << /Length 1822 /Filter /FlateDecode >> stream xÚ½XYoäÆ~Ÿ_Á7ÏËvßGÞg±a¯K6Œx ¡5l­˜ð“œhå_ïêƒ9¢öŠlÂôQ]ýÕ]M’aø#™¢™"a¦X¶¯7¿m~ùgÅgßn02F²ì&q£IVo¸Ôã¤Ú\lþµ!‰OŒò9§¿_n¾|Eef‘ðsy“qC3ÚdœP“]¿l¿þçWç—/Øýzùí—¯8ÏGŒKêHd„–YN’˜êWg?ÒÍËËéj¸Y ˆÄÏ ÂœÓ(åHiE‚ #Â` €TJT?eU¥ë£L̤ΙÖñH.âJ„ÿ¾ø&Ò‚h)ࢌOS¸7Ó¸æTàmßÖ.ŽŽáºû8©ÝpÛ‰f¸µC½uël'öp¨Ê½ʶI„µMÇïvö›tjhÓ ½CI–9¾|˜…$kyœ?¹®Î+²s‚4g$Éó ÿdE𜀭™0 `týƒŽ]@ÌéÖúvÎå®rµ  ag8*w÷m3ز)›·iëÖÅAs¬¯f¤êÜ¡s=œ?¥c —ÿ´ÝŽãí ?çÛºls»#Ûf—“mv€Äöé’²ðÖ ^Jù1®ð¿Û¨f´Ë%ÅÛ×nGX/˜«lâïŒ,.D’ë,²r.cà›QòwpD@0Œñö»Öó¹Ë¿s;æ™ÂEÎ{’Òïõt‹*0£Ðï“ áI.[õàqŒè¹³3b’³ûª ‚æU8JXÅ­ã&LoÀRáp9¤•x´IÔ½‹Û1HüR?Ø. ïÊá6nÛt¯³E0d8Û Ö}Û%¶)âF}ìƒë„·¬m7¸ÂË Iâ&‹GM;/Ä;’åPÝï¤Ø"o/oÃV MÛ¥x/ÚýÑ»»+âüÖ;×noƒ\1øç§÷¶i¦˜¾9¦„TXϵÚ¢çÂz3w¯áþàöm‘øì+Û÷®~|9¤‚˜Ö@€€†‰íͱ٠¦QÔmï…c€TÄQðàøûرˆÀÔC“Ól×»×bQªE¢zÈ‹þö&ݳ‘RAdp“Nž{þÅEk+—HŠ‘£ÿ]xãaŒîè]WÚªü=äÛ¸Ôµà«1“G±ß‡\.æeLwç]ûî~“â 8QsLËtîš½=ôÇÊ£ ÛºsÄ?ξ? .¿Ü ~FKçã- ƒ_ø8},S¢¢ÊÖ×…]³˜@ZŠÑb_ì(Ïk†î¦¼PÄuŸ.ür*ta¥N¤ H:¼ß»¾o»Ä뮬ªHÑ…‚’ˆš¸æêC(¥°T•ý-˜¦‹«pÕšS2H§†ÐÑ^·ÍšOBëb‰&O)ûxOílÓO× QÑÌY–‰ R,óÉxw]髨ß&€®÷ôWkŸîOjuyåR¼«´¿-«â5ÄuŽgPƒ 3¾cßxÅö,d âuüñúI Bkú(I ˜ŠÐ(ãYãN’——Ï}´tO½ H;×øû.äÓ!sޏ …T“gÁ*«@”àŸ ùä«0¾8ÛA¶øê<‡vÃNeÀCW^ï¨oÇ&ñ¦k봛ΦVéEŠêU¬„!­'O¹²D½œ÷£P'ÚÔ9¦Žjµkd˜ F_¦Ž+­XêÄ›,Í¥d¢ÛÁµ(…nžÊ^«Ý'×C–I÷¡ûôÚŒ?)CxE&تzÚ#Ql/}…´ô -ö§uN„¹^•jxÙW¯wê\!e4;ÑùµÝÿwèì~-i H;J˜OÒûèW¸ÝŠö©×+û€öE†Ë“t—r¤¡S#gÝd߆l‡ØP q±;„6ÆÐ±Lø‘z~ŒnßPÊUá—§«ºU1(‡f\бÿ˜d]ˆA|ëKÇ"üÂgúé¦X™<ú¶ÒÔæÇ7)pW3¹>¨÷£/JêyxÁÄ÷´e3ÓD,/à‚°o{ÌËÅÏç^µÖ÷ÆÁïá}õî ‡CKyâo!ñ^%TkÁ® ’’©¿0Ø¡²"mû¿¢},(‹ûyQO¡‘P”˜g‰zÈ \6iSù[ zÓÄ_§)†‡ÒSOýÏPÿ§¦Y%‘&\}ŽÂ—ß½dZ"Š¡º=úöÄ ¼Fâ·'b Íê d:­õ8ôù)òËg ã'¨E³/Ðg#QhùÛƒÿŒsß•oo‡S˜ð\AJ‚Ÿ çÄðý@ z"ðiì¶Or |>MN ?€ê>å¾­œ!lúcW>B(¡K…<õ|G†@Aù5Gâb%øý³ÁÓ.ëê¦lŠ+ÛuöÞ?ãŸÌÀúOÌ'kGXÂïGè0~«]–,Ÿ1züµYÀ Áø÷*÷/v³> endobj 79 0 obj << /D [176 0 R /XYZ 72 744.9066 null] >> endobj 175 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F39 52 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 181 0 obj << /Length 1676 /Filter /FlateDecode >> stream xÚÕYÛrÛ6}×W葚±\I oM[Ï8Ó:i¬L:M2Z‚,&©ðb[ßRY¶ëdÚ‡D /vÏÞÎR/§£gTR! ÇÓåX…Há0G#Ì"6ž.>Ó•žœRƒ› AœÖî1_ÚϪýþòõ„‰àç7“OÓW/Î˜è æH†,ãFb\ñvºÝh{rO"*¥jOVU‘\M(êJ£Éi« mô¸µw&Y«.Ê$wQäé‹?%Qˆ°PĬPH9oî™-“l13·y” E‘N¥X`w(ìB*ŠZuª×:«N¬*Y¼Ö>±œE;±ÄÇ©’ˆ),@]‚”ôq.©³¯uœ&1¦záÑŽD¤¸Sb§éž4D¿K|‡IBøâÒ£HDPÄÈ¿‚¸ÜÄsýîí¹ÛJóyœ^ø¡'œƒ,qz¢"p|ô8èc >äýHû²M"É%éÝ×bã¹wy¯?©$ƒŒth¾Ð^§*BNøö*9âVJ eÄ÷ýú~"Á‰Å—ÒÜC‚ÏuY™ ÒäË„àÀwaH‘ ¼ÕýÛ?Œó‰½ÅyØ^T­wù²Îæ•«d$¸.⫲=¢íÞ7ñAãw*·;‹¤¬(I¹r×éêVk'6Îìé:+7zžœ•Æå"lÁ!ʦ~Øøë_m|z‘gºÁÚ~¹s°k¥®\UÊí§^oª­ûde×FÊGJyó$ù£ÛÞä‚Pô0_èe\§Õ쾜 ,B\ò'£G#ˆ˜å‘úÁ¡q¹gouUY9¨ÓÇê8Xh‚ÐX9H‡`ÕOXÍËj›ú ’ ò"$ψÐÑæÒˆ’Olnæ`s¾€8»Ü¾§‡Äˆ(EÞà”yP܇ïªW=#‡xrôEa¬ø!;«¿q¨:¶ø¿†õ¯?~w±;_éµ+jr"lMªü,ù±ÀF¢P²wë4+gp`rçÓMU¡xrßÚD’O¾~KðQ*Æa2‰žZ()A(T"ù3ƒN§Þ"|W&‡†'áO{öm˜ìdHá 4@rÆö?KÚæÞA{QÍÌL¶=œ .öûYyOCV†k]Íœõ³¬¬‹dv`ÔrÍ_ü§š¿/û9¦Ý/g.'fuà2àû„µ.­êMê0.4Ä| V@ïÀßšgwãëõ˜!μ°'‹òžYY=èüê³7#-ÓcT^0hBRíƒ|Y_ï­\<ª`™{ a6‰˜» YxÄ›ÇqËaZRŽ&§Œ©àͶZY†®Šºƒeˆƒké"®ti¿ñVx¦PH:ÛÎjˆ ý>.2ã%/9¡Š·§1ÍEÀ®!»®'PøªÄÔ?ûÄ^{þkiÊAHƒ2·;·ÚþY]êV³æy‘,Í/uá‚rMŽî]õl"f¾Š‹x^ébÀìMv "ùZey2˜ `‚KÝÖUÙpÿnzhŦ¢Ü˜ÿòdXrn&ÜÀõˆAÁí&/«Ó'fË"_Ïàö<…0éæâ}7I©Äu‘z©ÚQуå"’› 8\/Þ¼¾œzû1ÆÛ¹CIÄP¹ýLöQ,Ýó”èݬRû­¿X.‘XÊ”¢<½Ñ‡©†„¼û/ľÓ8êªæbÐù¬î6ü3Ú½¾}{²™D´S½‰tN›<„þ«d·Î}sä¦ÄÝUfôöFq{¨© ÏŽÝí!òhÇ8º²î Ù ÎfMjß ûè­ÁĈ¥˜=Äšöîdéäçî¢EãðL/¼±È¡‘¦Ø ¡ $Í,ÜÌ…Ï‹•7 áäXÐA—QÈ|ÉÝGAU˜d7+c³³r‡‰Š¡îæÑPÁ}t1RŠ´.XÅ¥•ÛnĶWµx9 âÊ®æ±SóÊé´‚ ’šFÍæÖ[]Ch®²-N_žÒ ÷0¯ Ó¨Ò­SO»÷dæAؼPÓÏ ebÐÏv–Ù_ \jÞ…™€šÇU÷[B^tŒvøkIS‰Û“Àn»Y£ß¦#“]xLÆ Ž€ÉÒñ|=ú:úð #<~5jˆŸ߃{±q3Ú‡tt9ú³S(Ÿ —Í/9ýЄ}Na¦¡ÖZÂ,LDªõ_VñÆöðH¼ùy…ïª$MªʾÓý¸ œÄendstream endobj 180 0 obj << /Type /Page /Contents 181 0 R /Resources 179 0 R /MediaBox [0 0 612 792] /Parent 178 0 R >> endobj 182 0 obj << /D [180 0 R /XYZ 72 744.9066 null] >> endobj 179 0 obj << /Font << /F29 12 0 R /F35 25 0 R /F39 52 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 185 0 obj << /Length 2456 /Filter /FlateDecode >> stream xÚåZ[sÛ6~÷¯Ð£Ô©PܶOnâlÛݦÙÄÛÝ™$Ó¡D8æ–"µ$e¯ûë{p£Hš”íÍìÃN BÀÁ¹|炃†d¡èBŒ0Sl±Ý]üçâãg¼È.ðâ§ Œ’D²Å=|`ÄM» .uü(.>\üý‚:k ´îSúþúâ›7T.”Høs}³à E,ÑÉB€š,®³ËW?\¾»¾z¿ú|ýÓ7o8_Ž—Ôn )œ$‹5eHbê–¿ùñ×+»öâêº;Ž–B#"ñdèSŠ2PŽ”VÄó¤Nà@L‘TJ;¦®o矉þZž ‘h´í¢wiݘìC•îýÚ1]$‰kwUv(ÌjM•^~¢TùÑ&mò­Ýì4¹vi‚´V^•;Ó4é—°í6-³"/¿„Ã’ž!ÖTJ¤…‰AXM… Rä ìx¹-Ò& k³¯McÊ6|§¥ÿ›—ûCë‡M[›tçÇímfoÓ°ccLسwt"=ÿçÃ/+&–—ïüW¥²ïx±& I H±<{Ný²¾ˆÔ" äšV=˜é¸T$H)¡ÃÒOXà°¨]¥"9/{Ôk°#)) Ë>NЃ+|í¥ýê«ßW/ÍŠáåÃ}U¯˜ZfÍ}Á¥4²ñyBGŸe!Sæ'\‚c#‚!¼g½+¶ÌÂHf™  Ò ¦çàÜ?BR K#ÕæßfÛzÂ7uµó£œz¹¯«Ë»<³à°?pÙaSê- a-ˆZþx3ÁQà䊑Iã—1†°Ô„UAβj£ÀŽÀ2ø †€ÃÒOçaÕîÐ„ÑÆ„}¥wH†•l=Ði”Üšù>oo#æ'PÈ`— Ü%2 Ä2˜E;ÓÞVÙØýšÃ~_ÕÑk®½¯BXHë°üÝl Î a†}˜&:>ð@)ûÌ.-Û|Û /® å„Aüð›¯ã)7UQT+*@f@n*@ìüpo‡Uä!­W à/‡Ý1ÆìÒ‡:üß íÛ‰`ª˜ Ç…ÀR9.þj6ÇSFÉ‚(ØÏAŸœ)HGòqÆ€%lÆ@$I¬’wq-;ÊÅu¤KCfµD„$zÁÁ‘M}Ð}mnÒCÑŽ¹¤6À³DœËŽâi.)$I eޏl¶u¾oóª|¤OH„œðül•˜gu8„Ì( ÀL˜k4Ò\÷‰zf®5„yBœjÈ Ú§ASÞ™¢Ú›yËS0§ì¬¦ïÑœ`TØ 6dôº>˜yßɞåÇLÒdÒômZŸýï¾ c“ ûª\q¼¼³K;ÕT°&” ŠmÑÑ¿³Ï %ÌÙŠ)9¼Ä¸‚š«y[õiNÙ Ç%X€H(ñ˜*oÒ¢™7Öù¸<ë—3ÆêsùºZAË}Z“B@/L Œ»Y—ììë_~ö3÷.ÃùßlJ´?Æœegý_fce#êƒÉ Aùòz¥!ÂúévíŽÖ%¾<3¶Žä Y¶+²´ÇÛ±;ž'8ÙÖÛ ïgÛÛ)üÆA" Yï/¦}]í.Ëì=ä)SŸÈ–KHÝFŸ.­ ˜ÑX¹ƒÞ!ÜA¡‡è¬qËŸìô"„rz±s¥±¦õƒÿl+ÿ3T4{Saö¦6&ü~kü§;j=lÛCš®b§ØBÁ¸o«ÌXùÁæTŸë®øá%ÅË·Æ¥èXÏû¿Þ‡ë&u8-šrg W©-Pû÷œuUù´KC­ÃyId§HÀ^'\ºGóDøeî;‚y^ßVå >“=39íÑ&_…«XÂ]dGÂáÌÎl]ÉîÇ©µûö%Ìüëç¿ùåÞ(Íw¶b•Ö—!—o<-5V(ÕVRXdh-;d <š†òú…8™ûp§¬Š;p­Ypb‹\rÎݧy $œÛ ê 9“=Œ™œIŸÉ_W„eZºú»>ÖýÓw ÞÝBû¦&°Ç«_˜¶p9Ú¬ rZó]¼˜Xª`40 øàòxCòønë4/Gó@‰9>/Ž$O¤5j¢•|Nú?=ŒxœAAŸÇËxé ¶·šíî_YÚ†Ê ’Fï®åB‰-ëö{“Ô¤7­9 ’€˜Çëê÷Uö0žcÒñ÷dE„«£kã`.å“7Çì×ÕÍüMš@A„íMüy} *ÁÖàuïî»®ÊâáÛ‰Ö0÷o‚ɰµ™Q¸)–£¶€—qˆÌ•ë?pî$²3¾+]ýXÂ*¡„<¡|¸ãÙðà›Û6 „ü¸*Ã2m_M‘Òy¡Ôºòûß~Èòm{ªÖ)±½9 [V0›'ü‰®÷3ΰPnV$ÛÂ(he›–~° Ńû=·k: ÞŠ!Œ¿˜á5Åò )ÊUhýuýθ=3ƒy w- ¨Öy;7‡°rÕšB’íÃrê H’~sȘƒ“š€U2šÙ~ˆØ ‚émU¶i^6þË÷‚`Aï Ó©ó´ÈÿH[ŸÒ•G§ó:éËÛ¶ÔôH§wªôõÁä)UÊë'€ ×!£7ù°ýª¦M}‹ ΂°qcëè¥ë[yähŒ´äã¤ÊӖéôÜ3Œ]ý[>Ÿ4Ž?ë2´×ÀiöUÓä›"@Ñìöíƒó#÷YäM; nE÷ö6/²©àWN#–b†È± >¯_›gB§(u‘?¶ú;mYTJ(œŸÖÊÈÏÞ›öPÛ\À°Ãd¤"ûCOEöÓ«ÈŽ\‚‰W‘[Ù©È~ê7»r&8qˆëÝ ÑÉ ²×¶à’ØG wÔ4]FV§õoï6štoi“Ïö÷•6^ÿZ„ƒ—xOtord”`|_m€•ÁSP$ê¢{Uú.ɾŽ{âCì88·ŒàtÜô}R|k_iÒ¶{e-³XÑ!w«¿ë ë¼Sm5føÎëÛ¿[ãzÿ(öÊ"®zx|v ?󯳫²Ü¾?…—žÑû>$ðoú¬·÷¼?õ¬` È¡ÇÿCAP«”¨§9©·%‘Ÿ?åPendstream endobj 184 0 obj << /Type /Page /Contents 185 0 R /Resources 183 0 R /MediaBox [0 0 612 792] /Parent 178 0 R >> endobj 80 0 obj << /D [184 0 R /XYZ 72 744.9066 null] >> endobj 183 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F33 19 0 R /F39 52 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 188 0 obj << /Length 3469 /Filter /FlateDecode >> stream xÚµZ_sä¶ ÷§ð[䌭ˆÿ¥fúpIîšËä’ë3íL’™Ê»ò­­´‘´ç¸Ÿ¾q¥5×ö¥Ó'Q$E‚üè«ë³/^©â¼H +íùõí¹“çNdi¦œ:¿^ÿœôÕÐ5«þâ×ëï¾x%çS¥N‹ÌÚó+!ÒÂá翾½¸R™NÚn¤O”™bR-M~žù¹?tm[W¥…ÈOº„õDžŒ›z •Ëqìë› ™%û±¢®UÙRã†;êöBgÉGœÔýv!²¤ZÓÀØÑsS¶ë†'—7pD\ë!½¢(R­…`Z6}uû$ÁŸ]“ ÚvÃ{½ÿñB™äÅ[z[—c™^\i'“×#uÝÕM?‹(ŽÎRHËù•t2µ¹3“ ¤'ã¶kšîBšänø ŸlNs³MZèLFļàvi.3ǧû%3O²³I°”s–çìû¤&M–Œ+nìn|þ9áBeÉý]×_(—¬‡È¶9r^ͶÎ_ )R%µ\žýzfžJ™‹‘1Qf©µyÁsve_n«ØL6 j t,MìøéÝkî騃Øx!LR\U®O‘b²X?©Ì¸Š"tj ¡žIÊx¿«VÝzzÛ”#Mh«j=pgG]3"£*Ÿ¥¸ý•×<éKRD Ö™KaÐÍ•Ú%Ûò¹Wmì@âP›±í©ƒ±]ßíª¾¹§Þº…#ïújäIþ¸0kÕÁ@˽Ý-=Kz¼yýæ%ïÓ­ïqã%½Þv=ͨðð”Û]ãÅ”'Ĥ¬M iƒ †¸˜´(ä1yލÔS³´‘ÄëO±‘*u"¨éÛ²ªõû®ÜEö¶4ÚLRènþ]­Æié’[Óf “X·°×L µ¤û±îZzÇ{>IÎ&e°%üNÖiæ \4T:ñj Ë×í0–튧ˆíd|=‡r4BêÈvm÷ÍXïüÊ`26Ó[dH? AHýhÉ@µsþÛW(Û²nö=~nsÚžsµ§ 7èÛ"6ݾY‡é@µÑŒã³ä'éϪÚ1¿,ª4ñ¿,k*–5ÞòfAž©ðl™0ÖeTR§`ßqß·1e,@Ó ãžãxV9tÁ•ßtÞÎÂKÙóÄéùˆ3Aq÷SŽØï¢ý._•«ßƾ\Å,ƒËPäò¤jãÀ¼Ý‚Môîáj8j‘ ±U#N6‹;ü®¾6¬çæ]=nhIÞg×ýãiõ‡xPH5(¿Š·OÔöî‰û£šrž5…]ªâË ìr¬^¿ÑŸÌÌ™qä&•ƒóÝÒ“t]ÆÑ¡ýìƒ=z½ÅS¡!Çh€òˆ‘BôBÀH,ȼìïé·ó@’¸Ø¤„1ìÊ¿ÂYûºâˆ¥„UÐÌÔ†+ŒG ¬ö}O>ä N>øÊ“—åj'ˆƒPX–;(îÆÖMuØ % Acó»Àv}äªfv_y]ÕÑÌùÉáPèsÜ™™4ãÍý·àr«ž5$C ÆÆiñ@;@ª·(måõø9¢?:uη°»¾©‡ñ¯ :[•»)Ëók,§0_ðdlÑ—É:ås¯n*7 RC úŸEɃB 4ÑÃÇüTäî∈½ÊTXaòYì€qSxý6€s}d‹Ý¨üyš#$LòX],Ï@yžL¦ÚåG ‚œƒ=œLZÍ'h€½´>t<¼©Ã žÃªÛU4v·©ZêäÔ…IÞúlGHùi³¤‹åL!<×pÉGJKÍi ½<î|:w–' Lj8Åz-­9: ɽY@7KîÁÛª©J¾:û݃Ðp û*¸R@½1e îv²¤DdÚÃqË¡úp«Ç ÊAà¥uP‰ÈÕR¹†XØåKüzxñªÜGÑÔÜù©;%eZðZ²se£$˜³·GLü0”ª%ßËXÖÌG©Hìó!†Ï<Æø]¤yîŠO‰”»»hè—ÚÌ=…8!ô3ÖåƒÖû0†/$6ñC`¹•fî«n} ærÔ…ƒ¯ZuýÚ›.¿KwØ-²>Rì޼\^¦&³æA®Xû ‚‚LnÒO*€/åÙ,y{qKK]tã0ÐSos¬Üá0é§>¢š÷óy@Ú8j+˜£Âßõ×é#†ù:0–ˆ¿ ÚÌF f Ò°3ÔÌZ=±€ÌG9°ÎÏí§¾11U†+÷!Z˜ICýä© nMâÖÂÂí?6ï¨Àv"ûd xV¥ÿd-†Á¥Jó,äŸõϨÎÅ *•RÚÿã+J*Žò1ceQ„ͧ¾ÅÝÌ׎šËdAikÿœŠ½þÍÇ\¾åbÁ¦Ä7 ±T§Ó\(óDõ®P¡4CšXÄ/ˆ ØÁ,¸ƒ"‚LótÔß <þ] ¬ Bræ³"„RÀIq\lñßX2oø\°Îl¸áë$ØX&ùlAq•-NÆU ºE°'*¯àų° x×!ª¿«¦f¢›+æÐÚ†jPš>š…KªTðp|¹ýŽ€´ô̬2ÐÏ¥©+ÍŸI¦iÀóä.’ié”»â)‹Zþ‹–ò±Únj„žVü­Â+Ëk¸ç&X¼ oMeHi6Îf A=ÉPON E&+Œ×Zú`¦[Sت„¥ËÃ-{¨îÂKÍÛ>¨¦\òøxLÖéš‘ K«?åÿ“©$¤3ÐOy”ŸŸß·SéC0Ä‘  7¨Þh“.椓>a3žÅw˜Å'x¶‰BÅõø¯’§›uyDéB^¾‡}3ÿxâR áÒx3÷¯”̧Ҟd =%=¸p²€bŽx3ý> QQ{iopçhpˆ’r Æ­3Ë0„Fïv9[°YA ›mçóKH~ƒçΣé{žyÃTòÑΦºjjv¥~Œ ± ´Ð*uGoºfê‰Ý®ü}BýÈÃ/§ÊcO¾ùþr‰™èߊ‡€é›ßâ¨ôà†ŸQ2û©˜®^ôÕ[P¼’±$#X#žì:µÚˆ§KŠsó«ÃrB9åYÃÌÇ’Rpœ ×葤”r![°p¸Ã$‘ý”ž²@«MÝ,«”É£öªŽjð|#Û®½úOÕwG—ÐkÜÙËë3<v.ðÿQ£ÓÌÂsµ=ûýìç_³óõYvþÝDQˆïàâÇ¢çÛ3iziÎÞŸý=,sß_Íú T•vù£ª–àØ$ya/®Ó)™|½)wüŸ\ž,Jy¢,ñ7<áÜ©­ìò_+pjQÊ£=¨Ž‹­›r¨WÔ<¤f\N?<¡qgfýƒ«%endstream endobj 187 0 obj << /Type /Page /Contents 188 0 R /Resources 186 0 R /MediaBox [0 0 612 792] /Parent 178 0 R >> endobj 189 0 obj << /D [187 0 R /XYZ 72 744.9066 null] >> endobj 186 0 obj << /Font << /F39 52 0 R /F29 12 0 R /F35 25 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 192 0 obj << /Length 1217 /Filter /FlateDecode >> stream xÚ­WÉŽÜ6½÷WèØ X4IqsË`b Fâ$žÄöÓbO+ÖÒÖ2†ÿ>EÕÛh–>±X"‹µéj½xý&“‰!Fq•¬·‰æ‰f”ÐLgɺø°üûæçÕ§õÛ×o¸9YÅ‚hÖôã~ßvC¿J9Ëz¬†r_9œ]ÿö«²eYƒ®vÍ`‡²mzZ#—ëCóg X.‰ÒFGû³…ë6•íû,J‹¸to;[»Áuxz¿w›ò#¥ÜEp_wåf‡€Ú&BZÇÞ  k ·]1º´p%r’rÁ•JRƈ‘’…SKo]R´#XB¡.›²hëW8ÛwíŠÉå}Y¸"nØuíx·›&³\(N(g,^ðÚm=š÷’6rJ˜1<®F΂õ²yꡈVÙô ðè˜ìÝÌRžçÓʺ-Æ h ädB ˆ9š(.dX‚dÂÉÇLj·ÇwEùi=öCÜŽu„m[UíŠËåײ¹‹[ܰk‹þ‡x³S¼tB#šm×Ö7Cçw>dA¢µÌãÝ>RIã"uºˆ­Õäú™âá’‹£)6Ãeª¡þµ¢7ñ°ø½Æ.¾–Å£„öö·‰„ø«œ­B0d†„” bhpÛ‡\8[/.V™^Λãà`ÂdÏñ¡‰4Š}'>¼¯U.­ÊÏ>ˆÝ$@ør’:W9Û»wm17J-3ñX‚t0åš0)ÕsôdÄäçä¼éœ»ˆqvÁVŒÖÙÛb°÷ud”12A{ŒLPãÉ^;ئ°]êß¿AP6q§Ýï1Z½Éížx˜^þâ|\ßû,é*TñhzºÔ&ÔHÔ.ô箬"à¶©¾áR‹Š¾¶U®JÏ)ëÇÛÞyèŠ#/Ì£2¤u!>…+!ƒÒãPnÆÊv8'ÀBÉÛ‡’0¸k(Ý~›ñ„Œ‚»°C¤Ì×_N‰‡úk»Êú“î=…¶¬ìmÕ‘<oÖø ø"0ER8Ä©Pü"#õíØmb–¿È§ëU~µJ3ñìyá‘£‰ÈòÉÇ7×m]¹a˜­1PÒ)ŸVïðfÏë§×øûL‚À–âf,‡ˆbo7Ÿíƒ—<39Ô.3Qú®mîmUÖsôh±eÀ„86±†ùC|µ}ü0DInŒ¼ˆåüUWä b ôTdÅ7ŸY^þµ3‰MŒ 4B(mv¶¹ î“Ðd“'ƒÀõ‚ˆa×õèÿð%ŒHª€,Ѻ>ôs(ÛÂî±åò‡ÅBîŠc羌e¼ñW›îrÖI:§a75U‡ìuÞA’¯9УD‹œdÄ™gÇ*·J¥ñç‡`9$3/ϼü•ÅNÈû>°Lç§ï}4ý#»|1xĘÏï¡WIÀœôÁ~f×wÁê±YñÆzWm_á(b36 o7Z3,[X4Ãj؈ý܉1´KÁKP@Õ|ˆ•ÿ Èdï`ä%XNªñ˜UOAÙLjÅOë…ï§iÂüÿŽ„&LÁ¸©_>ѤXÐäí‚’Ìä2ù “ØS× ¡òiR-n̤°?=1t嬸Y>i8Ó‰à„1ŽîÎô„ç_ ‘ endstream endobj 191 0 obj << /Type /Page /Contents 192 0 R /Resources 190 0 R /MediaBox [0 0 612 792] /Parent 178 0 R >> endobj 193 0 obj << /D [191 0 R /XYZ 72 744.9066 null] >> endobj 190 0 obj << /Font << /F35 25 0 R /F29 12 0 R /F39 52 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 196 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM!ÂP „ýýŠJ+my{¼Z’!æuË Љ)þ>%„œørâ¾S’ŒÒɨ/,5y_±aš…>zëé•EXÝV”Ú~剮Я¦Ë}÷':«äì5ÏQ1V5¥X¦¶ý#†À\ÀÇendstream endobj 195 0 obj << /Type /Page /Contents 196 0 R /Resources 194 0 R /MediaBox [0 0 612 792] /Parent 178 0 R >> endobj 197 0 obj << /D [195 0 R /XYZ 72 744.9066 null] >> endobj 194 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 200 0 obj << /Length 2165 /Filter /FlateDecode >> stream xÚ­]sã¶ñÝ¿BTÆBˆo yºÞä¦Î´“k¬N2Éå–h‹­DêH*>÷×w P¤LŸÝ™Ž´\,û½ ðE?¾°bayÎriåbs¸ú|õûùb{•/~¼Ê™÷F.á#gÊ;¾8\)ãÒÇþêöêW<òY£Õ˜Ó_ÖWß~fá™7ð·¾_(/˜ôÎ/ Š ¿XoÏÞÿõÝÇõ?/ÿXÿøí¥\1©ŒÀ B1eµZ¬„d&üöæW$½úa= 'í7ùÿA…1§¤Èaå(÷šå>× ‡k]j½+I~©ÇÄÊ3íæèéX¾o¶‘ò‚­Ð̧#éf_t]Ù-Wºì“– mѸ{!“ «ðÌ9KfÜ4õRäÙŸK¡³²íª¦îâA~ä‚•”†9 Zi‹Æ}&þ™–[ÞèyéýÄ¯Ì Ô<4ÛÓ¾9϶å§<uÐ>Ïjq‘ºrKèû¦ë ƒB8êÐWõCdƒz‡MweÿX–5¡oZJ½û8%âYQo‰zßlŠ=á>>õ»&îkîþUnúŽÁ—·iͺ2 ²àn±âœy­)âêÓ¡l«Ír%•"Þt}ä“Jg=ئ»ØØD ³®ü|*ë ª;Ù¸­6=x§h«¸ÇeE[F¦§ã±iû2’Þ=͸Er jð:™û·Û›—€ï¼6Ò0b7ïfˆB§øàæ÷ì+ž6žq'ü8J‰uÿ{:b±RB §–<‚¢uf×yÚŒ`sOÿÅ~Oº2Ø”>Oõ"ºoš-}Ïš…[Μî fqƒY‚¨Üyfµ1Yf” \|—„AA6`Žn$wúØ”s¯‘zcbÿËœ¨0¹ö#“¿êÁëȽ‰–Š©¶«¢QêâPž%Ü•›9yÅàbªë¼±g`Ï”ÖǶA5ÿ¬‚%¤¥öê¡-ªš0¿}ÛìéƒÈ)•ÃÉ6¸„²F&TzÜ•‘ „IG¹”7t„žúϰòëßÿF|«킨˜ð¦„¢PÂ_“¿“^“ÐìwmszØa»(¨²(a0DÑ?.9E5à½pêËî»åJç:eÀ¥Ë¡Ú !T2fð֌ɱ »³Ï¥/0%Ü9<НñJ”hl/•hj8û%¥dRçI2£Â0 "†[òlMF‰P‰Aðhca³YpÌØÐèKrŽ÷ÌÈ\L½SîËC¬z5mC¤„.hªúÄ´CJ˜˜7†ü‰KÔrÎÄ&kNýñÔÓêä8ŠK„FˆUøL)!¿­’¯9G¤x²xÕýoÒkI'  ŸË,±+œ¼ošS¬V“x%TU_”­Ô2Z&–èAT0óT<^,w¯Å;˜€s¥Ç&2 #ºöõX?LÐð¹ÈnzBM"p²·ª7ÍСV úìÚÈÐ<ãýÛòS½8í#q˜¬Šý‰NR1„Æ[Æ“„ä§Ÿ†ñ3èµj. gM52„™J½HM{Ôšâß(cdõR¡ÐŒæuO(¡R¥(Ú%wÙà MeXïªî,‰³)jBÝEw@HŠq[Y€-m,µ¯ºž ÐBáôí.Ée¹B¨ìJKD1°%D8QÒ)R†S°J›U=­N]„.:8`†{c¸D†»j³‹¼ÛHͧl¡Ù÷tºœž®pz—Ÿr‹M¹úçÏ7×´’ €€¡òk24UíLÆUŸÝà°ÄÍ…Ö Gp·YP xZæÑ»¦ß%ª’€AÚgæÁ0<›QÒð¡.:Z¡¢†eÈ4ÏÚ ~¡VG\C´Ýi³)ËmÐÌeÐ t°Ã yaŒsMòMpÔ(¡PW“¦XO…¹¬Ë¶ˆ÷ X¡ZèÁÓõþ‰Ð±†—<ûýÖ)\˜Y0 ¥!oª Љ“i…6ù éÐûêó¹])êïOiý|‚ÊpÞ;öª4#wi-¶¶|¤ehq¹ê§[¸¦Tí³ÍU {¿OÍ¡ŠwIi&ƒcÆðT3Ú%$X`€¹Û§T Ý0Q=gŠãÉy2òÞÅÕ‘ãü.¹„n”‹7µ%Ç Êñ×;³QÃ…6XÊÚ(/—GØÔµdÜ5-s]y9k©¯µ6>é^w(ê\T;æÕ`Ñ‘dîƒÂÿì ¶º!qo›âøK[áÞ™'ÁœÆ ¸v{ð ˜Íø¯#?ÈÜJÁ˜ä¢Ê"êPPÞÓ¯ôR+{yÇ+»4·hp(y¬~urŸŠaqêèl4‚}p2žîF”à"é™ð’Ââp0àˆ JŸÀ·¾·¼²¬1¤óR»¯ÏÙÞ‰7<ÒéœIÎåôéfÜÎ/o|¥†ÑôÒ Ç:@È€MÜ4~‰QOJ¾k3«ÅD]e™Cšã\5Ó˜4óÖ&šo¾‰™*¡¾=6¡9m»9ÖX«3g>çã©ä·Óu²Ü}³ß7X¾㨑ËÍ•m ®Ñˆ-|(ž¦½³ã»™×n­XnàÿÙc·ô0:Óc7÷^ Ýácæ±{Äèùs½õ0‹-ÞÒ…7÷Ižÿ‡¨D]endstream endobj 199 0 obj << /Type /Page /Contents 200 0 R /Resources 198 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 81 0 obj << /D [199 0 R /XYZ 72 744.9066 null] >> endobj 198 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F33 19 0 R /F39 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 204 0 obj << /Length 3379 /Filter /FlateDecode >> stream xÚÕ[K“㶾ϯPù²RÕŠÁƒx0.âµ]eDZ︒*ÛµáHœc‰”Ijg'¿>Ýh€/‘šD‡¤æ@ ôëëçóÛ›?|%å"‰-ôâö~Á™ˆ¬ÅÂpiÉãÅíöçåŸWB-³§Çg˲ڮ~½ýææËÛ¾`ðÇÜÄQÌõÂ0±8¶‹Íáæ÷›Ÿe‹í [|sÃ"™Xµx„Os¡ «$J‰ÅþæíÍ_[‚ë@qÝ'ùù9·ÖFF 5äö‹ì>=í›1—Bư&·Wd³%ù Ÿ"ÚÚš1Ÿõ¦ÊM^c^%L㉚HÇZγºðn`õH‰„ž¯äºO“XUS  “$ÆÇê±HÙœØu¢"p~E±÷INð˜ˆHÁYXü®,²Y‘_ÅNäg<ŠdJäÃsL+8È&«Vk¡ØÒªk•÷ôlv¡ãîŸÙÆéðhók.MÛXA˱Èåô¢„¬;Ñ×PGñ‚|¬‰¤À¾gås-{âq8#>‹iÓTùÝJ°å©É®(!á¨òâûÍæTÕ³R2<2–]Ó}öIžËI0)ǰ²‚ã0ä–ø¼”®Æ`OLcgäÔç°Þì²CJR¸Ç˜”n²†^áóÃéà%„Ç›¬~”ÒÏHI%‘êªÆÔ#yIJZÂx!ž“ÒÕìIiÌጔú^’Rúá¿“R‘ï÷éÝ~ÞáÅ&²†©k ©GrÂåÙ$R ÈhÅ£XrÊ_¥ûú‚Ó»“=A¹œTŸË ‚ÊëàôB«=y÷ö SlBjœ«ÈJ PÄ-ð¡Îÿó>û¤©NÙ'4~À¸jm5÷Ã(ŸR ªÀd U¡y:f³ˆTsS^rÂ8×JÍ«AGñBà“  Œ'ŽÁ[Øô¼\‹Áž Œ8œÑ€>‹ßŸšã EKwžÔÊ‹û²:¤ŸB‡pÒÎ ?l—M ^˜HpÀ¾à½s‘+‰ØÄ]'}·Äã.ó‹ÕY•§ûü_yñ­Ö’™åçOHåîAÁ‚¨Ù&ÀPË–Û^‹ÚíãõjsÚã¦Ü‚Çq#sÐï‚ÚéÔ®´…6K<»·o¢· É!ö·e"euØ¿‡Žp^ì`þÅÙ“Û`P#†hî¾*#¸±)‹&Í €ŽJ-£ ®rd§"ÿý4ë(dP,‰_,„ŒÎ䬅ôI^Šf Œ^jŠèlÖ@®Ç`g!gΘHŸÃ¯þÅf‰.ì56­ ô1cÛùIxúcwí´ØRãœ'Í, )õû‡¼º¢ïüè_„ ìim¡‡™Í.+aᪿòk§Jlde§@çÊZǸ7ßN¨2yÆ*™²Q ²lë[¥w;‡2­¥`±I,FéËñi³OëYÐ¥4ÈÎÆòšjÚ#9ïÉ•I"#4>…¹‹=Eó8­¨&Ék¢„d³I/Û´IAo!×OT7„·Ü/˜Øà“b<¶HÔL=1”¬dv¹©²´A¹»)%=리²@%댦ó‹Œ@–h¼ÒìRT¬÷yY aGÑ€IÐð¼³–a6æ<= z¿]wïþ¼»÷›¸™¬Ž>\¢ª×ï.&Ô Ž^@6rEuì(N¡K¸%Sý¹¢b«wŽÓWó*y-.{9bsF!ûlŽ<‡´ÖgÕÒzå³Þ—b£ ™U¹òã&ˆ¼GH÷'Šâv™†±N·ŒËŸj§¬ð;€™I?é±EÀ9 2䯡á-(òX#†ìF ”&£Bvr<6P=÷Ù!+d‰kÏt7»²öÍÇ]¾ÙQs[Ò0ç>±ÃÛ×s7ѹóïÎá™›ò@Æ ¿²ºN0.IÉ—hEØÛ[i‚ðÎ7þþ—oiø[JÎÍ„ ]5 ù‰h!XY¼ž‰6s†x°Ž…^þpˆ¤õP8€Â)4ünhHZS' m¨Ç™>ôL±*û Åþš…iDÓ0Œç‰ÓÁbÄÊO 9Ïlp›~õóúèŽú]6Ý!rjÉ\”Ôk\Zk'2ì¡…¡áõˆ^( JCÛç«—XeÌ´øñœ–Ž.W¼îÍXÇMi&ÌPQwUv?¥Ô>që-†ùfãã!¢€* Iµw3±>¶»édh^ûòá!«^jM¸H{ɸï9³&V¡™ÜÆ{‰Pèn"­(èá ŒÆž ÔÍaò~OªH“¥ØokúÒ4è=ÕÙýi&UÔî5L¥ÒÝ#ýØùWüÉ×>Å*3ä¡™_Ÿr-ø½Î6䤱7<·Oàó z~¡–AxdÂo³&Í÷µ?¼¯CöêàÎÔõà^_*ri£X$A?õl}0ËèˆNîçÄ•¤iuõ—s¼-ÓãÄÒ9­Õ œ>£ŒŒç#­uX-ÔqÆ\ÈÈ$mRÒ»ÈÒýAQbLp²Ù> êãÔU%˜ e,>»Äf9°y­“‘½¼!½ \/J…T:ü'Ð" ÏÚ;æ]7 ¾u‰ã„L ¤èÚ$Ýn¦„ ÍØ†'ŸÁ+W•¸a Ï ã4¯3Ïö” ÉD?øå{9i“}ùa“µ=A,¹ÇÁ±æ~wØD˜£ÇË]裴ÆÇ±]޲œWxaî1éàP1‡Ži*8':bÌÚž†œªÜÇæ}¹I÷0 ~·uˆ>¤ñöê—å´:s)¥Í„:wiBÅÿ„:›{ô1MUÊ _­}"¿s@‡ƒ'RA‰(]G€ª±R“bË ]mÒ‚/d<ØrÆå…/rõ¥ëć„Þ`x¦›æþôÉO-V•Á·Òýð»§©: ”%l³emé›$Ú2eÿ–²S® Ѥ¤ÔÞ.wéþžjäõ!¹jjj«r“Õµwùš-}ÐõÃü¨úÜ %‘:߯ç$Gg°wå$O³>tô;eÃí­Â|°.÷ï1¬9« »~v¹{¾l“UYôÛ+„g²æ¸ý&$ÛNVbúž«™†|Æ4¾ `r°O¬dÄ<¤Äœ_ð×û´—ݵ“2°½Ã³Gêþ²'v ßeÙ°RÕ¹Îs?-ijáG+ãµ ë²møÀòz¢ü~ø/¶qå–…¢¤z¬¸¸ÑÛ¼è× F;µ¡ŽPÂkçOY™`x×Àøðœ?.ØÄg‰ßEµí§C?Še=Öæ`g€¡l[ ŸL³ÐV;§”_ƒú%v¨>ûîýL ¿²“ü?4×áÛºÙö³¯V“ÇzjËð;õŒap)á`ìèÖ-DöulüíDlô²!‡ßP7~Aõ(㪮ñ— ¤©:~ú˜(‘ÂvúXMúm4©³Qƒ tçžß®àª¤pÕbÇs¢%~ÂP ½µ@ôt……ÿ‰PÕ.¥÷õo0û*endstream endobj 203 0 obj << /Type /Page /Contents 204 0 R /Resources 202 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 205 0 obj << /D [203 0 R /XYZ 72 744.9066 null] >> endobj 202 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F39 52 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 208 0 obj << /Length 1884 /Filter /FlateDecode >> stream xÚ¥XKsÛ6¾ëWhr •±<>OjÉ*›¦‹Meš†|±¾‰5>.ˆ,‹ÀšÔ0‡æm¨iI 7B ü~ö6–«°¼kð&˜ÐÿiËÖ¶6gg‹ä­êzo/”,·Çﮪ8/©‹I‡¼ï ‹,Lø>ßT¬‰—9ÔimñJH:¬õ"@Œ+ < íãÒØGµìÜË41ò܇a°‚–°ÕÅ[û¶ê4tjܯôa?\Y¸w¢0 xÖJá‹ï_ù$grÆ-½€èš:.c¾’Áh d(ÆÀZ¥<üe@Gð76ÿu»ë†+ƒ,°JŒXÅ=VÙÕîИD+ÇÙÐíVÖ;<Å6´]§öHzu'ÜN_ ÜzCÛ­®¨zdæQžÚy´ðŽèñ°è8Xd2øË!h² JÀ ÙâY)÷z¶ýø‰J ƒ‰î·jåù à[»1Ãà* ¨ë`èªVö°‘F0yÉ NDÎ Xå$ã0&@¶n[D9‰•â{ ÷?·µèAAàP0ÿÑóŸµ×MÛÕJµ[Qð2®åÓ©%_ƒb—ÌvËÛuXÃHžžühë>N»‘¤(íµ¦H¿…-ΗŸ³…”0{à ®æÝîáq!’„T<Ül*M@žA»aGÓ>‚·©õ§™ØËL‡Õצ¾iR8æÜNÄ]{¢”ÑPE‡Uð>‡ù, ×pòÃ)cÛcæ<ÃÇȳVmmAÝnê¤ëæZ×€ÍÏÜÎÖL,g·nØöÄɲb0Êve7>´ùo€´v>¶™ûøÅìg÷c7[>˜÷[ÿ r!ãK–§R±gç…¯é÷1vò j¸þüÕ‚‚EÎ8"ñûvС¤”¿-¶'maŒÔvÌ>¤ayŸÒÄ \™õÑ%²½«ˆ„‘-Ì÷xCµÀù½­G„ÖS«Þ7wÆ@–‰™tEȰÕX0t&nF¶ƒ<æ$ec/±á¨¯Àrl+6‚‘ÑN’2ëÞÁhÊäþk²„úøÞ—’’<Ïù¤3³ž<Á m]jq_ˆ<©ú˜x¸ipèµ~ûçØœ8•ï8u•À&ÅáàðÛ¸ë€N…±!ºÌãÛÝÍÛ¾¹9Á­¬÷îrÏLî-•Uçäèo‹péå¶»á²߯éÌŸAÆ:‚p¤”Oz§÷á­HÞ³v¾u·WHx¯A·`0DîüßB–„,.¼¼xÄ!ßìõùÌÂ1³9xW¦„fð\mf_f?Óy5£ów3JDYÈù ¼PÂJŽ6³4+ÂK=;›ý:ŠYÂþåDÐK÷'ß4U€žÂ8Ì8+%pÈ"þÏÌA¯È„üßÿË,9HÉ΂WþŽT›endstream endobj 207 0 obj << /Type /Page /Contents 208 0 R /Resources 206 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 82 0 obj << /D [207 0 R /XYZ 72 744.9066 null] >> endobj 206 0 obj << /Font << /F29 12 0 R /F35 25 0 R /F26 6 0 R /F36 32 0 R /F33 19 0 R /F39 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 211 0 obj << /Length 3525 /Filter /FlateDecode >> stream xÚ­Zݓ۶¿¿Bo¥2'ß$’éCâ83N›Ä¯“¶IÆåI<‹µ$*$•‹ú×w €¤ºØ3=ÁÅ»ûÛð‹»›?%åÂæÖ³¸{XpÁó’›EÁyn$W‹»ÍÙ_—BgõùqÉYÖv›åÏw_ß¼¼»á ?¾àÆäZ–‹‚•9Sª\¬÷7¿Üüø3[lnØâë–K[êÅ#4¸µÞÙ‡&¬bµ‹ÝÍ››¿G‚«@q5%ùÅSf ‘\Ù9·_ÖÕi7\r)8Ë™Tæd3’ü>7¹àÀÞŸýºkŽCÓžœ(×y)Kx¹QF^çuáYÜß(¦s!lF.Ï4Ð\M‰³:¡ÆÚ\Eáx­ú]Ó×o ž%û˜•ÀŒÑúªà§$<2×ê’ɯª]__ûÇä(ö'\ ›ûŒËWË•,X6t§úv¹RŒgö>øÁm žmª¡¢¡¦§‘Ÿ˜f]½>u}ƒæøë’ƒMîÎ0ÌÁºê Í®zôDœô܃Ö/ÿ+©v§ºÏ—°‘ÝÑÒ,ÛÔ+ž ýFãi¹ÙÕ±ò$¤“¬#\M†]Ô»z_àxSFŽ/(¢™P; ÆPì’ÚíÏã´™Ît§i nÉ /n¡d¶ÞU}OëPàsÚm¨ûþІ!Ûj 7ÒFÀ èï×iœ”à‚x°H¿q"Þxª-ÑàŒA6ï)A¹QBJe};g%HnöoÇ]³n—ç#²B`¨ý­ EªÝ­W5'”Ñå\C» Hw‚+ ]ýË©éêMî7gbÄ»áI•ó² 0Ÿ˜«åŠ3ƲÏP/`9¨-Ì*9ˆ¬Oœs& •%Eø¦uniB¦¯È Œ"@誘Z@’‚¬œ àñ å&ΊçÊM»{‘ ÈÁb-DƒE»š¨u$FpËuçp Æœ#H h 8l̳øp`¥|ƒZHn³}õÞ.ÒFIÑ.ú¡:¬ëù©5C_ï|»B1PtÐìÈHqø¡í¨0Š”DÛ\i]Ìí“T̹`]pB*  ¥º”JJ(<—º,ŸHEk’5êã@Œ‚4îÚ5ÌÓãÖW›:7ÚþŽ¿¹Ìú9÷g¢xrð•¤À:"À÷5ñq—†%t𒍄gøê@ÛpÑ ­¸ë$  Pá’›¹™>uCà\ EàŸ@˜ ãÑÃÑšk6~Aˆªj˜²W˜:¹R€@ínSå¦`}¯È£…‚oïïëî/w9ÀÁ)¥)¨E–gÎtÜsãÀ¦£p  "@%ÕE RQ¥q²Ácx¬]èƒ5»Áœ)Æ(ÐsM§‹®‘<:•kaâ9[`¹*£-sFGPxW K4~ÍCë&>8t>F·ÞÖQMh¤=øÆå&èE8?äµ¢Àœ1q¶AxÓ 9Êèù1ÑP¥— >ˆþ;Q’Ù“åäܱÎ=¡(ºˆˆ&†¹’Ë!ŽÕºþÇ÷¯n±ã2¥tB–f”Žñ ïA…Õw¹Êaˆl¦ý Äv ÏÁέð·¾ùôJðÉDõ\3¯/É ‡¦?L]&ëuqÁ¦|'Ü©ÌvgZŽT@L]…~¸Î €Ö܈e'„XÂã86â‘cW¹PF1T%ó4"/ ’˜éÛ›õ¶ÞûDÏ·Û›6Ä)O÷õb–¦ßOsXæÍ m]{¤ H–‘×£gª 8â£g6[} Þ\¾ ¯ïÇðý¢*ÄB¯&‡á¦?åk€ñÁýûò‡»½~ùâ»/_z’Óã5:­P+²•î‚-œ¦.'/øIf:)·EÌó#AFæ–39IJ@a1DAf]U¹¯Hy¾ÛÒã}]ù‘º¡Œs¶U¾8âÁ—‚ÞE³‹`$Æ îœgÐy(ÚAcTìð[Ÿ“B/¾ûy#ïIø’$ùNhÝ{𤱨r5Bø¯6#Õþt<¶Ý@‡ÀP(.V;êƒÚÃÀˆq©Jˆ‹/»®°ŒEÒàúN«µõþ8L«²¾‚§ùˆ>ÚÓÜ×eâ#Nv¶Äÿw409;Íc‰GÇ f}Ú.q_)ò‡ÿë¶ë°DʳÏ|ÙÈ19ÛÏ®oS%3T”X®¢ç €vä±1°È0àˆnÿþìŸRj Ùp·ùH¤J$[m÷ñ(ÁZÃEÝÈ$J¥¼‚áS‚DlAˆZE‘êHh ²¡ãø#”_iY:D×áª1ýæ‚wˆð|BÛ£‰¸†+ÿ¢+›U}Jj¾,âÇãuÑ©ï$à…‰C½¹Mág#οy•.Š+£!*;ÑÇRå46œ³þ(œož”ödÎÇpâ9‡èj17N¬õè-‘ùzë$:­ëÍ%”RYiçZH¹î³jXÌÅáÕÐ¥r×:Ø jˆ#—jhtPCŃ*3mÒ5ÞŠà´±f¦æfH'!=t: S{ÐŽ5 öÓI±à‘ϪqÐU°ðŸ®[Òw%b£v íñ¾†nzºLs]_fÓPÆ)O‘ã]åRÆ±íÆƒc€¶C:å.áè .\ÕÖYç©Ö•»ÃVL  X¨fì&öÄĘ?WtQ ŽE fl´`n‹Á-¾Cu>Þõ†)c›{ËÀQbÊ”‰Ä¼T9*èxÛ”ªºJ‘Cb¬yßnN;¿(Š«y¸`7´ÈÊäˆ1¬€e€AxÍ5Óó™n:£Ÿ^26»a‚çé}&®€šñá~À!Aê4 l* ûéV½n½/J¯ÌKC¬Wº‚{¡íEÆp%9œ=+—Yê•X?M(x/g5ElÖø=Óд´€–Ÿ±kÌÄ‚_4iC-×¢ŸNÝ›ÁsAÆêñjL³P…K1Su^ÐmÂZÇ”^â'V«ßÃ%µ[;œÌµ’ɵ‘HûÚEoÚê˜Ê8E.Œ ¢ˆ–ìõ°‰q‹×Yï8|¬9-V@nŒW‚€5éz4}e+ï[˜}5|W1A ¿ L€{I’†$\nÈa¾¨Öï‡âçgÒ_H³!£ ¼ m¬·PˆŒñ F-aézX§]aYäÌr…ñÎy^ûyaKñÆØ?. •{<ƒ€â~8ÞJwß% 6ùc‚(gË%žÜ'Ÿ¹-%ËÎ IYd›>Eø"– ~N aJ¨ Uq‘•¦QRÅð* ܆|ˆ[Á¶ôßž†#~¹Ï+ fê{2¾§yözü²eŸc¡ž_1fQˆÜ؈býcjK€•¥~j˸‡Èšޤêœ`Ñ#z£ ÿÐ5H"ù=ƒÄÏ,ôÅÅuÒ¤ÓÉ,àrÁ\ÛfžS©]M#ȘÛM½Zü@'´óOjÿ¹US¶p_ÃXŦ;‡7ወèO½Cp?~-H›í–¼ÌÞèNŸŠ±Õù)’}zùýè±V9D¬âƒ¾3å•Ïß0˜¢¯µ¦F ãJäœ 2 !0 g–e/¶Õ‘Ž´(3ãnäÄ55„+!?KÂͼ®%.¯4q‰Ÿ„(¨å³Uh­AjáZ–¾\êÃAýë¾—endstream endobj 210 0 obj << /Type /Page /Contents 211 0 R /Resources 209 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 212 0 obj << /D [210 0 R /XYZ 72 744.9066 null] >> endobj 209 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F26 6 0 R /F57 215 0 R /F39 52 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 218 0 obj << /Length 3037 /Filter /FlateDecode >> stream xÚÍZms¤Æþ®_¡oÙu <ï€]ùàsœªsœøb)q*¶+Å.#-¹]Øö”ͯO÷¼À€@Ò%[IJU†¡éé~æéöÍÝÕç¿åü:‹3ÅÔõÝý5%IÌ„T× ¥±âT\ß?­~·fr¥ÏkJVuS¬¹ûöê›»+zMà^SEâTxˆ¤1"½Þ®>\ýô ¹.®Èõ·W$æY*¯á„fƒ‡þ^“IÉ®÷W·Wì%F½È(”ù橾ISÉÅXßßèûü´ï¦z2&bEäÕô_Ð’q')M§Z¶Û¦¼i9Ö).ÁÆ’_9L‹"G%1aAc!«åQ7¸ß#o—E]LßESuPªûãNƒ+ÑM"³î)Rg 2ð†ç8¸‰ ³£ÁþÿÒÍß¹[ÈÜÜÖ=í$Z¬¤«H6ùþÔ Ÿ”låÌkðsdjQpŠPÒÌþ¾ÚâôÌC;hkÃinÔûÈ\y.„Ó!r˜¾Ñº²C…ÆmPéâfqØegÇÛ]}Úö|ã^Ò¢|(ÛN7ÚÝ3Aå)Ö9qÑÈÒñ_oßÎP6,)ã,us~µ–råô,ΰ‡Ê­}«s êt†7œNg{{ ‚F†ˆõ)ÜØ3g$K¬|_ï÷6ô¤ª¶èñ/ÜbBE‰1¿bÂ2ÔÚšà{ºô„B¸¦nUwÝœpI4Ž+oˆx\G àÖ¿ŸfäˆB>snìJ¶ûz³ÑͯɜHy,ãŸ(ñ³ÏÞ#êõš“ÕùvOVŬƒnj1¿°_ÖQ–Áÿ™°Á)¡é`$:ƒˆfÀ—YšŒ½ø=/’p/ÞØƒ]<¶öhÒ8ꦱ¸}š”ûÜì¢pžÍÚ΢§;RHì7†nü£ÅœŒ­¶ù¶z,÷{{¶ñÂò²¡w\¶º›M|æÑ’ q꜕ú™#+óÂPg(0MW‡ülOŒ p|(ÿQ[C©ã08æ~sàeoªƒ®:ÐX0±úÊÎkÁL{'®¬Ú.·´Wõ½“8»4¸§œe³ð(„ʼnTÂͪ7×ÛΊu V³m4Æ_tJæ²ø~`Ë4ãã8ü^#¶‹MœsOf½e]:™7zÈ0}à³Îžr¶5X¨9m;@"ãwI»0®3übéý-ZK÷,W=ƒÃXéŽ6”Á½—kà}¤e´7ñ§r8׸'oàA']†Ò·yÕ Þ¸ÛǦ†gíÂà2wSŠFY°MZg pö:ZÌÁÉÆ­#ßâ¾È7{=K—·õÁÙL[n/›ºBôµ.©§”R8X1ãÖ‹*æ½ËƒYP´–‡2â¶<÷z`ðñ–r³#†JÚšêÚ|]užfû‚˜‘``‰K0Ò‡ˆî5Ÿ*ÖëúpìΘtøŠ§JA6”¥Æ6sÆ–®èRÒ@»Q±†NÒüóšR곘ÓèîÔT¼;¨|î£Ïx+›V/<6ºoÆ£Fx{Õ‚U©ü k¨OnJ7Tªv£t†jf|õF»\¬#JYÝv &EÈ?Ì1 {ôöû5€ó«wŸÿå÷ßÝnwúàlRŒ€ñî~w•=Dí ïU¾ìÕ€ÜF·üDP) íçÒ(§ªŸöšd—¡ÓÈŒ”—dÿµÀ?ÐP>)âC-”NQÞ3ì°ÿ\hžÝ~{ŒCÀB‚LdÍä€n± ¡é@°† óádXÈYrƒ““‡ý/fÁH,’-$QÉ«: æGí³ óB/Ðéô"£Pæ3N( (wú.u:“ÝËéÙ‹|AOvU"˦z.÷:á…<ƒP.O©zU³´¡D¥KÍN/3 …Î4c€x’ ?IL(7ºoÖû6§›w~‚¦ —(ýç2Ÿi…zÎöŒzÇ_LÇÀñSÇqÐ;>Ô2RðC_ÄÙ«n—wöl›»!ks“ôÚ#ßÀ ˆöêO?¼õ· ÿ H{^"±.XÛ©n0ŸËm,#ù(èû¬u}þ³Ð…‚šðÔ3컼¾¹­óã *3¥|Ô(†=1Û•b„Jç(FËЄWHª.ËKÌç ©lIæÝÍél^LÉ›S%°*ùÖÅ'HÿµƒÀЀ³"(-Ë}?ü¸+;mšó“LĸæèasßÔ‡§µFBh3¢"µ*Bu U˜¯HS<辩 ÚòwHJB½ÆÅ'ä*M:ÅT‡œqà ¡ÆÉ«>J±8KÓE–ö£PäLã36§Á‹QÇ=Tü7C_w.÷á§„`ÿëÜŠ½ØMã³iñ]éÔ˜©ÓÌ’‰ h ÒÔñÇÈÚ²”èJŽ 6Ãv(¦Q§¶çQ. ?èÃF7ãoeÀ˼žÛ]]b±ûRßê']m'9ä¸q‰¤ë) IĸøÖ|«¼(J×ò+(ÿŸ**U¬ˆHþ-{ªÔ™„oòÖÞp:ĘÐê¡¥Óä{7ã´1¨ýHg9†¡ªÇyËÂ~•.Zš³&¯Z›jÛwbµŽ2-ÈØÖ‡ƒ_'°."׫¦éNÛP6ã˜y›æxšXº1:õ½{#w}(†ë&oÎvÔ®Òµ–‚>ëó$þÛžéø˜U¤IßÍZèAÁ^ODÏDþƒ~% HqÒÔÃì ¡,ÜÒ~´3¼µ¨{Mx÷µŽ"˜¡Žã«±œõ'Ê-%ëîôö½•Wö‹W†ýž*:Uå³oàÚ!Ó=½°F¼—õÄñ,àTœðdúõÞãö'œírÜÏ>wÂ÷ñABS>”•A\õ…r¯¦_£“ù¨¡P3–8Å”™``ÆçG=g 7¤ÿ.íúOûf«–P\†;³µ}Ù7G'ͺ3 †Æ‘Ÿà:‚Ê\m©.GPe¦1e—zUu(!LH¨„ 8eH¼Ä(9S™‚"4•JÕsµ!Í’X¦Ÿ_NK/ñy-ðtó¦Z>ó+µìK*²XANôªÊHˆÊY²ø3'3 …Îý&n€D‘ L>Dæ¾/—Ë^§<ÆO‚¯·§ï"-{}9£¢‚iIBÇ*ÎU…ƒË/¦âàò‰Šã¼»wy¨¢É»® ر&2ZÀ6®= ¼ÁGS¸rY5õ,Gå…¨ë™cØeÌQw8³¡Éu\V€O™H×zæ~>Â*%|x=Œ#õ´§íÎÞ1| £›óìhÐn}vú&oµ‹q`úí’â)þ,"ï a˜^;¨årìo É&ñÊåA¬è,Ÿö§=Çó5 §ÖÝØ¦Ø©} óÔÿÙÇÛÿï~ë‹5ÄÚŸ«…~ë$Y÷Î4¹Ë´m†€*¦¤: Ϩ„½ŠV{mð|²$Æ!RSÊúAsí@ðIúÌ— ‘“8öÿz?2îW÷/ÿ&`[endstream endobj 217 0 obj << /Type /Page /Contents 218 0 R /Resources 216 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 83 0 obj << /D [217 0 R /XYZ 72 744.9066 null] >> endobj 216 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F39 52 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 221 0 obj << /Length 2315 /Filter /FlateDecode >> stream xÚåYmoÜ6þî_±(P`7Ȳ|—ÔÃ}hÜu/ms Hƒ€ÖÒ^]õI[{ï×ß Ii¥µ6vP=Ü}E g†3Ãyf¨—g_}'Ä"!‰æzqy½ˆø"b”P‰ÅåæÝ2ÍMÛ®Þ_þtɈŽs"™Ò ꨾·w/²Ò4û7]“•7^èã„h-¢@ÿU4é‘"IõàâÖæ×Ïý4&Z—[LH"Á¥°ž(xÏ>{æ¿Q©D/F_~¿=H^3.H$T2•=èH®5dLùyƒì$!T‚M,7ì’MkäÚ¼ £º}À~àÑGÊ¿ûÇaOa<(]³Ë㟖7‡ÍÏò°w©­»OiLÖ†X| ìv¦³/Ý8[(â‹‹¦³Í(òÂþ†#ø…÷›–D! OØ×-yaÒß!-§Nc° j|Ð:Ö„F;RÊv»¦ôrÐ 3¸1"bˆˆT3_—\À!ú¹ËÒ]nLXà¡…Kløó>ÁŒE`zÀgk1u XôöÇW~Êr(œÃËOí8Ù0ëöý °á‹ç… y”p©Í±-j¨¾ŒË–à Ӯ!K•s3€s;W³Ñ)@?®Xƒýž,¹¡Š’Xüÿ”l’A-Eã©Ñ=Â9wUHN0ؘaZ$¡@¡¾@¡‡Xár ²ðÅÇwV•~Ò…¾ýùG?¨®þƒGõ¨R@Ö¶B$û·éŒƒ„Îx;õJ”žý}¶èÁž‘Í]92‡ä%th¢à_ÕÀ Úuõ®úŠiŸaB%éóâÀ¢CR1-}¯«<÷ík˜ ކîoqX5}Ó¬X¼¼Ù¹ÒÉOæ¨\À*èë™ó{RÔÁ‰ÂN*rZüÛƒXvöòòŒ¶tÁ KõÂBÀ1¡JÆ‹´8ûxöî=]lÎèâ‡3JDéç:QE?ìƒ&?{söÏãz`¹ó|q¯qfKb%=ó§ø[{mvyw¬'°•"QO¨çÀò=9‡Nœiq¬g›6™C{6¥qwi@+XyR×EP±8“t@mÂ̱Q{žë1S¯ì¤=¢1d;Æ‚AŽˆ£(ÀŒÙØfH³À“ˆDR†]Á~ ƒ`?éÿËMc è'šþT•ö¤ïŸLŃëUœ¶‘ƒçÇ*ž‡ú”õýˆf‘?œIÁÔxOcÈCk÷îŽ=θ…ïöo«u È¿q±tåyi×¥áïýÌ~‘¯1SoÞT¦žÉðš®u}€¦56 J-œÕU °JHsÀ¡‰ ±— ‰ZAüžego@íIXÃã…‡ò•蛟WB-¿yýÂmºµEH—pÀ¬ç¸„„7Ó=Éþ4ò÷0´ŸKFb)Ø=Ü?Ý1ð?ˆés.™øó÷/‚0~òþJE„?ßîë0[]/¸‚{–wçå¶ï4CgæšN@ÉÜö>,’MY.[,BP¸3ùA…öpÛ3`ncÊëÛˆ ·> NÄÇ{ù_ƒ½îú0‘Ÿ‡½Ðÿ)C †8”|è ×c–3È _#&! #hJ4ÿ$ðº»mÈO§åÀò59Ó„3ÀÛ©š§ql‹X:Ui¤“Gá.UPK'Ñ)Üíy®ÇLgÐ P9f`% =EET˜î¤Û5ˆä,zJ·XÎ!.‡ØŒ§:~¹9íñ'Späñc §€;x|¬bh Ókîþ|7}–ñ‚«Æ×zŸìè^,+ïýðŒðÙÿLJ¯ÊAë”Ï@š—%$‘ÆôAzäè裴9Ýe¦¨ô¶ÊR; P¥D<æÿõ?x4”ZëÂ1@½Ê‚÷¹r ….ïoñ/ÏÉÁ'ÌU‚ÿâé莎nf‹]ÛMS|(U [\Ùæ>¦Íü’@é*9”YSOÌ6Ã/½Ö~ÜÙ2µá§ƒ  ‘üè§Ã7^.„Ó=]ÚÝÕÚ…£=®¤°›¥¼ì¯‘û+aÙaqˆÁ@k¹›± O×\ŸókìÂýµ›q-šñc .õPX‹¿ªàJaåÓpk³›Áþ6»Ùvë«þaˆ?rœxA¢’tð| péøfÁúõˆ‘O³zúËZrè½¹¿ÿàr…:¡ËóÐ!@-CÝy”»Zj΃Ò¢N'ÔsçÕÆ}ÅèlR¢Úç»CÈ‚ˆß8ü(Ü-Áÿ¾ð`&Ÿ¨‡žõ?Ñ÷½endstream endobj 220 0 obj << /Type /Page /Contents 221 0 R /Resources 219 0 R /MediaBox [0 0 612 792] /Parent 201 0 R >> endobj 84 0 obj << /D [220 0 R /XYZ 72 744.9066 null] >> endobj 219 0 obj << /Font << /F33 19 0 R /F39 52 0 R /F35 25 0 R /F36 32 0 R /F29 12 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 224 0 obj << /Length 1521 /Filter /FlateDecode >> stream xÚåYËnÛFÝë+¸)@ådÞîâÖœ¦® kQ ÚÉD)Ñ!)Î×÷’3CQ ÉŽ“ÖÍŽ¤./Ïœ{îcFG“ÑËÆ"ƒŒ¤2šÌ"E#E0ÂL±h2}_åiUßO^ƒéÙQŠ82­ÕéjYeó¥Ý×Ö[‹¾W…ÖÁúØQŽ—´±È(ŒÞz7²ç†#¥ 3xñâï1Á±3ßß嘩xZ ùåQN˜ïý¾ ÇtnÖ6 aƒ5\d„ ­õ«å8¡Çwg³ùu\fµ»½S§ùÊ"ÿñ>å åÈ`©À¯B’rñâ«ë¢¬VÄÒRˆç͸QˆpÕNáŽÒ>ÛD>Œj¨æÑøÅÊ5CRKòߦœí9†¤[œŠü«Ò¤{š-‡È¦ ‚ùóÖ·ˆ*÷ê›ÑoAtîé አÅÈs¯à aÂè!â~(çêQ5%/–ó!u¤µ2ϼzDÞAvŸjÉ¿eù~3LùÿrDùœÀÊúã~STYÝZ(*vnË…äzéÏ•x!‘¡l¸”wìºÛyiÓ¨hoêëÔGç£-‹'¯éK;O¡Ÿ?ôçˆû&ÜËó½ê'„!¡øso¬Š#-${,ÿ…Ïûa•æþÇâ Ð<®*AhÎöfÆ÷š•é°èÀ÷zè×áaQÃÜfY"9NÆ8>É  9OnŠfÀO¨ÒñÙjqiËj`ü)d˜Ð­›‹ßÇLįÎ_þùÛ›‹«k»Hšw3çÖÝßp¹ô¾Û›´ô >¿¯¯‹åÆËÕØðcTö‹½Ê@Ø@àÒüÙÓ˜!BÅ–°&×-µ$¾’ùõýZÌ|òÜ=Ø 'ŒPpœUÎıߚ€D§POÜs+ñ½×ìÌ=¬žÊ6Z¿mLlÙÉ€UˆÀàÍ=/ÓåÜVíÊ{°I'¼†V½ƒ ýâCÝkZŽYŸ0ÏŠ“¾Sv£±Q¨?hâ)J\Må"­wžKDðó„ï¹À¨)¨Sobüa¶;äO°òm„pò>Ä“&[•nŸ[—]:ÏB#­l™¥yö~ê&)ŽÏÚêtç~Ζ¡;·ÅªÊB‹"ˆŽBÍ¡] %! Ò¥NΡ6 }ŠJhgY2ϪúG_Ó…ê“°—V¼ÿv6àÐH½·Ãû°\”Ê/íÃ+XÙÚó¿É<ŒÃ%ÜÐê½N~FsʆoÂVB÷hh|9½®ykîÛ«f“$<_¬*oqé RÿƒmZ¡»n»ªw20~KÖÄ÷UõW¶ Pt%¦!T ªvye!·8!ñ‘ÇtÉl•;8áÛe±ZN¸ømuC…’ëÁƵw[–E˜³Yh±]n×~<Á.í\«ßÞ>ºv&cc×i}9X]&í[v{>Z˜*hwd¦n7öø—!t90 AIÚ±eúéÌñ%Ó¬èêĬÙ0Íî®»2ú’èN=÷N¼ÿV¨#¶TÇl§ÇÇÇáˆs9ÏmrSB~­kxÿ\ù3#ãW;æ?9Ÿ«Ë|(ã8¨&ßO ™@Rîú;`HGØv û秲ߟà7­éÙOîj„ð~Òsä&¹ùŸ>§ˆÀØ6áíÔA÷mÂ#Þ«‘ *Âþ¦¼ÂÈendstream endobj 223 0 obj << /Type /Page /Contents 224 0 R /Resources 222 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 85 0 obj << /D [223 0 R /XYZ 72 744.9066 null] >> endobj 222 0 obj << /Font << /F33 19 0 R /F39 52 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 228 0 obj << /Length 2038 /Filter /FlateDecode >> stream xÚåYY“ã4~ϯÈE„K¶ái–‚*®ÚP,µìƒck&.;X6Cö×Ó’ZŽñ G-E-o-4-öX6B‡Ò{vÔsƒ6àó~Ð9 µöl¶F7¦*¬ÊìÌu~Å^;žíTàL—ŸÂK¼MíŒ (Óì0Õoˤö£ùÏÖã52QV.úúüRQKgw›˜Fh…cÛôl—ù%È‚5Úa¶Ðaî£û¦®œe|yǨó'gp^žZÔ¹1áòœÝ6YBhÌ9Þ#Ïѵ.IáV¢).´ðºOŒÁ.U öy§o[0È"5E˜Jã@-ÄœR[C5ºtÃû¤»Üì¸ì&ÄfºóνÁà|ÛÔa‹•Id@-uyÙöÚ«”Ó„$4ó˱jŠz(]ܤ 2 —à‚ô “2†2íÎ'ý¬-—îî8#iÊ$.<·ƒ§„'öâ–Ñéuî4ÁÊFÒ¶l e%±a®jïÀ0WõdÙêÖ]Sî¶ûó@òv*¡² á’d(@ 'ÂUÆçwÕѼ,«I\ÞÏÜyÍUh Ž?üÜñ§qÇ!Ô\BOB}ùÃR#b8 ÷Êêáp€úE ÔC<µUˆüÍpÜk\V!ûÓ a雫{dº'wïÚ¸Âu¡¯6éS[„ˆqíû€71Ï{½ì±“Ýá—Í2E€%“jÑÃgøH)iXhs®»“”]’,I¢×HFMÉ$IB øðC¯£€ØxŠW,ÍÝ8%#„¬÷ÍSÂ. »ïZP=d„Q›…g—¨¥€³„·(¼\ƒc%“è iK›Ìˆ8úú’9Üßrã7^ß­x\&Ó+Чl…Œ9uw­½±ƒÁ §/ìúìҪܜý¡.³G•%6æ¼á)WÙ.›fVcÉó@6s…8ˆÉ$£JÍîqàÉåÛ`fY)H’¥â=G“„¦T^!/D‡I4ÕõrÀìîb‹×©áæšf·û±ž0}ÞôUÞ‡ r•O±v1¸Ê£y(²!g¡úŒ9¡Jmܾzõj¹ú„z×\."dn­EôˆLõþ߉[·öE`7Ö ðáÿIø„Ü1 gÌë-„þŒÆÁG’à6aI²÷[Á#,¡üAý¾+eŽˆýj¯l°Ù X–é{YΕ)[T©«„®JQ«ŒwŽY«æÿ#f‚¡>ç¸u˜}žŸÿ—‘Öaô ·X¹ÿÑvIÇ\ŒÑøÏèXþ‘ŽÅ¿¥ãT–qõ@°ýgÔù@vðŸ“L`þwå¢M‘ž †?YRüÉò´mk½ø<óð/9n»~ÚžÖc­;óÎJ×»s2’Æ‚½ï•« ̾çÍlŒ/\A=Ø™CŽ´PSÚ¢Ñϸ÷ øúGh¸ßmWú…?q.nÜŒÚhèÄ~‘+5àÛé~èW>@/_z$„=VÄ ]`tÀ•š¼zjMx¾ƒŽ}Ñy °ˆßÓ—øûbÈ™ʉÑwÃcøÇ<¨QIzUð.ÉÅ(IÒ,„Ú%«Ì0ƒUÚcL×? gr )Tü¨.c5VÃm÷ ãòÆ`0ü#4©ou£;[4:ï\}¶[Yï¡kfÉÊJ@øÇÕ/«×oèº\Ñõ—+JD–Êõtì[pÆ×Ç:õêå껑Ìöo'„žâÏß ‡0µ&ƒ$Òÿ!Qö¡“f4zvÈO½{8KRˆV›­âJãåØ.H*âxùÍUÍŸ¯e¶P²Â¨Ä·  È}«€HÆñÅb˜{éAEý.T¸‰endstream endobj 227 0 obj << /Type /Page /Contents 228 0 R /Resources 226 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 86 0 obj << /D [227 0 R /XYZ 72 744.9066 null] >> endobj 226 0 obj << /Font << /F26 6 0 R /F29 12 0 R /F35 25 0 R /F33 19 0 R /F39 52 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 231 0 obj << /Length 2926 /Filter /FlateDecode >> stream xÚ½ZK“Û6¾Ï¯ÐQJE\ @roN²©Jvc{m¥v«l(²¸¡H…¤,+¿>ÝèEj¨™I•j*âÙhàkô únõð·¥™‰(P‘‘³ÕvËY¦Qz¶Ê?ÌM.–" Ãùù×âÓêgŸÎÒ 50 †‡³¥ŒƒTéÄ ÇAK©yÑÒ7£ÏÛs·«+*ÿðæ*ØÒîmÕaEΫ:·Áb©ÂdþÓ–ú»¥Â—…Ô󬱶­ÝvMQ}þ+éssVÑÖ`Ó—­©X21ì·¶kìv⤠” òK¶•m²Îæn©h~*ºNž-U:–j¶"Hµnm5F[…ê±u›‚R†”S}ù뻟*­vnY(m²Š ëÁüoñTõ|[7DÁ.„žÍö‡Òr׉Æ3ßpFTÿf¡ôüÕ[ª¹]7]—mvˆ^ LD°ã7ÀXs*ZOùÄ ‡~£r :¤“‚ow>›¬,ÏT=;î¯Ú"·TÎèsj²ÃÁ6T¹Ùe\jmç ïxö¡©ûYƒý jSç´WœÚKAÏt@Î1ý#žŸÒѤ ú†rSì:/Œžã¾ãøÞÔ{G»íb·«´š7¶;6¶Ê©5kùK¥T‡º¨:Û@1â™Ê;–ÜŽpœ»A®¥±–Jû ÆÁÏæ4¡*ªË¼Çâ…I‹H–Ü·Y²ò¾ÎB¾ìÀ¬×ÿ³›o­æ[kŒÇÂÄÜM­nø~®é¼q`í›è[ylÍ”Ú ‡(Œ&4æY—QéT”%•Ö¾ÏÂý®"œŸÝµ¦¬ê „”«âRŽÅ–ø= 1'š1Й®Ýºó”4³âÐpè+óM ÈŠyK5å.«6ÜG74Öºœ‚Eh¤‘Ö Á¹è& Q:HL? …OÃJ[Z£ª«å¶©ýú9\±Î2;–PìTÇfÌw}p§Gµzë'0ë$ÍPhk=¨XZÓ•_ŠT‰c·ÏÜuNSÆ$Mè2T¤áRÖp©×p©×…pG°A¨·æ¨lt<]w–H°´ÁèÂ[ê!UFŠš÷uÃdǸc:5uþ†ûwçáY™0 *â0/¹9F± íon·,/(–¼™cÕ%a†A¤Ót,o½NëÕ(_‡B­jú–uõÙÂéÚÜæïB-÷Pǡȶ03ÔHAÇ^}ó A±=Ÿ@ùªxž·St£Í´âyŸ¦TÝ0°'¦T\œRèñy“eU±F3 %k=4¶Å›uÒßÐ|¨›®@W+îöÀ7ã:](äõæH¦ §ÚýÚæ¹SÛÐWð`&x1WXÛÛ¶Í>£—d’ˆ•M¬‡.ƒ#á9ž6À#»IN—…Š'ôgAÛÖeYã§ÞN2.¨MOX¬›œÍt³pïÜæX÷Ûõ5ÓC‡äïÒÈÂcðHcü×µ—E`ÖÃ?Vxï™Mi‚(Qr¦C7[Ì6û‡ß>| gùC8ûù! TšèÙ "Mÿ½/ú)Þ?ü»§¸ìI.‡4¿C/yÄ­p§°th£bÇïv›ËîšO©T¦:º#Ÿ=Égø” øDgóŠÏvÓ'ªW¼¦àï‡Æ8Vuœ˜Û¬Î˜ÃýCÅàÈÈ·\ñêI.‡4‰Õ‘ e$àaDà Kqeü&qRúKE÷Ä}HÓ19RÔ¹1¡2¹ú>€«xÓYÜÆÿ~ü^ðšßÿ¿ïœÑ9Ö³5ç~hgà.ö&˜P±K¡ J’+£>iƒ›&N4QwÅp@sBÐÀ9IÓ4¥u u”:FÃÛ¨ÝÃj×Þ@mÈá[´8Mï.8ØöU[0¦àFCõ"ŒH×U qÃm„LÄBÝU»i>…P¬p•â纇„®9¼ÐÃÕ#ï üä%9ÊC­SZÚec·BÁ q°™7 â6“õ(/e¶±_›ºüðM„#ˆ%B™ü…ó“*HE¨ž@x@sáÎY)„N€Q®éuýX / ßÉÈ×LÞyÈä+ð® øEÇjþžéC*(9ðp:ßVìñÙ:Ž·þúî'nv9hiX?ccáL$[W¹ŒH©õS^äà±xe,}¹³þk¯Ð½Ú˜u„ß9Rò…¡Ë>"Í/NƤ¬*@A¥q2¶”â¹íêE"ËTFwÕͧ”D}‘ŠèÅm9½‡9½æð†œ9ÄtŒHåÓ(!ç°Íé', F¯×0X΋bÔÒç´p¢“Mì«j7è’^ÂÆŒ>—Xk}®+,’Á”¸¾¶.º #Ý›¦u D Î-˜˜v‹Ñkº•ÿ¡ ¦Iúd0§ycI‰“Î÷ ¸:g*SÆ(™WvƒAUs¦*¥¤€{Å–O»b³ãáÄ`‡ló!Ä4ÂWÇmKmYØÌË@G\‚|Êéa_ÁÌrV+AD*q2ñ7GµèJëÉ$Ô±¥t£ŒofúàÄRž«öxÀðn2øÛâ«m'n³€À¿Oq€;ïO\†òÅXÂÌí3« ¡‚XE^/ôÉzL܈ÅÁö†¢O¼Ã»:Ç[$\r£rd„ROPª+Lô¸6 ãt;ªx¥Ó+5Câ24ÕÅuÚ¸«ËÒ^Ð+y\g÷Þ<_RÇý „·åG'2µ{Y’ñâä·Ë*ðJŒ¡ŽæÁÒå¤ýÝ€óßâæ@þÚàrt“q4x)ËÇ3a´ A‡0GE ‡eîàFy’Ë!͉ð¢Ò(ÑP>ŠpîáV0Ö Ýîȧ'ùŸZB¯¸fóf“:ÑâEt‚2 ¦p:€Ž™?OcB])ˆÄÚOÝóiì$ê®È÷',سT]3üáÓmÈïÅÞð§Øóp¹{å¬ýÞ ÁbíLlÌŠ-59Ü[°îŽc[]34X½6H‰üHìmwõ±Ì©¼æ£Ènüj»IèxÆ‹¯…‰øñV„üzû}ï}˜LýºZ ÁþÁ>ÿœûnç)GP›ï7;»çSÇwÅÕ"!â®s•°ØËŒ¼ »%ª‰£¯«~›£ ctk?®Ö£tô(_}8»u¿õ)’"5‘Œ†PÁˆÞn>›åfz/Ovk…¹6ó\²[=“ì˜6RZN¦»#Ň Eð˜V–{2ç[]Ì‚cÜ+„¢öãŸ8Ñ^'îUð1‹2”I<>Û >#ÌÄâò¸>á^„A¨“”‡øò‘‹Œv4x,s•΋ñ4ïƒ= þ—öí!öÙe¥ËÔ㟠èYÖˆó4dQ":#OÃÿù@‰LW-Lâèÿý¬uåê( |_âš§À¡ïøO[ÿ#œá×ßÙ]éŸká&A›ì#*{VÿI P°endstream endobj 230 0 obj << /Type /Page /Contents 231 0 R /Resources 229 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 87 0 obj << /D [230 0 R /XYZ 72 744.9066 null] >> endobj 229 0 obj << /Font << /F26 6 0 R /F29 12 0 R /F35 25 0 R /F33 19 0 R /F39 52 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 234 0 obj << /Length 2778 /Filter /FlateDecode >> stream xÚ­YÝsÛ¸÷_¡7S‹€Hæ¦IÚ›ÉÝLî:ñS/7.MA{”¨#ÈsÜNÿ÷îbŠd(Ç™ñøk|,~Ø]ì—ÞÜ^}÷C’¬ò8×B¯nw+Î’Xh–¬RÎcp¹ºÝþý´*2k΢¦Ý®»ýñêï·W|Åà¯x*ã4|•²,fRf«òpõÇÕ¯¿±ÕöŠ­~¼bq’gjõÏs›„cr¥Äª¾úpõãf`¹ó|ó%ÞLÇœçÙïßÌ®èënŽSˆ,V9^îÅp,¿‚S$pŠ9N[¶Õ©«šãkžÆ")@Mc-urêÊ#<\I)âDrFfXË͘'AUK& ó<iš:¨ÕoÚ‹ª×Y§‰þ‰Š$Îá¬Ëš±\@ ŠÏ¥VS”?µ5ÕþbÏZŸcù’Ò'ßuæ`×Áóè¡êöÕ‘ènoˆ°ÝšGm_v}ëG=Œ9ª8LÑýÅFRñ8™²úȘ0[È&‹A<3a ÄŒ')Ü6»‡}ÑѺɅ6à½îÖ[óGoŽ¥‰XoxÂcÅt¶oNuu4—­Iåq&ÔËšÓˆçSö”ª8Ñ©|Ž=½Ê‘AÍQ^°¨1Ê[´€DI0Án¥¢Êúáêø©6›ÖìL‹zºáŒG¶¡é~xGĶ1–v›Ž†öÅZ°èÏ5ÿO#]CKz»hI*Y¢¹·¤=œù]µ]4¥°rb¯Ù\û,["ó;ô]q_?aL\ÄŒ©oÐ’LA,}–Î,Ÿ2%Åc©RþSz)Œ#Kša¼`HcŒïv [)¢âHßæþߦDKœŒ Æ>5 ")À÷ÞÐך¶*êê?ètpËbpuªýlWŒEÓÓ ØÒ`Õy¶¶+:ã·_Ükb"0àÚpm÷¦{0ót€P`Lu§% žŸwki×ï˜Ë´ësZCöM_¬é ¶¾u¼dÔ³ßÄf ÛCeÑÙ}èé]á’ðü过ª®‰º÷#gñÝà@æÂM%‰ÿ ÙÒÿ¨w@H¦À!À5'ðH¿:à6Ÿúƒ9b@Q,ª§ºr|àŸåàÖ,ÈkØÌqÏ,*ÉâD |€Ò °÷³ÈäYZ‹à±X|úàc‘§ÙTÞÝãéò»W’AÔ•ßð¦RÁœ_~ö#ŽKÏèDÁ[†J'š|óûæxùÕ¿Âó£Ÿ#¼ðèÇ_¯72I£-HË8ÓàBH§™b}[qjÆ¢º)‹úX ó{Èä˜<ñ{¯é®wFìHL1€ÒÑÖàs>¢ÒDXÊuT³›Lés s¶‚6Á 0ð™u ;“yZcÁ8(ù®ü´ãªàJ$^ÇÓzã¾£©mÑDí KD±$§”Å:×Ჟmõ*XæL*J )éðJº®­îÑ›ôñðÈY\îv²™Í¢ŠÞžŠÒlþèÁk É^žÁ£‚‡VÔ=º àƒÒÃa’8ŽLÎ¥IŸcÂä¡èÊ}ØáYL8f“ôrÁ Þ£ÿÎy𶹈NE p;ðœ9€?HÁ“¾ñ«¶f‡ 6¤øM¹7åïj€1â>1Á]ø®ÜÔ®iih0 ûýbÜÀ{9†"ÓèåE–F¦6Þ!¸+‘•¥ùÞ‚€ëG´ýe—/«a—³)\ î@nцj=‹¶hMàpj›Í’sþ³Úï‡á“›„Û\0{*!šÙý¡úl.é œµ-ÒÇ<ŸHˆÀÍ™zNnýr(GÎqŽrÙ;NPö–L”QФë‚Ö–þ-›c7„SÈML}ã—×u3ŠxK6>û…d0@œïÌëê(§ê»­ö²Â¹†Zá›êÞ¯+|ÄsIá hðXŠÃ b„õú®3Ÿ»ëË*1œ#•Ïq^Pù'Æ…EW>Kº]c Ö››%½N¬!ì°¦›f=äÌ<1 a˜e§^C”KRŒÇ(+!ó!ʉüRö&`e>TöèY–ª±ÂRÆ„_µ˜ã5xÚ3æÃ•›ìüì$X„MpUk«OGãY¹œ. ÎÉéAígüj'*C– < ˾ְ€¤4Ui¸ý< Ʉ҃’ïK‡BÄtO4”P©³¤ÓEE)'e‚¿Dª¡Ê•¹zP‘'C^ÐúZs2…«nÑÚd(eð´eÁä².• Éúд›'%¤‰üi…Ãù¡Â]èÅÁ{­€(òfAq© ÔWávJh »ÔH ‹¹šµΚ#îz|'X3ß °Kò}Æß ífÀJEøŽ¾4S8J¤X©“ }øãùë_09çÑÿúDæŒô)|úΠмOÓaÊ• niYkJûÃrsi îé‹JÄÄDô¾¡Å£2Ä÷À˜6`ݱ{ªu¶¸Ñd0á þ¡ž•dÑÍR]ttàµögºîÜšËÈÿs†Kfh`¤ U‡âóÏeÙ»‹ÃèG‘¦DqlI©t,f%1ûÅíð¨Êuƒ¿ejÙÜÔt ×n‹GhCÄùÚYTW¶ƒRXøàf[*°WVÔyø}4FIÇC«ÇgVÇ-LÃí+»wt7¼k›ƒ_I|à/ ×ɶ˜¯P˜ ;âÞ,„sl,… ñÜž 'd»ÔMrp´£²þ§®4zØW®dY¸¶,P¦cg»æé°Çÿ–nGsvá—P ÉpÓ¥Ö™àR3%F½3ÛßÓϽÞ5bséBóŒ3kÎpèžá9§¢j­ÏW¤d±ÖBL{ïv¡¼ô_Q1Bi¦& YR™"ŒM;sÕ¸X"øp'& {_@?†U“×7½G¹€O"]üogiÕ¡²çê{¨*†Ÿ†’Iy¬ -€„‹ÔXCªìÛ·® j/‡æ(×›> endobj 88 0 obj << /D [233 0 R /XYZ 72 744.9066 null] >> endobj 232 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 237 0 obj << /Length 2202 /Filter /FlateDecode >> stream xÚÍZKsã6¾ëWè)5‚ñ$ˆìi²“T%©L²‰sšLUh ²¸CŠZ’óë·ñ¢@š”í*r"Hý½]Ü|ÏØR!•Ðdy»_Jº”#Ì$[Þî>¬¶EÖ4ë·?Â<Í£q"’%¶³ÞÖuöèg‰x–Bi*•Ÿõ'ØOJ¢I))¥¬}<é5Á«7ë xUíYëVQµ$1žP»Œ!™ÈÔ¯û0B˜#)á¥4àú8rº}8éÈ\æl‡¢(ŒRB;ûö G’a•¦=V<%É€õЦž²:+u«k8_BWycžd•)’D±HüöÛ÷ÿ~&àKà €Úó©Ðn›ZŸjÝèc›ï݆íÁÿôû/k&Vouo™Õ 7ŽƒÖÆÅäñ "L…í¢".©x˜¹Üp rK@§=¿©dÙâÏÜÃ@ÙV;íÞvºÙÖù;Šùõààa¨ ]Âqäv¡)œ$°‰D 弪¼¯Š¢ZS±zèhz­#´Î «zöX“tu¶Ôݧ2lzçé½ûÆ3,6Vš Å * ûÅOfc}Ù–-¾»]`^’%I8§Ë„I0 Ê—Ûrñ¿Å‡x¹[àå Œ@bù¢”Qï2 G‹Åï‹ÿt7ÉMLóÛ'¾…HŒcê '`fÊÂ}§÷Ù¹h‡0)–H)Ég„Ù‘|&'@$§˜FGNm^‡P…¥Êe 8ÉI K¯\pNˆ _H=ÅMLÒáŒÍE¥Nú …Þ_òbwƒh¦Oâ8•³ >¢ù)p\£}¨ï«£žûl #±Aö¼ÊEì1HPOcHVE­-Þz7QuÖ̾8+2à¸*ÁFоÓÚå°¢»"KÂ@lNYF4Gd™š_•€­%»xF¦9ÂHC„‚ŒvÎùx.ït² .œ¶ïùq4$bõ"ñ¹÷yQL 0‰t^ïѼf„X {+šiÉ·ò"Ù'(Ç%ÛCùÃÞäƒÔÊË<«»ÿêmkÆÄÊÈ|»¯le†Fâæiò"óltgEþ·Þ¹%%xéÜæ¨v6ui?³ÍŽ;÷1o=Ù¦ÍZí—ñtMv‡"¯vùŸS» äjwº}ÐFÓ‘„Ìdv7H~ÛCø¹=ØcÀªÑÐR8Tç¢#íž&á³´øªbõšâÕ¦Íù˜‡<(¿Ïl`V¡ƒƒC·Á:Œ;꥕ö½ SÚƒOA;Nš·Zïu­RÓ·¼¼}…å«j¿ot;m:nIJ_)(ƒÚ ³+¦ѼË„P4pòñ´Ù̆02›! ³‰¾3üOS`iëÎÂÀ,tUØSù¤P”S&º*+åi•%»YYÛB…dÔðÜú¢ù”ŸÜ¨ÐÙÎ<ðò÷æ5Ë#´%4Kˆt %M—^ ¼}ÖŒU´ ɸî‡^nҸƪJc2(Ò(-›+®ž*Ó˜5„Ç4¯¹zÆü%ž~6‘ÊAN¨lòv¤¤Aرùž¤—5-HúRBé¬R‰h^I¬%f“ôùÌj>‘T† '¤ƒ|{ ‘¢µ¡é¾KŒý³È›¶Ÿ*GSC40]/I½u¡²äÏeö%/Ïå¸$Þ¯ÿù¸ÓÛ"«õtsC@þ˜ŠYK܈ä5ËÄ qî[1Ϙæ\#`œPcg™QßÞþëw¦¦é©•âíx‹ÒôfUf~åÅ>ˆ!¦ÓÚ—Ç.”™Y§“ÎêµèJ- ue7”s”JÐ_ÈëéS‰¶ÞŒñêí)ÛÚ3Étõ.k§º¨ØvÍé… Lòn9“"b‰ùåTW&;…\‰ãdu®‹CÛž¾¹¹ùR(³«Påšy7M•nrPSc)_С- »L¬Yãhï´1”£M*x澞ªÓ4Û}‹·‡á,ö7S¡š¯íh'u%޽7¯t„9¦›’4ô¶m? ê7!× ÅýcºÒ?“5 §i‰A °’ ¢B/U\kKÊåÕM(6äBßÞqŒræÂ àÐÀwHzí.ˆ((óRÂæÄH>ƒ“bÈd`âçäešˆ¥‚X¬ŒRò¢ë lÒ\%'®ƒ:š›˜èH yUn[™þ¸uìõO“²'Æ÷ÊYE!9–)3„9|êÄÓ2Ÿ ßEä|ƒ¨$ãûcÐfqùÖ»û~Yv 'à[޽¥Q0 ÷ ñÁAÅ #I_¤9&êŽ* ¬ßD„ÜA“þ?=8E„PÒeÐàJ'3è%ÀJBþEUÿ±.¡endstream endobj 236 0 obj << /Type /Page /Contents 237 0 R /Resources 235 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 89 0 obj << /D [236 0 R /XYZ 72 744.9066 null] >> endobj 235 0 obj << /Font << /F33 19 0 R /F39 52 0 R /F35 25 0 R /F36 32 0 R /F29 12 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 240 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%+m÷ïgµ$CÌê–)S¼>%„œørâ¾S’ŒÒɨ/,5yß°c^„VMî|èé•EXÝ6”:üÊ7\¡_M›ûöOt/VÉÙk"Ÿ£b¬jJ±Î‡Nš%&Œ7\ŒÁendstream endobj 239 0 obj << /Type /Page /Contents 240 0 R /Resources 238 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 241 0 obj << /D [239 0 R /XYZ 72 744.9066 null] >> endobj 238 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 244 0 obj << /Length 2942 /Filter /FlateDecode >> stream xÚ­YsÛÆù]¿‚o%3Ájï#>¸¶#1.©}!! ÀR†$¦n÷›«_¯^Û½W7-n@-…FDâ3ðÐ…y )­ˆ¥‰` Ï9ŠTJ;²nÖ™g€‰îfn0špG{™îþYåMVù½ÀB IâÞm¹Úo²EB•ž¿£TùU ¯&DÌót“΋ÎŒhŠˆÐVNi­¼XWi“4¦£ƒ„ƒ”À¬Pˆ+Ñ’ŸP¡º$Âo=_ndžÖµÿ•×~×¾ÎV~Õ”þI¹ovû&ÀøiÁÄüÙµÿµÍê:ý˜Õh‘0Fç¯Ë& jÖix!oêc(WV,ËUD—†¿Ü¼LôŸa-ñü~þnS¥E½+«&Jƒd„¶Ó! ÏËò“ýç™Åóïon³¼ ×Ú_›uVewe•…Û[‹%-Â./ ÚiÚí­5DOÁ9(62hx¹N+ûƱŽ8Xc*ìK›¦ÊoÏ÷MÀ_ÞÂ#Áæޝ?/‹&+šäæq—àRQJâæu–®@BÌ‘`Â4X  ©¤àžCk?€‚FS1eì]¬’"*eܺÜ Ãó*÷J wêr¸.R°¥]º ?wUöcúà7b]‚£°JÀɘ”Õuµ z^DŠ" ËÏPšªãXÑKØX‚ˆ1^ÚÆe4³Ae›r—]z£`óJ˜aðp¬>Ÿf•1ˆ§LŸ•×ÌSÌ2…°Äü‰ÌB@…yŠÙ¿y5Í'%H}^ïèÀ<Å'ˆà@càóþþ}.7Y•¢e¹l_ã ÷òC½šfCÖ–@Á9ìÀ<Å ,ˆÀdÈà=sú£“Ëýø÷7ŽÉú{¨óIö˜HŽ5;'{]˜§ØÃró$ö’¼¨!Ç.³‘ÈQ‹x Ñ—í$¿½›n¨-7…œÈL=Z½8uØú 6u YŒR\¹kò²H7ß|óû‚ày¶`xþx_V ¦æ«z…¶5²!d¬N#„¬¯ØP¨áù]¹Ù” *æ÷¶Øq·zH‡÷vYV+ÿ uIïã~ u@ȪÛôÑ/n<[ÒåÐÀjâ< iKÄß,Þì€d˜£´DLAÂa $#¡àùÖւLº0Çò(Ôäœj@-Ò íEv—î7Í‘G(P„€få|t¶ ¿D§’ˆ2N‡tÖË*wæ4¤ÕHd0Ô0,¤aò”¼Ï5GDs6‘ø#Ȥ s$ñC›£mY%)”¯Ô7 1‰¼i7ٴآâÂWZ=C ùš6€Lßžõ<Ý—©}b_—E6­ü³ÑØQþi[åw‰|5=×t^”ÍXï ­Æ‚924ìèâaÓ·‹Dp×#2³.îQضÁ-ê]¶Ìm-lû+»å“õìt³Ïm»Õyáè9tDˆm‹uÌB"¨ïN{‰øÈß·z bÜRÒ°-Ûd¶*Ì |è ûa[è+Y¤¡×8«’;0GŠ$C!‹h#ôëTz/¹ò¼]WåÃã´®ÏFkG×CZ'tÝ%ö¾Jw»8M«r_„æáÅO?'K; õKèÕüb“ßV6ÈvpH1÷Xìàs)™À5, [›:V;çvÞøÄ¢’2Våío„v÷>oÖc 5ÒÎ'»)~Y`¤IìÏÜP×B…`6R—¹Æ˜°÷eº©Ç2¨|T{ Pe5t#µ‡j£¡“E¸ø aBnï.ãcÛ®Ù«ŸÀÛ•«Áì¢ÎªÞ±˜G˜°ÿ8øu Å1B÷®¡¼*>¢‘÷'ÀÙØ**u8ôxJ ½{²Z¹u€ =ÖÆÿ·#p@þ¶ûoK^—Y¡®-WÙ_zur¬Ôˆpþ•P«ó²l&¡‚}iÓäSÁŽ',fÇrAiŒåS>ŠŒÖz¢Ýk!&]>”Éž­ºQœ8`n5TO²nUþÕj:509Oí$ß¿þ~‘Óù¯áÿˆgBu`[°ÓSfç=MYÜÁ³§Wͺ´‘éƒÍ‡gã§/CÊÀmHè›v/$PÁc¹~4…#€E™T«¼‚{Y äöñ$Ô,a<ÎA‚ÓÃ*ì¡–¶7=Æ£¢DKÂŒ@ÌU_Æþh gUîTáZdg…–ÛÛ¬-kaÇø ´­ûbðžÖv¸;٪߷ÝnŒ²§ìõ„ÍAË!Úú³WiõÃTòº ‹ÞòÇŠ·„Ž $ÃPɃ_¹_øŠäP¿MeOª‡æ«#³6!Á7¿ð¢€ÅnݦËßk«~Þyv½¸n™òNÉû0èð3L ‚+Õ×dUÍ…_”…s9X­m+ÔÞ]fòF‚H Û_jÐon5ù60ël®÷9ÈÁÕçö»ƹè[Ñoûº‰ßBØPo%8BIbnb€ØëãŒg+ü}Snq+ô0¶Éï¶yÈ…‡O_VQšlܬ(G]³úðºˆÆ0m)#O0,"‘ar ™QËâPŽgå°dôKÆÁ!ÀcÖs!;9£K­-ü˜sÝT2õ÷|§Ÿïìw+EãìÊß³ñ'Òæ_ˆ~€¶¦}þ¬®!˜µü¤£­¦Ã™æÓãC¨U¬­dŤµ ‘ë4’R=écÿmÝXb¿­ë:þ> endobj 90 0 obj << /D [243 0 R /XYZ 72 744.9066 null] >> endobj 242 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F33 19 0 R /F39 52 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 248 0 obj << /Length 1210 /Filter /FlateDecode >> stream xÚ½WYÛ6~÷¯ð£ Ä ñÐc6ÍIÛlšuÑÙ<нV««:⸿¾C‘òJ³‹‚>If†ß7—®6‹—×4Y&(T,7û¥¤KI0ÂL²å&ýmfµ¦Gû*Ï«åÑ1+ï¨0Ý¡J[÷ ¯X7Y¡›,?¹Ç¾5û>m4î¾k½ú±Éº³ÅÒ ¼Ò©6»*5-Z}Þ¼{yͦqâåšH$ha¾JÓ×:Ï·z÷·WæeÁ‘ä,†¬îæØ+‰‰G‰”Âëìûr÷b<ØŠÉè>`–q$° f‰SšºVÅ ˆ— „s:(ÿÞštµf‚FÛ“½²‡Ó:ññ`J÷¢5M¦óì_ "b D42áu»ƒ)¼‘ÊItš:AÕwußyá¾3Íù ÷þöfÅxôêCètŒ •pº«*=NG%â'^)ƒN»1þíŠBø¶rÀXCË5ã Š OFdÈ`Ã…†Éc¡Å QŘ÷ú¦übòª6ð8FŠH9 ,ïrȾ­Ö1D´ýYÊ»¬*þ”âl’6‡¾C8SH :âvÌòÜÙßz?; o CògÝÁIí±Žâ"3ì¶Òõ-°ø­[A‘”TyÕjû—Ùuδ.Ó™@^ D¬æ9ÙBfwSˆ.%XŽ5¤›ûP6`Sö ³"*ºï Sv¾–އlwðÍCû±õ@ûªïëÜ„*~­€uÌ ÿºjîM.N%8FÍf;pe”Š6¶­D}É#èt;âg+ÍÞµç;WfáŒ`ÈðÌ«Ž×iOvÆÞ5¦6º3騹'gÆPÑwz›{Ö\¢ùJ0J؀Ʉ¯ŸËê*1P)™ü_t1$2gëí>T€ˆP.,-îÞq«‡10àèU²ÎÿáC2„ *0di ¦ñ\(¼9îú&d•ňÍ#Ù zŸX7ÐPšcÖš³ñÂÛ±;ÍqŒSü8Mëшa.ǘñÓ1R4fP·JÍSô£ÌÿbÒ÷·¯0³üçäi=ìÆ6Ö¯¨¾ÉB(”PÆŸH]iÀlž»|ætMïs,ÛMÇ ¦-Þ-\º0m­w¡áC8L2ržducöÙ×ðÀcü¼YâBI‹”#$çó?’;Ø7³t\‡9y±9öçâÙž.Ι0DìÜÑv¢©§À$“übœØÍż¿ý)Ûu?d,Û4l :P"ñÙ°¿àxÎõͰҵá&\¨€ëK¾b9vÈ¡]ÙåÐ^È$©µÚIV"*?Ž£·{? øL·-ŒùÔ ‡çÄ¥“üùë/NÐvºéÖÆq37Q›2u“„C7Äjn¶I/y¹¼tÑÅÀôâÍfa‡—ÄþÎða×]±øgñé3^¦ ¼|·Àˆ%БŽð€a‚%«XÄ<÷/n¿Í€Ïåzbèjøoóÿ¦˜"B¨Ûb…¸1tŠèõA×ÃÞ !GðÔ-¡ˆa, þ½uOÌ×=ŸWÒ¢Jûa"ƒ;J¥»k­[XA&S¤©îôÓOendstream endobj 247 0 obj << /Type /Page /Contents 248 0 R /Resources 246 0 R /MediaBox [0 0 612 792] /Parent 245 0 R >> endobj 249 0 obj << /D [247 0 R /XYZ 72 744.9066 null] >> endobj 246 0 obj << /Font << /F29 12 0 R /F39 52 0 R /F35 25 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 252 0 obj << /Length 2535 /Filter /FlateDecode >> stream xÚÍZÍsÛ6¿û¯Ð‘êT(¾¦'o›lÚn·Ýµ3³³I´GÚH¤CRõzÿú}I¢lgƇŽ$@èá}¿ßÌþØÂð…a”PaÄb}¸ørñþ#]l.èâç Jò\‹Å= (‘¹e‹Ã…Ô¶ì/®.þqÁ"Z¥”þr}ñÝ®9É5<®o2çDä6_hx‘Œç‹ëÍû쇷—¿_¿þçòãõÏß½‘rÁ$Rsü Fåz±â‚hÊýê×?ýõí5®½x}Ýï [ke ÓôdH)u2pIŒ5 yb̛㎔mŒõl]o]@¨t±Ì‰Ê­â¸èMqÜ·aÙ˜¦e„+fâ²Cµ9îÝrÅÍ>pnÂ[íîªz¹’4kwå§0ç꺪›H1O4½bÆ#QÆ*ª<å«ß–Be—¿/WBˆlã>PÊK×àgE µ˜*l»MøOwãŒ(«:)®iŠO.ìQDâí6NÜ/ÍŠ‡0¸E‰ÂÞ~\»õînçÊ6þ¨ Ó»r³[m¤°‹_¥&LËâf„Ÿñì®®ÖÀKd$<"sd¹RÊŽ¬6ˆ#4%Æåù÷ÕO¸h±’ œ[£N#¹RüĨ©Røº±:Yï ä„+š¹r]Ü5Ç=gÚí®!‘‘Z±£æ$šƒRaõÈ SJŸúÚH8žkMW} ŠÎ˜]‘ܘžõjãPÕßf›¶FÿëN¢Uj’KÑ9ËûºõÊã‚Hï›o>#u·4{¸‡&Û4sô• œóŽ­3Âyúb͆†„æjlÅÁR~!Ôæ#EÌx?'ÔRÝuqp­CÇæ6Û¡ûñÜ» Á‡™ÊþÛ†QTeX¸·ßÝ>ĉñ@°`ãËM¤‡nðj¦b±²ž µÒsñ nì†]&àŽe•-$üZ ;á4*„p„å9ºæ¡{í¼kãz’«”¦scv%\BTK@˜”ËHt=ÐIùä(“oy9>{’OðÉa nÂ':Å]»«Ê4—žW lçuYXÌ4á„™©R;š«”h`vT4Øš>f!ô‹uÓ¬åE®´ê+4 ŠÈxÚY˧4“£|b1!z%\þ½*ÝY³¿“ƒÙO˜œ ‹Îì)“—˜ið@§à†”zšDs 2÷Y«7É)pÍ•´s©3ìÖn‹6¼­‹®tY&“jf=À<6Dö!¿1Á¥ÐŽòÛó¤BrA€ïŸ1ûËÏeH^%b:2“¶WŒ*"•˜ ºk‹Ýþ¼Û),Þò+ hÇj¥ñºä#N' <Móg8ÝK±˜øÜ„Åy—±xLÜ Ð(×ÞÎ:«nìc‡R³˜¬:¶wÇ6¼ïÊømÖ+™–УÛ› 6›ú¥%9§º»~m =!ìà nYì›ÈÈ‹…•b0ÜybJ#“zÌŠ¡…ý‰¥žy\Hl½ ß×Ðu²Ì…÷Vøî½žàø­hV»&ÒAœâ4Ûê¸ß„ ‘ÚAì§›øüׯëËy%—_[€.ôTOÄy$_2'4‹Äœrž /ÆdS&ÏÄCÊäE[ Ys@áìZß·Xa¼4€ÃPtŸf|:LÅóü¾˜° ‘èÖqS…Ýnâî½3ZÙÊÉn#b3€°AÀ9ÿQ*#Ø^Ðìʹ)=Å–ˆ?ÕÅÝ–DÚ\+„õ¸PhÐéO@¸Ž•ƒkö¶8?tBøÑ³Ÿ®~¬[›J©;µ¾ B̨5æÊá@°aƒæÎ­}ÿ í b,¿=6[»ÚŸÜhKርhC?yÓQòGZ~¦XsÞ1`Æ÷­0Ž -*Ì0"@kcc`ËäséÐ4ÙÇÔ¨ÄÓJÈ‚9Ϋþ˜€gïJHNí±‡®UæÏúÝÍäpâDc¸dS¹Ø•U<µˆíL¤± ÞOHª0 u&· ÑZËI6ÜîšïçŒ-œRv|z7 kJJË>ìúƒPß•›¾Ë馿´+ SL û¼:¾šCÅÕj¬âxþÕÕ•ðe±¯>UÇîx°šDÜcž¯ ¤)kž‘P„Òljôxd@ƒ¾õÇŽêÉ^r;!ê¸;ßUUî^ÍZÒñÙæ9L ù#Çvr—Q-CíŽ'ýû¶ÚoN[æ?÷bŒC„1Ï֮ыFr~ŽãY““ @ð biÎ'§¼gÿ´Š8ðÂfÐæÏÑ +Øä´û¬ŸÕ„©&`ÔkÞñÂÁÏõPÖÏÞ†çeq´®JØ»ì;hQw¥^R-&¤úïhQ¸ÖÊg«ª’> lÜo]6*0þ7»ý*žÃÖϘt[x5o¯S=üž°ƒ>±lséÁ#ñÝ_üÀФ¥ÐÁq6i)`6µ~íí€C%‚ÙÄ=©ø}FóÜRóÇk#j8ñ@ÈÓìJ|Â*ÖEk‚5‚æ¹!ƨ©æS}ΟEŽ Àþ<)á,ËÝ${Vr̉±>Ì]\6W¿ÍGÔÐ ·[“‹¤ôzë+î©îçˆ%ÏŸ¼•âOÜJ)ÝíÉ­”?KÖ,;¸v[mÂ{ãê]±ßýÏ5¹8‚&Ε¹{å¹¥1ÕÍܺ »ìJÅt¸¥€Gõ`Óá"UK¯“<ŸÝå/’ˆ Ö®=Ö¥‹ì͈lpO‡g—¥ïjfî÷• w¯Ï9Çô×ûsG˜þ>| tú Šã!3 É c<Ä’?ÿŠ-Êendstream endobj 251 0 obj << /Type /Page /Contents 252 0 R /Resources 250 0 R /MediaBox [0 0 612 792] /Parent 245 0 R >> endobj 91 0 obj << /D [251 0 R /XYZ 72 744.9066 null] >> endobj 250 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F33 19 0 R /F39 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 255 0 obj << /Length 2513 /Filter /FlateDecode >> stream xÚÍZ[oã¸~ϯð[m æò.}Ê´ì,ÐÝÙ&‹´Š¬ÄêØ’+É›I}yHY’©\Ð.°/’ÈÃsù¾sè¼»½øîš›…!Fs½¸½_M Õz‘0J¨HÄâvóiùuÅè²X1µ|z´ÝºÙ¬ÖB‰eÖ¬Xº|8k프©Ÿ²¶-ü{]»m±úrûÃw×B ödJM¥ZP·ÛMþÖ”]Ñà»#ù´ Ü(ã_ÍëªíšcÞÕÍJ©%Y­—tùc±âjùˆ{—îý«•¿hÚ²®ð#쫵¤Ê‰å¦êÝ&&_¢‰H¸ð›^µVÂÏTQøc×Â(ž,ÖŒ£sßí‹n[ƒB¸¢Ë²Å¶íÊݻيSÏÊ]v·+ˆ]z±æ-²f Ñ´d×úpÉtYƒèíšå&ë2œt‹ÃÌC]V8e `§î ·`0ì=–ÝŸ9-Ø©{kãì¸ë.§êÝ®vªõ Ã3t|Ž'ô»çY…³¸§YÁÀB‚šå»"Ï`èe©÷ÅôûòaÛádUÎ( }¯NîTàŽzsËC[»Ã±óê­°EÉ¡sóÓJ¨åÕǘu)·Þ'½u¿/²MÔó„"©VÁI/½ýЦÌvåPΊ®éU86·ê•¶n»â€3‡¦Î‹¶%^¾‘71‘©  ]]×ÍÍOW‡"OŽÆˆfiˆ–ç\\"·e¾FݹN8Kå«(^Õ:~ ®“Uy@g` ’JÊÇÁyƒ¦œ«­$õäS•|ét¬Àÿê*ÈØ34àUåU–7EÖóçâà´*¥Ay×Α0áÀhip”û¦Þq÷ûºêEß”NÄVFŒOî6¼†õ®)Ÿ q¢SÍßàÆÇ¦ìOÀ$¾vá »êàŸ"«H’$‰vvk¼‡C¨4XùKDòÑrsÃÀ3•Ñ29BôfÇQ^wì:ܱ$ÎE†öDx OÂÓ=áés ÷úŒð´°ŒúTšPÍÕ8J¯4è:ñi`ê¹Ø5oÉÅm,¥*Ð/2SD*=Á7ÏZ CëPæ°e‹ã(i«×†â “ì[Q00nbùcÖ€oÙÒ0~)™4£ îï=Alw÷h7k#Š…2W19Õìh§Ùð†%€ñ~Ÿq¡_W»'Üѡ̽ ±W«™{•µ»¡'ñ¡½r }æÊh\oNPä¼X ê»)Ô‰`3õãu÷KÝvu½”c)°ÖÛ IŸ%íê<ÛU€+–{.cé’¦°:W¿Uö5S]ò‚ˆCvƈV—‚¥Ã ‚‘¯.m×¹K‚[À V—¶—…vX]Ú‰óêÒ½†Í‚3˜n=wl{HòÐy®²” ²[Ârlƒµ³j  ‘Àûª[#Kao;&·–]SÞÙ4ëèà–³€ùÐ+}»©æóÕ0uì·wwÔl®’S Åþ·€™bŒ÷®ÙŸhR•‚ä}øœò|5›ÑN>lQîîxŽÒõ¹cxÆcõµÂkû Ÿœ²œùƒÂ‹QÊÇ€ý iš²i‡ÚÕ£ïÑÉÎ ië!ik$mH[õ¤}V‰Û´õicÖé> ûOÐæ§oÕžazHÏ0¬=÷‡#Žíæì îýýæÃ³ÕëÛ9{Rs P)%úa¯­VkŒcŠi¨ŠÞ ña¢`G}iiÑ,Ñ&}ù>eÂæn7¼Y\I’öq–‹–;Ý ë²Ë˜Š ×}‘åR‰;Œq, „of.ü% Ðùþ×lw=·è$§¿ôX+)Ñôô£&÷‘>Ív’x¶£ ÓýÛl}¡‹Í]üpA Ôÿjñˆ H¶¿6†p°»¸¹ø¹_f ߯ ½sÿ¯ G¿ã,$Ä®½Þµ*Ò^;«T.ÿ´ÍH@IºL­í9Ø~œöƒ×¥LG0B1B«$xð¾ÞÝ3°> endobj 256 0 obj << /D [254 0 R /XYZ 72 744.9066 null] >> endobj 253 0 obj << /Font << /F29 12 0 R /F35 25 0 R /F39 52 0 R /F36 32 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 259 0 obj << /Length 2547 /Filter /FlateDecode >> stream xÚíY[Û¸~Ÿ_á·•k.o"Å}HÒ,:‹d6Mf¢I€j$y¬F–¼’œìüûžÃ‹F²éI€ö¡@‹ÆEòÜ¿sÄVþØJó•f”P¡ÅªØ_ývõþ#]•Wtõó%Æ(±ú”H“±ÕþJª,<4Wï®þzÅ< ÚÌ)=¿½úñ'®V†?·Û•4œ“™•‚dܬnË÷É‹¿<{sûòíúãíÏ?þ$åŠI"¤â¸ "x&W.ˆ¢Ü.¿¹¾y‰k¯^ÞNgÃÑ*ÍSô?ÀÜRàK¢3Íì¤ :Å)'JëÌÞêvW9D:_, IM&€8.ê«¡k>Wýà–žÒ¥DKªýÚ}W›j½á:K>p®Ýh»4©ÆbW·÷Hd¥A0’!Y¦?gß~o™¹?ÎÌT±"%Z€6©&R§g\<®eÀ„—˜˜SR™2Ù ’šäÐwk–&Ÿë²p&K†nïßmm1Ö];¸Ç¼-ÝŠ¢É‡¡ò³ã.ݨÈ[÷þÎï?Ué·zÚc”žÁ8cì„‘Œd†s¿0Ǿ¾[sšÇpå®°MA,cĤ©³ØÛäPp;—˜”ÓIQªHJò T ö·×¯"”h‰N¦6>ª¢a“5´¶šù?¬7B)ÔFQ ƒ{@qÚß;‡åP¨4ùõí«ü¼_Ä ÊÚ-wÅ.5Ò©_öÕxì=]T†%YtíXµ#±†»a4!ƒY-dõ¼*rÐ'lò‚SN(ìÛÌ‘ñ”Ÿ˜#R¶6„ƒzèúÑs÷Ó÷w`vÜmý/\ÅO5y¿fYro) Ou@¤iR{RûãàGwÕü + ~ÕÎïýõíµLqï= ŽÌR’r.zì›îPµޤ$if&ÑøÛ8Òuûx•ó##BM;á„"@Äé2¢ØÒÀÀáDf®¯ L kðŒ'õÖkƒ••«P+VKÏäÀµ5 ΕW›uµm ޿НЦ§rË‹îØ”nèè¸%NÚ0ùî—µH“go<ñá©‹Ü‹×uîÅ3Œ_Óú°ïQÑ'åöè@[%måUßò+z÷ÛtEÞ„K ŸP>”'7UU6ƒPtì=Rš yp|wõàFM:k…0Êýžª8öõøàžz8p ^¿sÅÑ`ÍÒžøË!ÿí³È’™Jƒ| )õ‹æ¸&%FëGk¬Ã… ?8ÑTË%.ø¿3OΠЉ ’ÁmÏ é÷ÍxÈà7€R¡¼½\ûNX*ƒOÚÔ3¸(açvSmöu[X$”?,¥ÑÔ{¬‚`ìðïwk@ÿC˜Ïý Ÿt`tç—Î0àÔÄ2SSµ.ƒšãà<rlÁ¤ê)¹,äųR“:ÃàIÄ™ÇÁ¯´ƒ]ºèïÕð§ŸVψì’˜É(`ÙpuÇ¢V“ˆ˜9”¯á†qoÐLÉS•–Øiœ¡À£ƒ0²! ^82¸ÉÒ ¢u¸Ã#yÓtk@ÄšLÀ}¬Ì¬1ø3I6Cìð0™D. 5õ?7\ ñô¬…ÂoþfrÝÕFAJO:¾’wv¹µ@ÿÑ\I·0æ² .3Œy?Yø¸s#T»lOÜcɨÏõ™‹ôy=•­ûµíŽß‹ê€™‰LUاôÄk\™AÙ_–µO_™@QDZš0(¼’çÅÂY5høÓMC”2r¼“VO@ÏÅ=˺á¡‚[‡ÀW> LÈRìdpøŒ…\á=v•ššîxGÕëNtÂÍ!â…ÆpàO>PS¨£…Öñú®DOA"^Ÿ“½ ‘¥Eø µ?„Í”¸!#@ò5T©eèCkÜøÏfõ/N/ê_|¤ñÅ}ÞæBmë׺ûc3Ö›ƒµaœ~}ýú¥{ vsäŤÎ0BCÂÝOd">‘Ù2á©®{Å]'\gP´8:|N €™d'­¶Y3`áÏÆ1/vÈËðè73©^@? VLfó5ΰOœp¦˜ò.£¾ÊK7²ÚÃܨîýØ*Âép4Óƒ¦ÀÈÑÆS|"cäòFB7Á¼.¼m®ÿ¹»‚žê×n$æ+ g!î@ôUçM.=g«)8ì@ˉÉ÷øXm•÷nÖ.-kà01Û#\ó£AÈóI¿E€‡C…zï÷£D1ÖH¦}3V¸~¬Û³÷£Î½šagj…v½,x(X5×Kî ÍÆâ¡"’²X3þ 5áØ@Ñž$“¥Á{¾£H ŠzÆmëu/¿ H[þ²ÎgDO½ëo©%‹Ñg½m ü ÛÿúR $Ñ¿¾yaÅ¥ÙÄþ…²‡RÁ\2MêyÃ'4yÜ”·™†6ÔiŸê3Æý¼9VnÞ& O˜°a&Ö–‡Sé<ý³X$øa¨øÂË£ÙFTvA*ø!‘Nßàb^’ɹ¾(—Œ­QùÒ='©ÛÃq 8 ðþ‡˜ëÂ'‡a÷Ø{ …É¡,€ ÅÏ?íÇëŽ[w…¹Nñ|¼Šâ³Û°cÛüë4 SÞ~1ªø¦sj^ûqƦö¡ ÷Ålù‡È'd0Rªà÷ì 2¸Xê¿ 3/|A¶‘/È3BçÁS(ï ‡B[B¡É¸SHÃ}þ°Ý ãendstream endobj 258 0 obj << /Type /Page /Contents 259 0 R /Resources 257 0 R /MediaBox [0 0 612 792] /Parent 245 0 R >> endobj 92 0 obj << /D [258 0 R /XYZ 72 744.9066 null] >> endobj 257 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F35 25 0 R /F29 12 0 R /F39 52 0 R /F36 32 0 R /F33 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 262 0 obj << /Length 1666 /Filter /FlateDecode >> stream xÚ­XmoÛ6þî_áo“šã‹HJݧôeCº¦Éš ÐmѱVYr%z©ÿýŽ/’%GN ( ÒäñøÜÝsÇS^ÝL~þ•±iŠRAÅôf5%D"&%ŸJB`$žÞdŸ¢ßg”Gz7#8ªêlöåæÝäíÍ„L1ü#S"1J¥€C8A8Ž“ér3ù6ùôO³ ž¾›`ÄÒ„Oï`BҔ¡M;…kRÎé´˜\Oþè4Î;•ó¾ÎW÷ñJ‰gñï½R»Âã¤$F±däqv*€“RŒDœ¦Ç8›eoM^•÷| r,µ°„“‚Æ: 7“Ð,’v娩­Îy_©ËÇH ÒQ)¥ÛhýU- }2úB$ü¯2ŽÁùéè÷uŽM`Î8Å'ãþ|q¿‡¦cq ük­ÍZ׳9# ÊŽ4*+ã`ËOòr»3~³1µV›°Üø± È/ð3Ž£­jyqS©ZÎH$›“¨™©wKS…ûW0‡]sOrâ0º£”I@at]ªÂ ù?žPH>ìNl åòUîrä. M9 ’Õâ_½4h6„D¯×ª¼µÀýevÑ3§nlf¸ ŠðK¿•é•­C.ÁÝÖZe~g¡µË#03O"Z“¨»– œ,•4Ê–ú»9Ít0<‘˜?G”¡nz€é=cL9‘XF¨ù¡*õi²?ÈÙAž {ä'‰£Z7UÂêW< üܬU˜ÝåEág íGÕ|µw±¢Õ=…­7aÑŸÏýJ¾ cÐm3ÇŽ.ÕìdUíÊ 6/‡Y@{YÀqtq~ñÖϲj¹ÛèÒÑ—â胶ãßsô…qH_X èqäó¹·«ó…j¨´ÒáI‘ýq¡=¨|ˆ},E“ôì{.ˆ=òA<Á½>ÄO 9wºY <Âf8Ú5ža$º[ëÒ¯yŽååmû³P&·ñ>ðÎiüiÆyÔ@!¦)ÎxžáŽËpÙ~›/UQìÇHf0ÉCµ–V;\¡Šû ‰²:ìßçP^ᄇÒúº‚r]šùûj©Ú¾âÈUð6¬µÊ #c½˜Íc,\ÒØÛ¶`¼§9a"=ðÜ"ÊÛ:›Sh8ô=É~‹& ´KB¸çANeYnºS.@ýqÜ|‚pÂI°ær«¾íÆ –]^ìÅØc†Ò„´^ùè?¦(&(‰éyàe6¢‘‚(O‚äßïG´kãÞ mA•5Ag3×$.9íò¢²îõ>~qðŒ›¬ª¢¨\œ1<>—&£ñâÑü>ˆWQ-0Òo¢û¥­ùvk0×7»r”ð¶1ŽsøÊ <°Þk†Ùº‹ß‹M™šëñ[؃V§ß¡w]ÔBöÐD"‚c6ä2„t<ž*ˆì¾9ŸÆ~W+é”Ç óW˜“€óóž"ßÅŠX)"„ú¨3å8I%³É[ã>œd¥îÓƒº÷iÄlI‘ŒãÖnßÂÚjèmïr.dÛ¡lªlgK½½â3¥ÒÏV3¼2˵/Q°RëMe‚œ­R­·þS®ïÐendstream endobj 261 0 obj << /Type /Page /Contents 262 0 R /Resources 260 0 R /MediaBox [0 0 612 792] /Parent 245 0 R >> endobj 263 0 obj << /D [261 0 R /XYZ 72 744.9066 null] >> endobj 260 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F39 52 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 266 0 obj << /Length 2242 /Filter /FlateDecode >> stream xÚ­Ë’Û6ò®¯Ð‘ªŠh‚ b÷4“uÊÎ!™ÄÚÚªs HÈš"‚òxüõéF7(êaû²¥ƒ€f£_è'Ä2ŸXªt©D'RÉe}XüµøãÏdÙ,’åÏ‹$ÖºËgØ$q¦K±<,²¢ ›vñnñÛB05ZÏ)=n¯~J‹¥Žu›Ý2Ói,u©—,2‘êå¦ù#úñÍÃÓæõï«?7?¿ú)Ë–"‹eV¤x@”±NʸHR¾yý ¢.^o&ÖÀ¹ÈËXÉÿA…9¥ BšÅªTEJ‹,ZeK'.”*½Pÿ²îXõÞvVëT•QÕ5´xÛ­Ò$ú´Jó¨ÿˆŸ½š úÙ,kæð4×À»LóÂÓüÅà¡g “'‘íèÿÓJ䑜í bM™Ïh&@UÅE öDZÿ}÷öã4‰E’K@F뀢(£]_ŸœihãÙÀÿ±ž^9”ƒÅÓ™¡ùƒŽÞýº’yôðD_ƹêƒq?À6ÍΧŽCZ|²a–­=Ø1°Ü­DUµmíhÍ$Ó@‹æÂÐ{b=î wúkÔ܆\ ë<':¶YÉ "n²h¶fXåy¯ÖRéh³÷Foô/£­©+°Î‹‹BÄy<’o[¼È'œgÔ´>2íg;îý=¿CÕ¡^èKÝZÓ´fÏ’‘3{1Ý*±CßÛ›t˜ðÉB°˜ÛЛI”iœ&Iì$¼tn|i½ýÁËÈþ°"Îв±;tÐH6]‹@кb_Ýš '~¹CÇûòÙ{óY$ð)Äín¯ Ïã²Tß½TÊ€c»º=‘J¹þ`hLD;2!,,é‡Ý×à÷>:¾;u5îúM"£Íª úvrL?à@„àUðí‡ÃÉ´ò’`ǕȢÏÇv,k;¶ŒhÇ~€8a*•£ëSE,Òóí‘—»}ïÓGw™?È rÏ">W‡cË€j¼Âpc50¬ß…o–ï´$q¸½/Ê6O"U(pk-Ø*-¢÷IžA¡« "hëùÎwXÝVÎù›ø`Þ'‰4õè&<Âê;gH*¸J€3ËRð\Àƒ9ô#ó…R›æ4ð¶®ÚÖMšÎ¬ŒÊüþô#jp×ý¸ç !Œ¦ö꣉ç!Œû}5„ëÇ@ë`üpE jŸvÆ]ÝØÁÔì;\‘8s>¹éPÏH'8Þ¶¦œˆ®2:ÓîBQ‘_/*$¡]„w(bbÿÞ¼¹«PѵHBíA;z7¸SSäôUç̬‹ÉB:¿° ~€+JC°å¢+¯;àCÍw/å€aoSOž­øs[5ÿ¸§”Æõ”]º¾3÷RP—y¡C Ú£®§ÿÀbJ1öµ¢bUÎN"±4—ÖÁÒÚüóž€%Ô¸>b½Çã¶r¶¾#d® ©(1RÊ,z³Ù<ÑŠÎùåÌ,^\„MâJµ“e|Ú’9†è½ê© wÐM¿/Î~U0èx2]œ»%¦Ñÿô·Ë€ˆÓ" ì¾£ z§3†-žÉ8SàÞÅrkZrôbNhKç[£àkbnL2hl‹â²ÌaÚ¼c™2–Iö½š¦²,˜ÄÕPh0öËt’ÜoȧKAÄŒ‚|q}öO•¥ Y Ð…œª–Õý<À`[þ,Ÿpoª&P4”ýïÕj ÖË• B?â <€íïݸŒ•.CPañÓS6öæce»I&oà,Éâì¦(b¹´LŸSð²÷a¯ÞSׇ©Ð¶ƒþ´­Úøì‘ésÚ¥ @û‘gpåGˆÈ¦âB¢"\›ãH†oB½’fÁ9‹ù’Þ˜£é0‡AƒpQœÈ'wC*Aw!)¦ÿ¡êvœçÁÒ³¹ I§Z!êÀD’$ƒÎíMÁ¹TÅZæå·ZgzžñÔmÝR„´ Ê€{è›¶+2STd 8Gû—þD ¼ü'Û{Çž^ƽè¬<÷kL+üÓß³ÙÒ˳­ ¸E‘êj<ãr–ñü÷œ(4 Ї׹Ún7@ô §z¤îB¥äPJø+€ö¼Ì_'ãFßË«y[ øtn†ìGŸóx#¦‰†=(ð4àu´-mÕÚ/|f6x {“ñü [µ'ÆÛVõǹüé¤ù•R#f’ˆñ;§¦3¢ ƒÂKrþ.ŒÀ϶m‘¿“Ø.!“|š[9µ ‰ÞîèkÅÄÏ1ÉüôúõiÀyJ&ÔUÚ,é¡|>ÏŸÚñ^“ÈâÎ 75d,å¬!›ÒJrŠÏ@’⼫TrŠÏ›¥ç‡G³¯ü„í÷•ˆÅ¸×$ê#¾È ÑŸ5ò’ Ø ³ÐÅø?Œ>âI Í´WŽøý¥ßþ¶ƒ9ÆÍšv€ùJ4?³í–lè{i*.° Ž¢Œ—¢q€YÁ0†·´çìûŽËb"E„}ð»ìÖORª‘„õõùÕøä{,Ž8¬¡·‹žkx3ALëèxƒ=¡‡|²Ì†ÿ£äàŽrŽï Jì ü—ÕÂ?X Û_Áb kð¡¾ÝsÎþȉÐ׉óô­*(|Û0#†)r–‡æcS97ÞågÑõ OvAûæYa;sbz 1qáÈ_Ñ2åÕB#@q¯¿ïò~PÔÑp¬iøæ¬OPŽ]Û]?0”ü€ì—xœüR&a&$ðHÊf`å%Òs³ /ÃëŠÎÅP« Âû4Í>:\Ð7ON&³‡,zÏò2wõO'¶>îÞõ§Ã—‹B‡"§Ô,ÎqwοR±/+uZñÅW©©nxX éE§%Š}ñm’7–ùT´ml=ò±þùCkÝx-÷¼—¸z#γ8)àÿæ‰Xê2ç'b¡Á-±ßÜy"žº}äÎaÆÒ©PË ÜQ¤”P¤ òü Ê/°endstream endobj 265 0 obj << /Type /Page /Contents 266 0 R /Resources 264 0 R /MediaBox [0 0 612 792] /Parent 267 0 R >> endobj 93 0 obj << /D [265 0 R /XYZ 72 744.9066 null] >> endobj 264 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F29 12 0 R /F35 25 0 R /F33 19 0 R /F39 52 0 R >> /ProcSet [ /PDF /Text ] >> endobj 270 0 obj << /Length 2655 /Filter /FlateDecode >> stream xÚÕZÝ۸߿Âo'b†"%¥OI.i“K.ÛÛ= EZ›ë"K>QÞí¶èÿÞ!‡”)¯œlPEŸL ©áp>ùÙåÙã—¼˜¤P\Í.¯gŸeŒ*21»\½O6z¹.›Êlæ žÉmU×v”'}w‡¤¾E‚Ñ]UÖÕ?5’«É¥Áç/ún·ì‘t5ç4ÙùuÕµg·®üø›'Më×o[cª«ZûúC‘®üÖƒ$«|~ÚuåÝ\É„Ì)WÉùœÉ¤ìLÕ|Æ…«¶Ñó—¯gt¶`ŒR2§Œ›ÊžBÒÄÿôw[½lWŸ®»v³§›M»ÚÕúRÚŸ6v¯°¹`4ùŦ–íf[öþ|ð|[õk+Äã—BEâ2%gÈfEZµKÓßÕWŽL)8QiÆüBâWļà°‘ª˜-`-+Òü[,A<%"-¸[ù¼¬ë«rùe¾€—½X!“ª™§4¹±Æm¿ÌáˆÖv;‘[R"!(^¯.ÚrÞ6}Ù,5®èô¶ÓF7½³¥ôk ;ýÇN›Þ*˜—f…d?o_íw]ƒD–Ô;KšŽÅ. ¦ÎU,åooߌžçÉ*éOïÞÂ#H¹\»©„0»ºGbÕàïmWn·Î7¹÷Mî}ž»írÚwmLùÙy‘G]"+ˆÌså-ý«6Û¶1“.CÊS¿ÐŠÑ¬‚$.Žíï^v§àXèn.Ñq©pŽkU^\´`ãPy 7+ÃÜËgŸ™ Âó{NèH@5Ö%?PÊõꞣmPËÌCEƱ« ʳ"ó¡ðéÓ¦¬šOŸ&,,)I¹ ÷GÎî˜.hSEžJ5VÏ•÷6<¼×á×-ªußv¶ßœWY-9•ŠT&[,¼ jaÁ>jìã<"%ó‘b_Ñ m“ÓMŒ.oÙÅLÆö¬öA꾂FL¹e:¼vÆú¢ÃK.¼ÀEw®Ý¯(2#4•êÁ%Å4]†4 Z©CR÷{á`àµc×ÚqÅ-dô@;LŸQÒ?ÔÒHKÙš0¶Ô”#k–隘Q"¸ ï{EQø¢%~[ÎPaìlY÷LðlY08ë²l»Öú¦´ñ@·‰…ØnÎì¶Û¶ë ²°¾*mUµsÏÿüÊ/ZvÕ¶7lp©ý»Ý® [áëÀ¿Z–½öïÀCmwøìËš] Úv“‰‚¥DR)½Ç<&¹¼<¿æÀø¾ºrE(ËÔ(ÿ:—!LåÂÃXT§Ó˜ƒÙ×msþwnh;(8!Àø´(‚K¯û~ûäñãßÛf{GL»ë–ÒígMÝOEƒÊˆÈTè%¿ÅB!%…ã€ôFC/|é`¼éÁZÞÅ÷°Œ(žJ÷êS+ntŽ4#9§!ÍZü3ˆË¬ÿ)çÛ²è Ý÷) %Y÷X\ðã³ ˜ ’œme¦ø¦9ÀH&ü{§ä‹[ 6•»Áú*ÏÒCÜáЉ,’e§Á? “U˜Ló ÆWMq" 7¼öêwí®Ö²ð¥·p„2Ñ‚tUëgúuéÉm“–îO‘|à\œ¿»¸„ß§6º_·.5‹|%©…cγ—Ž";P˜6€is]sëš!×=4W‡,"€ OÀtYy˜#Öƒ¶à¦¤0íï!ÀLé0}7 ­=b¶>zy(»9Ë“Ï;{¿Ç¦¼»_Qžxw±»`4À"¨WîÏv_½ßÞ:{qyf…ÎØŒe)I™šÁ%ü,³Üœýqöþ#­Îèìõ”Ž"—³[°¢°þ¾ ÃàÓõÙÅÙ_†‹Àq³|f›K#YYy È‹Y@ur}m¡Ë¡\Èäé)¥X~CL.sÐ%KÄÄTaáˆE-àK••ðdF‹ã’μ€›³n¾)U ˆX.bž(é(ñSNò<å°5%Šr,ó.3³9¤bÊóžÐæËû"B>'8Œ$ÌéqsŸLÀÈ܇޲èÞܱˆçCy ®®L¯&kÈDê†L A'P"FÉ¿\­º£ö ’PEÕ)í±üŠ=hnÛƒ(á?·ÇÉŒìq(á{Ä">%ê’ÿk“Ä=Î)³°BFå)ScÌr"’á.*-`gúÊí—emôQËœNƽeî 9m™XÈÿXWWU¿¯ €LËIþ€–µ$Ld^é5vÒªÖ7'ì X•Pdcûú{ߤisF˜„r}BÓF,¿fÚ¤PùCl{2!#ÛJyͱ”ßmÜ#n È™ªï²«½3䨫9iZU€.дË Óæ”È‚ç 'YÎÔpq í¹Gáš0mæ“ ™ùPâ#fŽ%~S°Pö¾ké>M¹žÛdCÇ3dc¼AØ…e3F­ß‚”¥ÙToqÒä©$> endobj 271 0 obj << /D [269 0 R /XYZ 72 744.9066 null] >> endobj 268 0 obj << /Font << /F29 12 0 R /F36 32 0 R /F26 6 0 R /F35 25 0 R /F39 52 0 R /F33 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 274 0 obj << /Length 2306 /Filter /FlateDecode >> stream xÚíZ[Û6}÷¯ð£]Œ¹¼“ Ї¦™´I·I63/»i0e9V×–\IάQô¿ïG‘²)äK!`ÓE0X’ÅO‡<ßíÐz~?úÛKÆÆ $•ãûå˜`Š´æt¬0FRQ1¾_|˜ü4¥bï§O²|1ýxÿzt{?"c dLGœÈ± ÂZãh3úmôá#/Fxüz„ ´?  c6õ!!(‚Ž×£»Ñ?gµÅ™oòùS´ð­ tÐDû"^†»uÙFIE„ò!aLžÁI…F ÞÆYDy²-“,mc $ °4P%’Zñ~¨c‡p3âR"*`ÑÜ•ÖÚäÌ·i¡Š.0­+¨ù6ê%]s¤¥C’î™ì@h$¨M„/Ãu÷S>Hò6JtQÞ@yûŸU2OÊ)˜Á“rU†éIo —ˆÂ@ñ¾eœ¤–îžy¼ §O>'Y>b‚œUÑf”@¨h«ìæeFn²Ån½Ô* ÏQdHj=“ÔjŒD@5ÊÕæXL’)™öpWÄ {ô:؆yNpg ¸-íUçÎZ´ w¸ˆÁ˜¦Ií*`Ô¹ |Ylã(YîíÉ1³øKŸzC”-âŽü"`õa.¿„e™'sãs»2îN.…•p Õ¸´X$QÙëi ƒ“‹gò©§Q¬ ³Baã>µ]„ßÿè÷¬ÁzžÕFØãY>Ä7á&.¶aäR€YSp€0ß»l‘ÙÏ"N‡$q¨/ÕÁÝÛ)“ïÞuPgÖNc?Kõmú9^gÛÚ{|p3& "˜›œ ͯF|Wü¦‹uœw ©@×ndbº£Þ (U—²|ÊÔ$þmå·o²ô蛄#Æ%­H¤§ñ¡«„š„]Wлß|cóå"mÿ˜UZö¢”Öˆ>vÌ«a¿ÎN-.!sSš1粄)q¹ÊjÂÜ5—"àè1)W5¡ýx¥ïþiWnÅü/êÏœ¥ŒVU V1/c®0Ý×.±ÌÖëÌtõ‡*äÖ‡ˆÉ±Ñ·ò)Ñ“O»Mœ–5úpß,Lú3·Tì)»3ÊM£.¯QB h©µ0Aø&O¨ !5té‚]¤&†ƒyL§qÒD çY5!¤aÓ!Õ„oó„šµ zPå6Â{‰‡uPL Ùvú&»*A‚pÞDYçŸnÖÃè±ÞÙ] ¡ÙØš8ÚC6qùâÇûûwïÝ »zP”aÅWtŠg„€ú¤T0¤Ð÷Mžè7YU^Û%Ø£«¸‡.ñ* YT”û~U (4Ä”šŠ=“'4¾`î'ì?Hã6ÊŽ}”Wk|õ[O`¦ÔUBŸ)qAš ŸØÀ$j'²÷Mž"—B›+$½„ÜÁ@zä¶Qöë£üÂ6p.Pô yàþ€¨è}“§r5ž1¹2U‡÷ÈôÀ=L{€¿êù+õ<×ȧìÚ|“ýzžkþ†Õ9=?@ϱÚ»«ñK×óFhî»T/Aš3òÿ©æÙ95Ï¡Âc|•óVÎs ¢É¿ù&OÈyN@WI¥/’óÃÁô²ÄIœÇ,ÑÄyVÎs(WJS5¤œ÷mžóCOD8¹DÎ30‡ì/}“'ä|åI9?Æ#ëO@öÔä¯Yjå¼ Ã?/ãÉ%2žAYÒŠò!™ñLžh ™ÖÐSW¶†ÃáõXjîfÉüñLAlF ȶgò„ÎcJB_Í.ù¡~8Åm”=û(ÿj"žIlFÙ}û&O‘+¡·å®8Cî` =rÛ({ÈõQ~1"ž\*âYådÈŸå}“§25¬´ص®Ãö¨n#î¡ÚGüUÆ{2ž^ ãR ™H<“ý2žQmBƒœ“ñÃô<«°Ç³|ˆÿ;ßT¦ŒI˜¥e z•ú¬2¬¼Ë‚[Ù¯Š†4-ÂÍv}‚Ïø4OÒ…qͧA$AyN}»3 #Ÿj湟³Ü81&E¶…2P&QXÖ;2V\öûÃöGµ‡¦¥½\‡0Ä€½FÆü(†‹Q5 {ApC§A(9¦QÈÉ”2§cÌ„ŽyµÃBfAù¿ˆ}‹¾endstream endobj 273 0 obj << /Type /Page /Contents 274 0 R /Resources 272 0 R /MediaBox [0 0 612 792] /Parent 267 0 R >> endobj 275 0 obj << /D [273 0 R /XYZ 72 744.9066 null] >> endobj 272 0 obj << /Font << /F33 19 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R /F39 52 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 278 0 obj << /Length 3138 /Filter /FlateDecode >> stream xÚµZ[wã¶~÷¯ðÛÊ9‚ É“ws馹¸k§éi’“Re±K‘ I­ãöô¿wð"‘²·G}°‚à`0óÍ Àëû‹O¿RñeÌb-õåýúÒÈK#8ãʨËûÕϳ¯Óæfßl®~½ÿF†½‘`Q Ä%·ã~á!‡?AeŸä\h+BC°8 …ýà~“ÕWsëY•6ûªp þ˜Y³ßå)õ,Ë¢I²"+è9+ÖeµMš¬,Ü'‹rßP³Ù¤ôý2ÏÒÂuf+hfÍÓ•gìj.c “;â¿p.«Ú Lótë¾2³Ç,Ï©{áÆ–…o¬“WbÖNXu“M™¸µJ»ÖuUnabYE©4“7N”7?ÞÿiDŒ™8vƒ–yR×Ds•ÖË*[¤+zq\‰pöÿ¥°^Åõì+|(+`fº¿¿¥¡ÐsÌŒB¦„Vn¢¿ß½c†3Å¥³Hêléf° ¸—VA×ÐpR ¾ #4NW‚ÏJzp¯‰G’>ö/Òä.çRFL˜XE\$[òYR¬¨± Ñ •ï©H4€׳x¢_âæä2€± X̵†y Ó2¼}|7"E³(2ñ ¬¨FB WóΛĀ7\c½K–îñÇwoý€¤]µ3Gg_ƒ ]SÛbÁ ‹~Óí®q¢¨› Æ!p@td¥–¢ºH=¹t½Ï©½öôuU º·D>BŒïÒß÷)˜â±,ØF/¥ X¤¡q$Ì_ "¯­Û¤ªÓÕ]™ìFæÐ’I ÎŒ†–‹¦K'gt %dŲÜZ¿…O­Š…+“r(…{ÿåºÌóòJ†`þó¤½,®$¾I‡Š­Òd5/‹üé³yóáiñ!«ÀsŽ˜t«—žình†U¶DsNª§‰¥¦Åع%½m÷WTY²ÈÓúPþw[ÖÍ1¢Á‹Œ™•Q,й:7õ›¯ßžD0¥”w¬!¤+M&`L ¥ÃbBñZ1“±¢PñP‚—çœ[ y®zSÆQë›­ñL†L+ÐÛ–«=F9i¢Ù/RjÕi±"­ÃÃݨñ›[z󯓇´Ì\@|Ð<DIáÌå¤÷6¼…;À4ßCÁ9b Àvª–·xÖ”ô 1® ´Ãß™Ð0ªÂ–Ñ:­œ' ·½ˆäzlBÌ®»UÓg'5¾ˆ´sçпC«tsoR?¶ÞAàµaóÛ†º­¢a™K–»n‚=È-XšJ¨†ñU‚!ŸnŸšM9†ÄH±P´1{Ó4»Ìs‚qk7W3r ¹ô>åMY¾ÏÒR*‚P!àA³ âÈ®ÙÝîk×Z¸åPÄæ–Y“?Q_¶Ý•U“®@ÄJBÌ®]wA¿ÿc1VLEÂóH‹„±ð`8&›Óf¤/0¿¹~ÊW)HÖÞÄ_õ,ÕD¸ûQèóEä²U´TfÁÅ—÷H‚_ ø,‚à ,ˆ¤¸\n/~¿øùW~¹ºà—ß\@2Gáå#…,ˆUÔMl¯Ô ˆi<ä<,†V/Ù;öíhŠÐcë·!ÙA|3,’\÷"h+ø¾wb±1~ÐÏŽŒî“8l<?ùä=&Wé•â³§GH m[Õct!ºÊ@ødñ×1þú„'Ë3ÁeOšÔ½LÜra¶vÀgëÅà÷ºç· œ¡Rñì}A¡Ø}’Ôþ“cÁpÂ{ÖÅ$ÈgAÐjÎfé¡ ¶@Ó4ëza2OÁ>l“'±po1Qkí“ûí>o2¬ÈÓi˜22áABtûÆçtyîóë´yLÓ¢÷âÚÇçU†edu®#y:Ê]:mʼnßo’â!=È~|÷­ÿ®Íjvü»ÝŒi³dm  ¸ì9Fä"’W ÙHÍ’¼.©«Þïȯ}ŽU„µJ?>XÐgšyR‹dùžZ”ºDu,ù€ÊÊ4æïÒf>é«!M Û»­ƒT ¹OC³¸2yplQ”³•cÃF?xoeL–ƒƒutà`æêý¢ÆÚ&ÿE“V‰E|=*ÔS9§3p0ˆ§a!•TW"š=ì}Å6…ŠÏF\œó20JH|ÿŒó¦Ý$‡MëÁÜ¢ÎM …œ~ƒHËïé:C;äS“WAxF6=Åg¸TàbC)ޏÄõvœÆš’}eã“6/‰ˆà¯XdÖhLô$ç}šÄê ‘à*cÈS!Ó`BF€Äí1j]F˜6‹'TW‘Ãi­÷i3)AŒ†Cú?`ã&&/¬(‹ôÚ‡©1œãG ãI €>ÃP9ð'´Ÿ†Oäã°5Ü«Á¾°¿»^Taöocxå÷ÊF6¸¨ÒË÷02¯UoÊ}¾Â696ì³»g¶±¦–n`=±ß:³ý”Zâ‹ñZý`êéݲ -mfÀƪ&i$ã*ÒÃZ ¨±àÆ£ÌH}„v1›\Àcæ¡p cå¯aÒö—ÿþÏ$üÎÆ`¿CþÆá7`ðûn¿Êp1ØD0œ’ì§Ò[Äì›û¤­*Ÿ…Á—Ň4/w>ï ÐXŒŽ©ËdG¡pZµ >Oó„jC(°BIœ¾z5©Ú³1Ø©ö¿ Õöü«­ÝÉâ€ã6b1Ó&øw?ÜÜÞ´z8¹¿æöª°Ë¡BÜÃ1døŒÂn• ¹²µåÓ¸ÊÁ×Ga¨ÎjÍ=š#*k¡høÀ¯ß£‡œÒúÙxì´~Èâ„Öû,¾q–ns~ír~-fK¶Ý™„¾/~ønnŸ)•„ž¿}÷-5H%õçca¤Nk†U/…qùì)œ . þ2ÿÃFîtˆ ì @CV«¬yYÀM ²>'°:’§p% dÚ<«sqØÁê€Á Tõü’N~n«ò':®r8Ã&á [ˆ3üõ8öE6H‡¨ÿT!ž~²óU ”jé:ËÓIL AÂès‚ªOóªp 04:xUç㱅Ջ㸰xƒ)mlÚ3˜Ü'¿±-ðM…Käwe,¦Æön”Aí.À6m6%î¤*ÀS Ü–À™v¸©€å³ÛX¶ÀÚ±Â]í6z%t•.¡n+R׃Gx‚Em÷Z'¤5ã&Ï™âôi«GD´ÂA ¤µhCû›v;îS|¼ëž'±u6î;ld¾ÃVŸùNÌ۠=©$Ù}}²Äae\ Îª¤M»N òPPR9š 3‚Ç´Ïÿ0©ˆ³qØ)âÁ Eôü˜-ª6Iì[÷Ÿ5Y’gÿJº¤ô%zÜWù´aUqV öh +‰hð‡ CЮŧɤ ÏÆb§Â“v*ìsØî ûÝã]{"Ü”ìåÚx¬oV«*­k¼1©1Fg­Ýû4ÇÔ™1 ƒsý|ü<^N²Øé¥Ï"ˆÑ†µØÝ ²‡5õÐæMÀg?ÝÍÔéE½K—v¤ßT²£Ë±lOç¶xöðäó²5Ú°ÝZ%Ãl^aÅçì·(›£ü—£Î~Û$Å*§Œm\3ÅÕY ÿ>ÍS¸€T0ŠÝvüI\œÇ'YìpÑg‘J9PÃ]öP$;rÙŠ±;æÀ3½7dPAqp=Ë´ekw16nBÉf¨ì…Ò’Î?ßÚ wŠn0a3˜ÝÝ}{Mã9»†¶‡åË´j~óyõÁ"ÁkÈÓô %ᇼOŸ¦háNJ ý¥€ÑØ„,ï’*¼Ñž¨ábìÙ ¾ «†Ê^]KWô½¢_'5|îám;í&jµ_6t§ah" ŒYrªÒ‘1S2öüÒ”C©)fâHõ0aÝ5CkÌM’åÎtÝMl&z„ã­\ÚØtƒžÙd’¾ ØK®d(¥¢ÁE vht A:µ‘/:ÑÑı|?ïòw7n1h w7 àxàÆ6{³Iv Ý—‰ðfÃÕ\K9û"«wI³Ü´W„Ü™hö¶Àë.v+¾|ïŽqEÿ=ˆGendstream endobj 277 0 obj << /Type /Page /Contents 278 0 R /Resources 276 0 R /MediaBox [0 0 612 792] /Parent 267 0 R >> endobj 94 0 obj << /D [277 0 R /XYZ 72 744.9066 null] >> endobj 276 0 obj << /Font << /F39 52 0 R /F35 25 0 R /F29 12 0 R /F26 6 0 R /F33 19 0 R /F36 32 0 R /F14 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 281 0 obj << /Length 3133 /Filter /FlateDecode >> stream xÚµZYsãÆ~ׯà#å²à¹HUdÇ®]gmoVt*U¶Ë#6 Ð8VQRùïé9qp j+Ê‹4 {zúüº_n®¾ø†d«,É«ÍýJ’•Ä(ATÒÕ¦øiýCµS×7”ñu~ýËæÛ/¾¡|´š’„ø=2ký²¬Š²z° 'd9NÏüÂzû›Úu–ì>oí`«T¥Gb½kTÞ©âsxÙºÛ;îëá¾&|ý¨÷0SǺ(Fˆ¨ÆÉ›À-Aëzu^òíA%×7<ëÛÃÁ.¨ïí ´Û6ªë›*Ì:®†#­nRšð”¤«Œ“Œs<: 0K8Z·µýßíóÎŽŽý¡+OåžÆ ë‰]^ÙÁÖ­Øíó²R…#S?(`¥¹æ|8ùÅŠ€™¸aå¶(Þ¨¼€õçªâ4‘YJœ~F¹Eb¼(ɤnÍޒ¯Ýé>æ‡^Åic‚è@GLà&•I–fÜKXûê»Sßy¡9´'µ³b*"»¥$‘4ͦ\žïGÓ„rݲ¼Š‘Â"I¥nÍèxSJ`å2õby,»ýŒß7›Í{;²Ü´1]ÝàŒƒˆÌëŒrwª»íâ9s ')£ø4ÖvO`hy}UùqüxÊÛö±n®©\Gå*‰¾ E ÑA`F¦jÜìcvçä eî"â:àè~Õ¾îÚü‘°>ÀW+e'´ÓêÿVòðfWWm—W]kçï›ú8¬ˆ0Ä9ÈTz…ßþ¸yaˆ€Py0°ÝÄf‰ªÝ5åÖx'lžoëkÌ!ÊÀ_Ä—ç¬QGpd©ôOOyÊè¬ß#à ™ Bàü$k˜Dºš'«¹B”Cæ±®~´ÍÛrg‡9X+¬)wyWzFмËÝOîG¦g×WÅÈü´9Ö›1ÑÚ8|:Õ Äü¸ã0Ї‡I°Çùþ.rüéÁ^â6}SÆlÃ^‚\pB %€Î&Þ¬Í"D¡îõÉsHƒ|ÚS¾sïïÁ-§¿hÔ½j=ú“"$!)„ÚTÎÏ7ad™QHfÞ"‚'BIñYÄúñû5 Î?Iò‡ÉSqIðiÂ%á—¯95ƒGH£jöòT{—.!|‘Çâ‡H(#xÎþ§ gY‚Ş‚ý ZÕÙÞF6eÈI:X ƒ¬F†€Bñã(Zy×ÔO“Ô5Ç/AlyQx\²}Š&S 'è6€‘gX<‘œ²±¨@³ª`)¦ÂÙ샫L` á¬ë ,kÄ×whåîXùÁc²íƒzRÙm»Fûh$|²$CBLeüV?¦¥gì‰sÆœ©1¼®ê.–„9`€Z¾×™/²9M2ð–ÎËÎÒ ”¹#Ã^d³ÞzìpŒf2êƒ(Ókæ±)»dDRä=òÛ¾.;Þߘü»ßuôSng#ÓÖs¡¹æqëV7j Â¥íç<áDÎ\Å–%Ä—zP) ÚÚ” “„ Ï{W8ë‡[pèÑ8šš m²Æ`¬›H×GHæÇþ¨O'Ù°«/08ömwy§‡R[®}ç¦Êjvƒiš~×ÕÖ‹Y>„±¦î¢È1M0Í|êÇë©öæñ; ,1S=ÅØ4¿T­èxp)KbràÞG‰£xù´á8­OsŒû6îÆéªÓá©{:©?O| 3ˆãÜõöŒ% /†Ÿ"›³DJIFîÄ?ûÌÚô5Eë'ªÛØÎ!ž÷_búÒô/•O€"šJ6Þ:žPdãŠþoKWìˇ= ˆ€Áæn홂í¼õ`ƒLàõÛÎNîòÃ!–ðAÙ`fUñL¨‡r,åÜRM»UѺL—öøÅè4}RÀ¼'Îÿ6qÜBgQuÕAÍÚN´ê–x…`Ф@ˆ:õµüÏq~[ÿ‹¶’'X ‹ÑœþŸ£ù¥º3±EÄ‚9„ÝÐávÁ§2E‘¸2ù ãÙÃôRÈ„£‡nÎsµ WÈI¶ù݆·i¤•(š1ú‚Ɇ"?¤- ªŒ·¢@m™ Au1Üsò™Å:Àè6FÊO&%¿€ÓEÂdîj£•€Ä¬ácá»\›InÐq:¦LZ°ÿãÂK¡&΂ô—»ñ€x(òËÆpÓжÿSÇïÜàHÙ  %ä0’ù¿·ç‘q½”QÊ€Œòï]igï=+¹}†Ò¦év½“”E4Mk»P°ª¾÷5©Ûtž“C‘ïÌŃëIY®2]„Ðó¼uÓõCT¶9.?=PîۡܤçñÖX,¥™ø«ÞW ›À¯®¾Þ\iÃD+¼‚ð“0ÆåŠd4Û¯þ¸úé´*®ÐêÛ+.”òÕ# °ÕÕѽ@WwW oÉ›1Í/õíЄ[Ýâ 7pC$$KÍï_Ô½ilÍø¤'£_KGðBHÆE:çQ·nOêÎøÌ„Íaš,ØlºÌèÊñw¼bB£&níÌŒSOòfLÓ²:…€`SF š0 \×wû_‡k¸êEÅäÛ— Õ§ßeÕhžó %¸†¥Ù”Wøbz5ƒÞç ΪY¯÷1ƒw]c˜29Æ s'ký1ß$KuâmJ€Pÿ2Þÿã»w&…›Ûœäõè +oCgm±YîTë¯ô´ïóÉ à)P‹$©+VŸ$¿®>BØ<¹@SµE¹ë– ‡qH\ ¿ªáŒhF '…2‘2„yj˜þ÷–ÌæÕ f3goÁlÆì}?´ç%Âk-RПi.IdK"=oÊW3Ò‰YúêSO<£>4UtÐ_Ôˆ+‘Ìm€.’vu¡–ÕK)<¨æ^3%ŒhžËO«W×È:ébÄíÝLõE¾¤ÞWc0¨÷YöõŽùÛ\§€ó,‡‚õþ)$û}À!£ 8‡ùíNÞåIDÑ ÊlëL+–Š=H´‚¦¯ªÇ͈Ñ £H€"˜#÷ùǶ}Žà®Wo!Eðpq3‚Ÿ1;xµ;xöxƒŒ÷wóuƒ¹ö?¿†‹,”vw?ܾ¿ jœßl„ˆÐTœ 0 þº—%²ýmÄ„5Ðï DmgפgµLͳÐíîcYÍÍÓ´V&}š¡C1½ìÙ…[Ûm¾ûý×#o[-…Ý.VÂÈÞ¶Ïn«ô·8æüÙªÕ)IìÌÞM¸Æˆµm•Ö¾±BÉ·%<ŽÛáçº ¡ÂpyWÝÀÙ}…aê¿2[UvÑ›ÍwïìÌɱ‘®ûJkØLîT£ý'†”é-ù¾KQš.{2é}–·íí7xÏ{º %Þsâ‡ða†Å‚ø‘ÿȲFâîP]ãhÚhš¶‘ôƸ ÂR­ãLݾðÂY4ŒŒEKé_-fõÁAÊ̶R¶>Ö{u(m=ÀOpÿ:o ºíS[’ËqIu]Ø‘íÄJ]Ëv»}`Ú˜ü·Ô:9äSF~ðƒªîìmKÄ.ܧ-ÙYŠ}áÚÚ÷6*àxT€÷Æôº]×C±ýdŸÀAü‚½#`ÓWø|Å] à w9‡mk°¬ú1iŒSkm )×ô¿ê„#—ƒöjv½…]/'bR€³º|ÿæšÝòÇXðÎ)yq‰qz‚èÎY‚üQ˜.T€ðû›!›ÄôCK‘{lˆ‚tx¡ÅRݦß$• çÎbÚw4ÜÇÖEpnñ3!ÒŽÚð%<€“‚ñ'|ÇEkÄó_~Íoendstream endobj 280 0 obj << /Type /Page /Contents 281 0 R /Resources 279 0 R /MediaBox [0 0 612 792] /Parent 267 0 R >> endobj 282 0 obj << /D [280 0 R /XYZ 72 744.9066 null] >> endobj 279 0 obj << /Font << /F29 12 0 R /F35 25 0 R /F39 52 0 R /F36 32 0 R /F33 19 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 285 0 obj << /Length 2069 /Filter /FlateDecode >> stream xÚíYKwÛ6ÞëWhW*§Bñ±è¢™6gÚéiÜX]¥9=´H[œP¤ÊG<þ÷sñ¢H²©63“…M.>Üçêõfñͪ—iIårs»Ôi,åRŒ0Sl¹Éß'ïŠ~hënµ¦'ý®p¡>dmWä®·/º.»ó¯nšüa%E‚V6?}ó†MwXSî¶X…$åÜo±-ÊOÅu“ü1Y#R‚ñ%¶sÇÃqgð×£”Ë„¤… sü «$‹Èç F…—euýö»«È’¢”1â§67ÿ,¶½¼mê>+ë²¾s}«(Ój2m¯&´Zó'ï²²+žÀE4GÓÔï¶y8?´mÓFp ‰R!®òöÃhÓ¹_œd]ýÕŠ¤Io„-×Lc 4G¬œë·+&P!äEÖSk¾É†ªK¤F>iM8”ñ3ÖäiÜš1“ü ˆ™pÆô‘!AæÌ<(^ŒÚ°½[«E#ÜÎ:ZVb~´,[–’)²—XV! šZv÷ ¦–…ѼÌ]£nF»‚²E:7«?¡ ÖÌ=Æã|¶™ã•ò™‰ý$9=ÒJI?§]1•‡ê¡U|ûKSÇÄJ¡ÄQlÔkR…˜"r~dpa‘˜@4FÌœÚ<&&…ÞĆ'›] ¡Æ)ǘlæ¸å‘á„ݡؖ¿cL„]³¢‚ÑvúÆ=m²0MîM cyÖgÑÉ·n¨ìݳ‹!”I’„G]ÎÀQ†4ÁÁ¿qJ'ùCíËíŠ çGR#)S1Åû²ªÀ}4MnLê×$ Õa˜Asý¬ªÜ”¶èÀ½lX™®õ?xfnáÕC¿küPUv½I‘`8p$z0œbúH¤0£§;»ç¶ÊºÎ"§Fó~ÔU»ðú«•q•3¨›< o°l›<†gÍ´@TQ5WdÖ÷my³¯z_D½nM9 ×éÖ4ÖÞCމz¨†Z@øË´CÓTOµcJ|öÑ$ƒÂ'ãšS#9›6t~àÒ™mGš¯v^m‹‚*0—zÎ ÞÖ[3•)k.xØ“¸æ.ë\㦰0Ù±ÌR–ÚŒcw‡ñ²÷S­l«0Éà_àéu‘›,b”Ê´‡Ëo›ªrÁé`Û½³|ÝÔaÿ™½¼ü¬áÂø'³>+«ì¦2 …aiJéA¹·ÕÖZc]à¹_´Å~LÔC½Ýeõ]`\CÝ—ÞA²Úúƒë-A3Ô©&–Øñ\åvíg\÷X&7Áœßl®0’¾ž•™zØßRñ9äСÚжû À¼„¨ À‡NOuˆ‹}¹/ú¦©ºg#ÈшèɈ‚š ;Ú¾»{é±¾óQä\¸w½œ1Ä×”½Ìâ-j  ÇC†ÇͦÖ`‘T9p3 ˆ®Öcœ¼.ëÜ׈ôØ.g\»U¶pa®êRìIÂ3¯ÊÎ=o‹~»s„™$Þ±]Vv‹a°öK/Ò¸­š0+/º-Hë!x"õƒ§ˆjˆÄçOÁ{¬&U’pW|GÀtš/-˜Æ=oŠ.–¥S ^@‚äæ…7t,E©g%º}!94}áR(§PqªçÞrh›m‘maë;h½Î'uTª³IPnðH‚•;Ìh-Û6Éx-…¨ /¦“=mp¥Þ Ó‚‰6ÿÚ=[s߸öEÝwPk(¤É…ŸŒÆ<2nç©p“œàdɰó÷l @v>ÓÙz‰SJ'"p¶™c¼ˆá‚ñˆq{IQÜ÷Ì‘R*ð˜W¯œ­NîK‰ó.&×ø/'¼}ˆá› >Ç”ÿ!B›kó1E¨Ý“ÂâÁÁË{ƒlZ_‰f†õ©ˆ2&Q”~nÜÅì¹&Æã`^f¹»“üÃ8Sq ?lÆPxIÀ¼®CpO†ë>RPô—ÛýâÏÅûx™/ðò§FL˽‡ÑÚ Ý‡fÐQµ¸^ü:J\"×S™¯Í§•` ‡×0Â`>#ØÁý¾¸ ÷ÓLÅ@/3ˆ|&Ô)N!7žà4YõЗM}Š•(曋‘ ü<Ö¥‡¸_0fâÌÄ9;Ê\O…:°3‡&¤áž§†~wû&ªâ¼ýÁi˜‚+Ä%í?‘ù+h)²gXÃí,nýËEl?åéÿrš))Ü# ý?¤™† H¦É%iÆTæyši”hÕ‹hæaŽDã˜hœà|žfZÎDZ¼(Íœ }‚f®Q¨^/a™„›ÏCOQâÿÀü™O°Ì)Ô'Iæ1mŠ1N2§/Í1Šð‹“ÌWïŸà™PQ™ê™|(àJC(ýB4ÿ2Ñœ:4ø‘àKE_’LÔÇ“¬_O9÷*Æ9E ƒÂ)œ1M5Nþ¶Ë½UJ ¹5?#Ò™ËÚ7–(™ÆõøCAóÑ{´9Ñ¿dMK´endstream endobj 284 0 obj << /Type /Page /Contents 285 0 R /Resources 283 0 R /MediaBox [0 0 612 792] /Parent 267 0 R >> endobj 286 0 obj << /D [284 0 R /XYZ 72 744.9066 null] >> endobj 283 0 obj << /Font << /F29 12 0 R /F39 52 0 R /F35 25 0 R /F36 32 0 R /F26 6 0 R /F33 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 289 0 obj << /Length 258 /Filter /FlateDecode >> stream xÚ­MKA †ïó+rÜ=lšd29ZÙ"EÄÅKéA-j¡Å‹øï]ºe¡=Ê@’2ož„ÊcH‰ É'/{÷åVk‚#X:B³èá§BµÌ°wó(vîÁÝ9>ø4Ũ™:Í;7[HC‹%u¯ &è-ÄR(‹A·YU—W·]{_¯»ål¡ ¬è5Jÿ¡1L–4â1’ ííuûØÞôÝ®íŽÓËð2r¤Øbê4n!Š)'Ö €>¤  c*EÏ5ß>×BÕnûñV3Uß}xú|¯=U¿ghƒ"Å’O`Ë–Íä;ˆ3°£Ó‹Éh TYx U?òüLTkáendstream endobj 288 0 obj << /Type /Page /Contents 289 0 R /Resources 287 0 R /MediaBox [0 0 612 792] /Parent 290 0 R >> endobj 95 0 obj << /D [288 0 R /XYZ 72 744.9066 null] >> endobj 287 0 obj << /Font << /F26 6 0 R /F44 128 0 R >> /ProcSet [ /PDF /Text ] >> endobj 293 0 obj << /Length 114 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶t?«%1G¨[¦XPL x}J 9ñåÄ}§$¥ƒQï,­x[ñÄ4 -!¼¡§Wa0Zámø•®¸@¿š®öÝŸè˜Ø­Qp´BÞ?Gn¬jJ¹L÷íœ#N‰7\ºÆendstream endobj 292 0 obj << /Type /Page /Contents 293 0 R /Resources 291 0 R /MediaBox [0 0 612 792] /Parent 290 0 R >> endobj 294 0 obj << /D [292 0 R /XYZ 72 744.9066 null] >> endobj 291 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 297 0 obj << /Length 257 /Filter /FlateDecode >> stream xÚ‘ËNÃ0E÷þŠY& ÏÄcÇK"ñh…Ä˲€&HM M$ÄßcÚ$Vó°ÏÜ;vÄÑ)Y £\îÂdÌÊ`†`cÓZë!ÔeR,Š‹ÅåÙÍñÕù]Z…e¤> endobj 298 0 obj << /D [296 0 R /XYZ 72 744.9066 null] >> endobj 295 0 obj << /Font << /F26 6 0 R /F29 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 301 0 obj << /Length 114 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶ü+«%1G¨[¦XPL x}J 9ñåÄ}§$¥ƒQßX¼x[ñÄ4 -!¼¡§Wa0ZÑ|ø•®¸@¿š®öÝŸè˜ØÍ)8¼÷ÏQ3V5¥\¦Móíœ#N‰7\ÌÈendstream endobj 300 0 obj << /Type /Page /Contents 301 0 R /Resources 299 0 R /MediaBox [0 0 612 792] /Parent 290 0 R >> endobj 302 0 obj << /D [300 0 R /XYZ 72 744.9066 null] >> endobj 299 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 305 0 obj << /Length 1186 /Filter /FlateDecode >> stream xÚ­WKsÛ6¾ëW°É…jMo™ñÁm“Ö94i­C§®4EœP$CRVýï»xP¢,&q3,ûøö["†‰R¥#ÌRåÛÙ§ÙíŽV3½a¤µdÑ&q­H´q©†I9»™ý>#ÁN†’±¥—³Å*#´„Ïrq¥‘$ZDRSÄ ÕÑru_½ÿú·Ÿ¯ÿœß-ß.ÞpŽ—Ôís6'”!‰©×·Š³×˃gp,…BDâÿ!ƒ±¥!ÊQªRbb#¢­GL‘LSåBúé—ëyBSßäí]Œ@Ù Z’¾f°mZËÏŠ`úØø–ºÎIpæ ?žŠQ…8å+mî”_ê90É#Lþ¤Âôô¤8‚wñ¤ƒ[Ó5uÕ…ÙÑã>¾ ýlÖ®Kvehô΄…ç‰Õ@÷3£U¶ :VXÙ“hâ4€ÓRÈtàÉCŒç °IªÐäeÅR ‡§Ha¤Õ,ÜȈ†£`ò"J¢À•ä¡ ,¥¹¿ì^~·Øuí¢¬Q‹û¢Z4îì‡7‚+„m¸È…òï…—óD‚«›wöö°#w{ šJEµlQvS–µ½Xì=ðÊ©‚ž šš8i÷ܾøÕîºð³}Ý–«wž‡½“ÎL¾q¾œ.ÅÁ TA{}ïVb©VÑHžµºc€ £ÔŸÐê?' n·=ÆÃà}Eþ†x¨„ŠÁÒI<`Û;¹ô°åYõÈL›}0$GB¤ú[ 8Vó A=q¤þ“#ofá?¥©¬±a-d«á<ƒ}§Ù®Û:ø×Íu@pÛÔmïLJ[qÔa ]uоÖ!<.—íθ€ÎÛ‚#,á{öÖfZ‰ðÖ&nøá­í&oí‘¡ó? ÎMIqx¯êaâéÏ¿Œø*‘endstream endobj 304 0 obj << /Type /Page /Contents 305 0 R /Resources 303 0 R /MediaBox [0 0 612 792] /Parent 290 0 R >> endobj 116 0 obj << /D [304 0 R /XYZ 72 744.9066 null] >> endobj 303 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F29 12 0 R /F35 25 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 308 0 obj << /Length 960 /Filter /FlateDecode >> stream xÚíWmoÛ6þ®_¡¹" EJ¢Þp gm±6iåuÃÏswô݉º˜Jú¥aËÄB¦eòôVv ÙÁ²M*O3eŒLU#c%Jb–Õªf8®R³J̪¨„}ªÄE­Î§oõKà¹È³m«òfºÈõ,§{ñ¾®Jý&Ît–Ý©š ²ES¯ò¬å¶h‚‘G]£9€ÛEE3„‰Ó"/k¬šjr[æ)ü¼A}ízŸ|g‹8[ ÜpÄÙàï˜âu™œ¬êºðuÂðOôhkm„È'ìä%§Õe±Û8agà&ªêE¾®Aƒ ,ʸwñ­X’ä­µçÐuÙøÝsƒ J<ó-²ÓYl±BÐ&Ý<Î3 Ûgnt®“Ú‹ù‘U˜xÄqŸúÊ¢Uçêh³ kvÇÊ^b´Šû)£qÔIVë´ìp¶…(³øa{¤ÿÐíPd:ž+ï=ŸÝè:ÔsŽ¢ÄÜæm^ŠLCÆÇ2Ì–¬õ…¶ŽÏï ×FØqÈ B8‰“;Ê=ã?Èãžá8ˆzÐ4j"—SôKô–àJ5°2¾æ=eªX•*Á ͽ ¤ ¥†è+†‡<ÃÝ !"¤º¦A|Øå}Ï@úÁöòºƒ°òÇ—þ¸ä/lÁ'WQ-˜–HWÇ7mß4EÒblóÙÇɇŸ'ÁÔòà4¸_k“÷ŸüIvÇ’¼`œ³M“¬òÅæ«³‘hCU´biX!Ø®ò°@y¹ÔÛ ôÛ(oû–>²ò@íÓ1jÜ—CjÐmwB›Íý•'º(ÊÓ^WÈ!…mµx °1;ààˆþ뻟‚Nå ?þ2_‹³ª³ˆ íN¿?¿ n ‡ÅqŸþU_³pÁÊóSýñ“ô‹|Ñ Cxþw9Òg‡–eØL›‡3õì[Ìð|†;°–~„=ýI‚îpû½ý[õ´x‚ë«÷Ád°z6äÌÿEõÕ¿’þYUäYÅŽ+2ÆK–°ôþ²Ç–Û¹Á#‘,Uì×;±ª†·ôrtÞ½1ĵd“—ÉâT2ϔχÿ–2ÜÇÍÖ'O<<™·Hi2•À±LÚoj!lÃ¥ÒŸÒlŽå…„å·F¦çRy ¸ëzž!§’e»ý"‘éÃNF¾¶'t!¾6àÍmÃÀ?6,bð—²åªšiض¡Œ‹‚Á={Ë/c¤j”ÚÊ«ßðÁÞWG”üº šXiúp>Ge„`endstream endobj 307 0 obj << /Type /Page /Contents 308 0 R /Resources 306 0 R /MediaBox [0 0 612 792] /Parent 290 0 R >> endobj 117 0 obj << /D [307 0 R /XYZ 72 744.9066 null] >> endobj 306 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 311 0 obj << /Length 778 /Filter /FlateDecode >> stream xÚíVÛn›@}ç+ŸÌ{ƒ¹–’ÆV5‰ShZÕµ"ƒ»¬ã¸_ßÅnÒ`ÇU£<Õ’ÅîΙ3ÃÜØã@ÁCÃV)E®ejp«v µK "f×TƒxÜ>Bdh:%„´g,MsM7ºNûV3I;\¦B›§xhZªƒ\Ûî”DÕM ™Ä¡Ãõs?M·ü3‹åâ"`Ï€UGЮgÚžYï@`ËÕÇÁå§x¥ ¥QpÛµ·2Úó/ŽFúàüÊdw,ÍLêÜÏÓ¬ðjáÛ7­™ ã"š±yX y¸@9ŸârYåq’Mq«ÉÊ#¶«Cؤ/ûؾúï·D«Õ ýÌSÆCåó /È>†û"~İ2+ p9ûàW,{õ“çõõ$+D˜E¬‘hýMü|±NÙß„»¿?«ïX3Þïá?Oö«çñºR×vY#›êðBÎÃu°^€ãS/̪͘NvxÇR6g™, $!§1]ÇiÕÅW$žØÒ%™hõi×ZÍ”¸òk‡ì€×ÂOú ÷R=j=íQtqî›Ô"dslÀ¢]çï¾nï¾v—m!ÃòÛÑŒ¹-E9Öߢ}Æïïáߢݚ…àóþˆç+ XÊâ†Iºä¬æ¨A,1€m–Aö¤ë'Ï€jì>b ‘ä™rt 8Ϲô§êëoÄ"ð§òH„ßY!—Y=ŠB>]–á>.ñ5xšÜ±¬Ôíáövú#x±þÍ2Ic|'…@qÈWI¦;ÈADå+ƯφR^Ì0›N«Jä"Ñ -Öžc{×'õ^•¤Ísç Há}±Æ‡Ë?ÎÀ‡c§²âÕcmGù4ñ7æ¸÷bo"W¹ð$òÅÒ<)M)ƒ@¡`¨´¼ZDlxFså‡2ž5Vˆzª:K]Á† 꺆:W:¶³Ù¤Š¯\nitÐ××÷Pîð×ÐŽ(5èö ïfðqÖ Ò>Ékh A¶Ú\£¸Hf§cÙÈ5h •šwó¿!ê#sendstream endobj 310 0 obj << /Type /Page /Contents 311 0 R /Resources 309 0 R /MediaBox [0 0 612 792] /Parent 313 0 R >> endobj 312 0 obj << /D [310 0 R /XYZ 72 744.9066 null] >> endobj 309 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 316 0 obj << /Length 635 /Filter /FlateDecode >> stream xÚí–Ûn›@†ïy äƒTöËA®%'rÚDmœšVµ¬ Á&F² vŸ¾ +i|ˆ«¤½h}³³‡ùv˜Yÿš#O‚'„ÉÛ0ˆìÝÈ&‘MŒ¢&•½p¬ €¨ªa„ƒi¢N¼3xB Ù6czå‚d€" ×ßöýT Øg6Æ((ŸKo°éPæP£™‰ ÖXWÃËOC×sªªKE˜¶aÙõ¥=w4¸Ð†ç×Î0¾ç³$åÏb>‹sgµyü¶3-ŠÔ0¦|îç@l牟‚$»…•y$aßÂΦ[Ñ®ŸCkbÙEûêž®AeY‚ÉŒg>’yË…âÈ.Â"JZG ‡á—Üš²Ó?Úï¯Eq^øqÀ7‚ÖÙoóçË?$ÝýÝU}Ïýgýüue·ÛQ.7©ßrýDÚÇáøYæ/½e*â)uü¸žŒõÉ–àøŒÏy\4”HÔ aº Îêåå‘S¬ay‘‰ÏìôË©_ð{žõàÊû4ßžFC±…¨mY±Q\túø÷f°Iö aU™-[Ϩ+|"Ͻ”H±§"å^ŒÎÝáF•ÇÚe"$›Öñú³âõ7dæŠçiçüÅåF¿Ñ‰ýJz#Ø”ZÿŒà´5záyø_ßuÛštß41ßu§QkãÕH&•³4ô$,HÆUcfè11sé»4ž 9”|&! rjÈ¥˜ €m›ÈsIgV;™I®t¹ÆhÂ_{:Zµ€¶hçÄÐt€:“¦3ªQÂQiÊã0Z¨1-Ѫša0åøÝi³à™HC‰Òbu"ËTŒ_¥HY¶Ÿó^DûIendstream endobj 315 0 obj << /Type /Page /Contents 316 0 R /Resources 314 0 R /MediaBox [0 0 612 792] /Parent 313 0 R >> endobj 317 0 obj << /D [315 0 R /XYZ 72 744.9066 null] >> endobj 314 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 320 0 obj << /Length 593 /Filter /FlateDecode >> stream xÚí–Yo›@Çßù+?Á{q£Ô’]µQ;¦U-«B°M8\C븟¾«il|¨ÇK»;;¿ý3»;šq ‘Kn"ưcŸ‘Å‘Å(¦š¥¡ žÉ#¬c]Q¥T.¿fÊ<¸"—šl옦^{P¤j͇֨O‡E5õ^ÄmcU€çÐÒÛf¹š oÛæuëݼóüÀ­%Ô‹‚JǰfÑ 2šªÞõëåßDZ,Dëó˜¥yénŒ/_ ªjáRF" K 沸XÞ“ºADq’ß“Á®UžÐµZúhý×[ÐjµÂß‹T,CYÇ%0¥ðXÆO+­QcäÃÛ7~CéõOû«I^Va‰ mô»øùÕ:§„{Ø¿«¯D‹åð‚ü:Òï6.âõî)õQnNHw6Üp¹ ×Áz²!¢n˜7™1ߣM¤"yÕRØ‚‚ÙTs}°9zeâV[\’Wƒ!½ ¯“V´ÉÏCš=*õózJó<¤Ö£Ò>€$°Ã{,Gò,Ÿìœ÷»rõ<×ùÓɵïíLv0­渙eÿÏ7þƒlu+ÊE‘—⸬ÅNËZvØsÓ8=âªuòþø•›q:¯Ç%/)buÍb蘚ð2é‹4›SK]IkŽm t(fŽÃQ&é¦ÝuRÉ—n¶üÕŸ@ãMuä@©Ÿ¶8Ò9fŒ³mmaãöCáTM•[¶(pÇå¥Â¨F¢ù Ý0±Ã™ ÕžëþáîQ°Øendstream endobj 319 0 obj << /Type /Page /Contents 320 0 R /Resources 318 0 R /MediaBox [0 0 612 792] /Parent 313 0 R >> endobj 321 0 obj << /D [319 0 R /XYZ 72 744.9066 null] >> endobj 318 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 324 0 obj << /Length 612 /Filter /FlateDecode >> stream xÚí–Ùn›@†ïy ä+¸`VfXäZr"§MÔÆI iUËjL$( /}úŽ XMbc;ÝnÊ ³o~Î ¿Î™¯À ÂUŒÃQý¯ªET #€¨EU?i}`¦!¤:AÚ\'L¹Že"ô±/(Smàpn® H5(Ùxø|èÑ .ÙDT5†a)·#²eVØr)w©Uõä¯ZwƒÛ÷Ïw×Ö›Jճͦ]oØ¿1×÷î ™‹iš‰*f9›&…[Ož¿ê<”eæBX„b@Ni4ŸÀuŠ$L£8™Àή]Ñî¡UZÚhŸ¼Ë-h±X€ïéTäÓYÃ…rIaYD ºQ ‡áÇwo½ ¥5>>oÄIQI(v‚¶Ùoòç•«©8%ݽöS}#‚Hä½.|:Òv–F«ÝK‚¹Ìò¤¾%Íýpƒ<Vþ*“ÒeVÝ ÙtFl¼GŸ˜Š™HÊŠËcH±¨ã˜úú±[nqqRvz¨ 먓V¸I^†ä-*Í—!Í•¼ùe“¶È´È„õ1ï™=âžÀgƲsÝï2=û¹éy7Ãko°Óõä²f˜HGÇ–ýß ÿ®þ#ÛºE–&Å‘ö…O´¯_1øDáÿóFæx=¬ |Ë9¤âuIÃL€¸|‡3å›2#5Rz¥ @›© ÙA;QgŠÉí¦3U<åv‹1d¼ñè¬.žYùÈWU;™`LªÊ‡Ý „s¢õ³L$Q¼Ô bÙ²¤Ò Ƹvþú²ðÂ\þýL‹³²^‘Wõ•N‘¶j>ç†p¾¤endstream endobj 323 0 obj << /Type /Page /Contents 324 0 R /Resources 322 0 R /MediaBox [0 0 612 792] /Parent 313 0 R >> endobj 325 0 obj << /D [323 0 R /XYZ 72 744.9066 null] >> endobj 322 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 328 0 obj << /Length 1215 /Filter /FlateDecode >> stream xÚ­WKsÛ6¾ëW°Î…JM 2ãCÒ&­shÓZ‡N]h ª8¦H†¤¤z:ùï]<(R6mgÚŽ‹}|û-‘Ã’’`„™dA¶}ž]ßà`5ÃÁÇFJ `‚Q¬lg±HúI1»šý2#ÞN†¢±¥wËÙâBJÀg¹âD!A„¢(&TËÕuøöÓ§÷?}ùÛüfùqñ!Ž# jw€9 ›#ÊÀÔê¿3г÷Ë£gp,x‚ˆÀÿCcK}4F2‘ÄÄ8C ˜"!ebCúî‡ËyDe^eÍ<"<ÌëÎ :'ØeËÌò‹hBœ½H0sƒ“M‘â؉1/Ë®©ün5‚Ãv‰ã.ˆå&oÁ)áýR¦¥›ë9DðWº­ íªµ[Hݧ͇¥ƒ¾õBÝìóÌK]‚ …!74fàQOè6ºÛ5¥%-WNêb¨uÖù•«ŸçŒCñý¬kvn tÿÀ×s‚ÃûnS•.sÆÇDb ä8@`2_åGtÇøgJ:%0JÑ "E’ ")Ήã!8çK“WiíF]“f^hÑ…o EœöùJ¯œäVÕœòð0<4Su·ÊÛ:í²Mï,õòÔã3n4ÃR.qìSoêl‘”Xx_B4°ÔBãXÊ„ÊB‡°‘Ú{DÒ#MCŠ\YâSÀ´®uóuM(ê© 0F`—ÛêBouÙ¹CY#ìzÕFÞé¶sR’úUzDˉïL,÷{o¥z Ÿ¥Eq›fwN¼Þ•Y—Wå9LùÈg¶É‹ÕIpÞoÚx;uÚ¶º¶N–N0÷Üsy;É`‰ð@óª™0Vb‰É pjÇ@I’po¸š;/Q»ta0f=(@lHºšÁ¶i-7˽é¡û }­ïÌn<£ Š(>ög/õ50‰&wZp…azzZ à?èâF·uU¶~vdô¸—oï}Oëµí’]᛽Õ~`ày`ÕÓý‘Ñ2Ýz#,Íi4q"À‰É…ìyòkãc˜D‚&=hòÖbRÀÊ%Œ¢ŠÑÑ@ýq0y'öeIÀˆ}#@h‰ŠÝÍ÷ê›Å®mE¬Zܿ墶w<l1LÛÀÎ÷tx56W‰¹FìÈ^#½*…zE¨­ÊFEens!¼±ª Ç‰b§¶{bš=ŸíM©ÏÞœýhvŸ;é¡jŠÕÙÇ’£I§:ÛXŸV7F“$wPåèôúµ]‚$Wö°rwLqx"ŸŽôîð5á´»í ƒÔûßDCXF¶“ ÷ÁS…[C‹ÚÕÜŽá#‹t;¨Ø ¾½è÷¦ùbåÀ—gy‘îu“þ©¸ˆq.“§q‘Oâ"9bDòÓ¨V'¨ü× > endobj 118 0 obj << /D [327 0 R /XYZ 72 744.9066 null] >> endobj 326 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F29 12 0 R /F35 25 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 331 0 obj << /Length 561 /Filter /FlateDecode >> stream xÚTMs›0½ó+hzÌ! I†Ìp°;I›ZwàÔ4ŒeC‡¯ ‘Ôÿ¾’çàaé­vß¾•´Z¥–™Ãvº³Ø^À°€ÚéöÉY¹: p=!tòªät=¼ÉûqÖçB­S§ì¤ûœ>ú÷*6cDBÛ#iÀŽ„Ÿ?ùC/üMÙø¼yq=¦h»ƒ,ÚFÇjoADÃèè]Ö]+¤ñêý,kþ‘ßN´µñú•<€I¦Æs†ïYÍ·ëLdõªl¶e³7欗דyÌ€ˆÐ"Óѵ¦h£)Åkãi^Îãàöå ÙžŸeÈŒý”Âyž7d2ð®DLài‡ß÷ŒRÂijž!cÏ$?4\®M¯¤.RH¸H]»œ¿‘©›FéD†#á0˜“4Ò[ÇYw©…”7´‘nZJdjÌkë¯õô í­íG ‚ ©ýª€º”Q„íÚ",œ@e%Öϧâ½Ñj|”¦ó: Âè(Žª"L q–]ÇUCü3UÑ®G)s¾|}0ÆdöLƒ4ÕSAÿn¥* endstream endobj 330 0 obj << /Type /Page /Contents 331 0 R /Resources 329 0 R /MediaBox [0 0 612 792] /Parent 313 0 R >> endobj 119 0 obj << /D [330 0 R /XYZ 72 744.9066 null] >> endobj 329 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 334 0 obj << /Length 1089 /Filter /FlateDecode >> stream xÚ­V[oÛ6}÷¯ÐÚÙ@D“Ô•2`í4E·z‹†e JT­AU‘Š“?ÞdKœÃ%žÃóó‰&r üCNŒAýØwòýâëâî:Å:ùÎA H‚œý"ˆ’aP/n¿/åñ$‘7fz»]¬¯qä@"yÙ–N!:Á @˜8ÛânùófsõÛ/7®î·Ö×Aà øA„5BÒa ö°"ˆõüwjââj{\Y.… @ü*3 àÄIŒ” Œ|Ä„8R ˆâ81’ؾ­© +ÇÉò#[¡py°ºòáòa…Ã%­Í£«ÇLM7õJúQ½ á÷"¡òM—,9ZyB¸¼iDÇ,šŒì…Ò¦?4¢¶»ŠËC¸®™¹ä'µrD•X«H?`¥¹ö¼j¾˜[±³ïj¦ 9ØUƒ…×¥ÉGœe­E‹ª®DE ì‡#Á8€`H¤r%ø¯Û›™ª°Ì û#˜åSz÷´“Êô³ÕA»‡*§`ÖcœørøŽç€‰FcëqΊQ@0ăÇR›¤ƒŽÑì„håÚ+ï˜yg2ç¹¼‘FU­8“œHL‡ÿZ5Õ>³–*ÊSQÚìîYr6º–6Öð¾8ÓÐQpmÇrÊíÄÁÑ‚}“õí§•ʯs‚‘-ŽI&²€(Ð!%ÊÞ@y ÂÄ7æ¼þaÝóný¹jÖ´yXy‘4¨};¦{A-w &fxm&”UMߘ[kæí@û4‘MÀ:a&3>7£ìØÞ¼çýçcÙj<Æn”oöþfsõ2ÓÛŒÓ÷ÛíæVK{Î6¼ÿƒ~í)ﳦ¨igéG@»–Í…ì>’×Ù oŠþ†pžW¾Ao4—$ ñ§² Z¾‚¥›O·[EÄi]~VÓæ‹Øä¥-±ìhVÐŽß¹9k„ü=3ß½W´sî=îëTnc>MÔ©¸A'é·a9ÇÑNà:3b´™ØX5ç}WTƒín[gOº\E¡ùCÄ$ÁÓUøŽÖõå¶ë©…rQTÍ¥j‹ÓÖ ýä(Õ;rãÔ~éÙ'(ítd“ZZ ·ä}ßTy&¨»Î¡÷¦1C8ûy”cÁ ¬í²{õµpO*~²4Ð~wÏøÃy~ §M‘v”·¬áZ»BŸS~B˜ÒrÞÙO-u‡¼}kiÃVÒ.ë8—¯zQzÉ+÷?-ðÑ4é1‹ÎöÜ)&E;üŸ¥?±s…|qîA÷÷¡«L®§U¾ƒ(ëžï&ì^àË“UM;lˆ8M›lOÓÔÆfssÓtŸUMšº/|ê|´]~»IY ЭYžÕ;ÆÅ`_h>¥ùíêL…z7×—´d=-fNua`$¯Ïu>IB{¨CDþh‡:=˜9ÔˆžŸJCù›E0Š@þŽ#lNa8èùü“íOendstream endobj 333 0 obj << /Type /Page /Contents 334 0 R /Resources 332 0 R /MediaBox [0 0 612 792] /Parent 335 0 R >> endobj 120 0 obj << /D [333 0 R /XYZ 72 744.9066 null] >> endobj 332 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F29 12 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 338 0 obj << /Length 605 /Filter /FlateDecode >> stream xÚT]o›0}çWXÚC` ® Ø@¤<¤Q»®Û²nåeÊ¢ˆ'B"À i›?›ë4dM¥jO6×çÜs/÷2±.®=Ž(Å1cJÖ(ôPH &~è£$›ÛSÇ'6ö°ç¸”b·ûZ¬ªL8®Fö¶Êv…pÉíŵÏP„cÎí† ×gØ'í¼|p\®Èë¼#¸üàz¯éš ÂÆ,Šû„éÍÕô \ï~%7ßgw“äÆxø¶kZ¸=8Ó‡ÂÜÚ Î|[W²=`U¤Mc<é^ÈQ‡ò(f4öO±™Xr¹Ì˼].FQ¬‡‡%å\‘0ã1Tü±{R„q„zöTnE§Î8&aHOãå&\Y™ QêGng•¢ÝÉò\q:7 ëÞúñâÆU|·çèÒìÇXí5uÀz TÔƒ¿™qµyèö¤®E™åϰak:.cÜžVÛº­Ù˜_+‡2ûÉ|{t> endobj 339 0 obj << /D [337 0 R /XYZ 72 744.9066 null] >> endobj 336 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 342 0 obj << /Length 884 /Filter /FlateDecode >> stream xÚÍV[oÓ:ϧÈ´°ºvÒ܆öP“†ÄjÑ$Ætä%.µHâÛY)ŸßRšzN9 ñ’Øþß~ÿ«ý|éMσØGdQøË•Ÿ~‚ €aúËâfôbÂ@8ž á¨)±>ÙŽ8"|< ’t$rµ@ш6r|»|5=#?YÏ´FèO„0EF᣿¦­àÓ;ZOI}?žÄZéV®Y­e5·2ŸEif¹-Ê–äÔñ–xK8h¶Cì+Î*Ëö~qa´j7¸ü40IQœY8O e²#e L³Ôœ¤Ñ"¶bÈÞÅ剥¿y·´‹³?² õIoÏZ9¤Fòí©92”…}j#zª¯0¤X0Ü|€¼¸T_d”&ŸsÒÈ=ї怲9`Z¹6œJ¢Mã¶”ç*Â*¶;%š ©ÌÅâÍüJïõv‡ê«:ä3•šýÔ®h ^RØÍf­JÈUg9‚ÖŸ9š#`!ÚÊ­©|ìÂNkû—kGZ\¨ òn8^ý`9Ð/ šZd(I÷¿î|ânQ3Ù¹Ouêâ"™s ×E \oÝ"—Œ»00nÿU+ä»Z@H%â’Q’ŠÔRœhaÁº`?.ËÛ•sZ:{+1»¼Ãù''@åúAVTYw°jÒO⊵u1˜Ük£F€ë5–sã✓+N„ò¡Kź²¢%1™Äšïèæ1ø ¼ýMSµC®¾V™»ø–º#<­ÚqµåÔ•uÉr\Ö¸k£³®h”³ÿ½a.YWbŒœúSû|»Aä¶!9+Hï±cÔ\AÐüžpü‘üÄX7Z&ÊŒh ÔŠcFå=.[,ÿðA¿ôÃ’Lâ²'8x÷wJ»Oú³Û=9S]~ÚM¾‡j÷Nžî«0¦ÔìFÕY¯´¿{Ц½Fêá8½MO·¾í¯uzø¡® §¸¤_ ²_§ßÔ÷Jò’ÙüO¯Z„4 Ä¦çϯ½Ñ¸WáÞ‹K™û›Ö+Öùrüï‰ë½\zHqBé·r40Vÿ¼òþñnn¡_xÐåAfiäoÔ”e_y³8í6¥·ðÞîÔL”üdOÑs÷*ÏÔZýì£|„Ô{“+Gƒ`df”†?‹b(QJ5W”tx¿¬ß0ðendstream endobj 341 0 obj << /Type /Page /Contents 342 0 R /Resources 340 0 R /MediaBox [0 0 612 792] /Parent 335 0 R >> endobj 343 0 obj << /D [341 0 R /XYZ 72 744.9066 null] >> endobj 340 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 346 0 obj << /Length 558 /Filter /FlateDecode >> stream xÚS]o›0}çWxÝC` Æ &R’(ÕmU·äi]…8 `†¤üû™˜TÉš}<Ù—{ι_éÊpnÝ` #B\°Ú€Ð!Fy¡VÙ£9³Î?OþnL¶5KyÆÞ²ФeÍP“=k’gvÒrÕ‚p¨}å ‰ãJy‰c]ÇúÄq™äUFG²by—vÎÇŠVüó)áië¿{žæU–WÏ×Ö½¯ àwDЮ)ƃ­”õÈq ž&Å– 9¢ˆ¢Aÿó²QïÛí|¬ÌA!3¾“Љ¯©[¾þq1j ¿>̺A÷¼b½âÙU?s׿Yp±½b4tÑÐC݄Ӱºh»Mû=üqz“ŸžEù Œã,O¥Zœó•ÜEøêLKã§ñø„@f °0ô"JÀAâ(rAiø=…±4¾¼ÊØŠoŸ MûG*êÐ÷]ˆ±«3@¨ qz¾9©k¦öô¢C­£oÙ„挗uÁ$ÓOÜRa?ôëp{Ë%&+ô§ùKÒÁO?ø 'i(endstream endobj 345 0 obj << /Type /Page /Contents 346 0 R /Resources 344 0 R /MediaBox [0 0 612 792] /Parent 335 0 R >> endobj 347 0 obj << /D [345 0 R /XYZ 72 744.9066 null] >> endobj 344 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 350 0 obj << /Length 844 /Filter /FlateDecode >> stream xÚí–moÛ6€¿ëWÆ€JÀÄ7‰²¤%’Ìm—µ±[iŰ¢0™~,É“˜8Þ°ÿ¾“Iev§ÈìËæ/&ywÏñŽä鮿f¾I=äz>3“…9dæ„Èc~`&óÏÖí ¹¶C !V<±±®¦¶Ã†•Øf•M‰•fÂþ’Ü*E!ç1¢î1 Q{#ä•íëÁfÜ ´Ô —› }ßÓ—#—ôÀùál³…DÛ}£ÝÈ)¯AxÏÎýlÇ÷Éê^ &™„1qµ@½ˆ#7T3øjôqüá§qœD]N/âÉÕÔß}ŠÆÅƒØ”[¡lóMQGZxs9XI¹0®³•ÈÓ¸.Ó-*«%nXY9_K<èòrBûôšÚKí—ø‡'Ðn·C¿•Q¥(+ó–‹A¥ðXÏO;÷°HÅ?¿(½öëóöκ¨eZdb0êÏÿ[‘ÎE5ºÀ_¯ô›]—ó}·JsO %KÑ-¿Kóö°ëu$÷[q9€”Dµ¬à £Û²^]àFë™-de%ên™Øˆnúˆ’ ÜŽ{ÙKÝsЏo_ø\Rð ‹ÿöfFÿò{ާ“»xÜù A­kyòcת£~]¢XT§Hy¼Nkñ6I¦˜4EµY™îåª,0C¼ËøûTŠè)¼oÕˆð£8O#bô8Ò7ï“.èMYH8u§¹©.Å£Äð¿SÓl•Vµ—ƒ{¹p‚Aä(–r¥1žK[]Ÿ: þ¯ÿ•ÚøQÔÛ²¨Ÿ)©®MyJ{ëÆK‰ÿ°ÀœÜÏÙ,O×Ål†´gu=Û¤ªYªyä‹pè“N¿¿ÒÁ½ŠÚ§ùÇ33ÿ«ÎˆéÎhÑÌÓûÔ¶¡ m”ÝT5 [ȦÓûj[Öb³‡¦Œ«Å\Rõ·†7SU"Ó(×?BQ2D!ñ\`6¨»Ttø£âiuôC±e¥r%:ð>Cq‡Oô¼ Ï jµJ¨Ñ0ƉAa˜´iH¹‡ˆÿYnüj|þB̹AÌ[*hps‚héÈ ÚV=Ù±ñá 〽sºÖ­ï_û€u!J=98EÆÎ6¾¦Ç}èsiÛ8þÜMýendstream endobj 349 0 obj << /Type /Page /Contents 350 0 R /Resources 348 0 R /MediaBox [0 0 612 792] /Parent 335 0 R >> endobj 121 0 obj << /D [349 0 R /XYZ 72 744.9066 null] >> endobj 348 0 obj << /Font << /F26 6 0 R /F35 25 0 R /F29 12 0 R /F36 32 0 R >> /ProcSet [ /PDF /Text ] >> endobj 353 0 obj << /Length 974 /Filter /FlateDecode >> stream xÚíWmÚFþî_aYUxׯ6Øá¨î®¾6§”#DUÓ(ZìÜú­Þ=^úë»ö.îŒ9©ùT•/žÝyæ™—Ýã›™‚îz¶:Ð]DZÔÙB50Ö{—×ÕqÀ7ÃÏ­ïtĤLÏwí/³{«]ë®=p+ý×K¿v×Á¸5[= á!`í®arɆåõzž)W\áéƒÿþ£?yuN‡Ó‡ëI×òüt q–ƒ°Ù&qJ=©¼½ÒVŒåB4XAB¨ÎÕ4#¹žKT Ò £t‰´:/'lŸ^Â&bibûuúö@´Ùlô¿² ¢Y²çEÒİ¥á æWEÀ g _~~7­Xí£ËöÝ(¥Œ¤h£æúÿ$„b4DOwšÍn²pWùØõš—d õú1ÙŸ5<¶ËáJãñ(+ø9j£ûŒ®†ˆƒÎdÐzÄð{>2ðíåF ùR`ï5Å….•½ ¬èYÇp¦¡»FðM»ÙyÞÍÓÉÃxê×¶³qÝöÛ”A‘’X0L¡àE²_YQÿÿƒá?;;òŸé£E©â'£ú¶zy Ñ?ªó–bˆŒ>¦9)(y,oO”òî“$UK#Q<úX½ŠÙ~jÞ¤ä«âþ¡¼Z²7uö{¼pQ¢|16DÚ˜$ É˜"J9F,E–‰ß—<†íŒÆ’ ²5ùd  =§æh\ŒÏy@çÊ0D²VC$‹wa~5ÿ¿„ǸY™Ðœˆ²þ†mœdTžCÁáLËÊ8Î#Ž“õm·Êzí¯”¦£<&;(¾þ]iÉ¥dÚr+JÅóû#jç”:ßeóßêJ<æú‡Émø8KA‰“Ê}©×Ê—¦Ö1pÇÄ.sèìÍã]õ’•^ꪺµAå‡ò"ZhMŠrœ  ³€¢åcjHÚè;O²æiÔÍúoáÌâ?qÆÏ6ZÃq’ýS¿ü&ëÕ%ô·ä,ÊRO˜ž›µ÷ð¤±Ç|. ‰È{á.ì$.Ûþêµè“×bk±•ðÞwùü‘•ë4”õ”÷tÅaiuÛ¦<$¬jßTmKljò§òù VC«÷ ÿp¶ºá ¬®kª‰b9ƒý"V¦ÊûM—ÛwˆnÊï ÓQ]þ}Áüû‚ï[¦n¦QUÀá›N¿gµ®óÒ0Úòuкm÷pKowmÛiÝVӌмËÚ†ÝÚÈ”¸uÛ´[‹-KJø>Á¿ЧUendstream endobj 352 0 obj << /Type /Page /Contents 353 0 R /Resources 351 0 R /MediaBox [0 0 612 792] /Parent 335 0 R >> endobj 354 0 obj << /D [352 0 R /XYZ 72 744.9066 null] >> endobj 351 0 obj << /Font << /F35 25 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 357 0 obj << /Length 873 /Filter /FlateDecode >> stream xÚ­UßoÛ6~×_A`‘‡ˆåo‘òÐ¥-– <ÄEÓ ÐdÚfKš,·Í¿#O²åÔÃl0 ’ÒÝw÷}§;rÂàÇI.HÎe2—¤Ü&&÷Œ,F>$Œ:g$ùF•³œleìxØ$wÉo p2ʦH¿,’Wï…!Ž:ËbE”uÔp§‰q‚*.Y,ïÓ7óù»Û·7Ÿf‹¯Þ+E¸¢R=N€s&$5LDû·Á0y·8D†ÀF[Ê ûL‘FBÑÜæ<$$¡’[ À5yncJóªœ –þ±ñÝ,¹MýL²ô{±m7iÊ„V&œB˜ÌHªt'2ËYJù,㌱ô¦î»fðv¸çÔI±OÕ‚j–ŽkQãêg\IÄÍj0Àe×½_í7xÚ6Ë—Â žƒŠhΩ°P·Ô•8 ºÜ9ê ꬵãù…À#`6ED•§ …w-ì1p ÚÎ8KŸû§f ÷Íÿ>ððÝתôô¬Ò\YÄʤ£ÂI1QZ J—ÍrR&NÖbT²VNêŸ[]cÉA¿ý¡Ú/ërú#ÚÅÌ˦®êõxŽÅ eÃ!Äq‚ ,¥&"€–A/ø‚¬°ÑVb¶?Í2I^GÈïx@¸°[úÄí+ðBŽÐ¹N[lÉU×lÑîóÝ nªmÛt}4¶†²Ú!ãTÇ£ÇÏñMvx娴?ÐrSìv2÷Ý®©_G[ˆ—k—Ÿ†´Ðòñ1¤÷øø…i¶ó›Õ%>®‹­¿ºmj?œ‹µ¿b`ç˜æ3¸Óàˆ.WG¤sÔ£5Àž‡sä'€2w2n»?²¢ÇÏa⹸¦w}·/û@ /1Uͨ*ž¿Gsø‚ùEÈñ"°CMešžx€ÃMÝÔ·~]ôÕW3ï}½!éèü€ÞÙ9÷6 Í÷]ýúãó›¶½¸¼ÀD£wøŸë ØC«óÐÌ ºSî¤GÆÖj_NÆ] øÀ«¶ÿç^¹nê/Œ‰õ¾º hÛ¢|[¢Áu¿F!D pNTýÓß8­¡¢D0Eê¿O8Ä˦€g\2pÙcÜsn÷¿õ2¨§uJÏÜ|ZQf`ý‰ãÅw.ëpñM€~¼¹a€Âä9Q0þ¸Àž7|Ìç/5HþŒendstream endobj 356 0 obj << /Type /Page /Contents 357 0 R /Resources 355 0 R /MediaBox [0 0 612 792] /Parent 358 0 R >> endobj 122 0 obj << /D [356 0 R /XYZ 72 744.9066 null] >> endobj 355 0 obj << /Font << /F26 6 0 R /F44 128 0 R /F29 12 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 361 0 obj << /Length 961 /Filter /FlateDecode >> stream xÚ­VÛnÜ6}×W5­Š,—ºKö!n¤)š¸õ>5 Z‰k Ñ…!)Û‹¢ÿÞ¡(­$ïÅvÓ'Š£™ÃÎÎ\­´Å;ÇÓCù¾«¯¶º…1r\øö£á aúyvaÎ}Œg4O¾„!º3¿¬>èXŸ[E^µJyIk&Æš¯Õ¦"÷Çô·¬.•BY§kºY]©ý)¦q’‘óöÞürh˜æœÆ"Éžrõ·ÝOuI ò°ÚQÂ{mÛB‘„ãèËZïÉF}pÂîò„¨ÈâѰŠwî«%QGtv‚5 è*%[¥uKÄ5a¼®þ®â’,?ÖuÙÚQàEÁÔúbK•õR-5%­½±%]¼âˆ¶HåÇx¥N@¾K–Á yÆÑ öó@/ÔuiƒŠ:N%ò–ž²šzò|3–W]–~¸~ûÇͧ—Ý®s”>e%€$I’Çv¨ÿq `b«0ßgï;ˆ' ¡â»‰Æã;20mÿuŽfOÞ£BùHt„ ÷'¹Ôñ mJ:„Ò™&Å–¢¤¨¹,-|JgœÁ¿ÿ9“BxÊ&ñ­×ê­Y¯Û(IÉ«[ޱ]‡FçÜmQoâ‚÷tÒ¢N…F{¸cÙÛ‘^ ϬöìÛ_r‚(ÔGòá¾æŽ Gî4º9mùë ùïŽ;òÜ0|±ãô(;„€…´ Y\¥áç¡Û ¨)Ú„ÊIÎtÿÑþ¹€ Ò3¦CMlGâså§P˜t–‘oCá«<+rYuM ½áï;._ÊïΩף›؆p±„µ“ÈÇŠ+«å´ÿõ&4Y®XCžSªC£O¿JÅÅ;Û×-(ϳå<1w#úT‰oA¹8ªJ~6¬I©}Ó>Ázªaýƒsjzú=l0²"Hv©¹~Øo íFû}3ûùèJ¾Ҁܵ‘eÙŠ¾­ž+WÂá@¤ô …v•æŠŠÅæÜó|Ùz$;åõªŸÄtðì!–Ùícú­¦endstream endobj 360 0 obj << /Type /Page /Contents 361 0 R /Resources 359 0 R /MediaBox [0 0 612 792] /Parent 358 0 R >> endobj 362 0 obj << /D [360 0 R /XYZ 72 744.9066 null] >> endobj 359 0 obj << /Font << /F35 25 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 365 0 obj << /Length 683 /Filter /FlateDecode >> stream xÚíV[o›0~çW <…|#@i¤´KµVk“ÚM몊› ›Ú4—ýú™@²t£i'íò2^ìc¾ï;ÇÇÇG> 5xLÝž£†ð^k@V×ÒÃ䦌 ‚Úƒ±a’®Û ¬,a`ÔŽbj܆§ðزuWÑNIGºiÙÀB.^³ï^ú ÓA¨ýž&ÕdÕãz´|Œ|dWAÈ©f—Ë«aúe¥S²g»ÞÚi/ ÆæðüÚ²9ñœVœe6cÒ¯´¦E‘ûÊxJ³Hõ[ò(\L`9”ŵÁÉVh±X€¯|FEbžmt¡‚ìSXÊä‰ÂÂZG ‡á‡³wÁZe/?}™o¦L‹i£Ð6û›üÅjF%Ýýý§ú–F ýüqe?í'«fˆŒætL…äl·P˜Ä­GÁü³Õ ÏŸ JüŠÚï±(ÛTšLýb•«M«óðe!Ô¶Zýx*RYð|JE–àfÉhÒ¨Â8;§“¨Hçô„tBE«OœTðf¸[3àû¾Ÿ¼"wð§Ë¶Å <Üuÿt#Æ£ó`ØØ *æTørGªô Ø–™Ðyµü Ù芥K5Ö®2žÜ‰ÇÏ+ˆÚMe»€”xå¾cbb{Íjð\jä«bÊ´Þ¨Œ«¥ Y¡ˆ˜¼§ÂÖw¡=ž>²/*5 ”#®Šf¨ ¥FtY@UÃMçð¿7þµÞøïºØ%•9g’öw¯øvñw_umjX‘ŽË׃ÝÈQcœiÚÍ-Ò é§–çÚúB`Ï#z¦uwcÌ´@»ØÊ˜Šoî6=S:`LªwÆ£‹Ú궪b&¤­Jsý6Ñ;¶<‚»J´D9Ö&Þojˆ¦endstream endobj 364 0 obj << /Type /Page /Contents 365 0 R /Resources 363 0 R /MediaBox [0 0 612 792] /Parent 358 0 R >> endobj 366 0 obj << /D [364 0 R /XYZ 72 744.9066 null] >> endobj 363 0 obj << /Font << /F26 6 0 R /F35 25 0 R >> /ProcSet [ /PDF /Text ] >> endobj 367 0 obj << /S /GoTo /D (page001) >> endobj 369 0 obj (1 Introduction) endobj 370 0 obj << /S /GoTo /D (page002) >> endobj 372 0 obj (1.1 How to Read this Document) endobj 373 0 obj << /S /GoTo /D (page003) >> endobj 375 0 obj (2 Examples) endobj 376 0 obj << /S /GoTo /D (page003) >> endobj 378 0 obj (2.1 Server Side Examples) endobj 379 0 obj << /S /GoTo /D (page003) >> endobj 381 0 obj (2.1.1 Simple example) endobj 382 0 obj << /S /GoTo /D (page004) >> endobj 384 0 obj (2.1.2 low level soap processing example) endobj 385 0 obj << /S /GoTo /D (page006) >> endobj 387 0 obj (2.1.3 A mod\unhbox \voidb@x \penalty \@M \hskip \z@skip \unhbox \voidb@x \kern .06em\vbox {\hrule width.3em}\discretionary {-}{}{}\penalty \@M \hskip \z@skip python example) endobj 388 0 obj << /S /GoTo /D (page007) >> endobj 390 0 obj (2.2 Client Side Examples) endobj 391 0 obj << /S /GoTo /D (page007) >> endobj 393 0 obj (2.2.1 Simple Example) endobj 394 0 obj << /S /GoTo /D (page007) >> endobj 396 0 obj (2.2.2 Complex Example: pickler.py) endobj 397 0 obj << /S /GoTo /D (page011) >> endobj 399 0 obj (3 Exceptions) endobj 400 0 obj << /S /GoTo /D (page013) >> endobj 402 0 obj (4 Utilities) endobj 403 0 obj << /S /GoTo /D (page013) >> endobj 405 0 obj (4.1 Low-Level Utilities) endobj 406 0 obj << /S /GoTo /D (page015) >> endobj 408 0 obj (5 The ParsedSoap module --- basic message handling) endobj 409 0 obj << /S /GoTo /D (page019) >> endobj 411 0 obj (6 The TypeCode classes --- data conversions) endobj 412 0 obj << /S /GoTo /D (page019) >> endobj 414 0 obj (6.1 TC.TypeCode) endobj 415 0 obj << /S /GoTo /D (page021) >> endobj 417 0 obj (6.2 TC.Any --- the basis of dynamic typing) endobj 418 0 obj << /S /GoTo /D (page021) >> endobj 420 0 obj (6.2.1 simple data) endobj 421 0 obj << /S /GoTo /D (page021) >> endobj 423 0 obj (6.2.2 compound data) endobj 424 0 obj << /S /GoTo /D (page021) >> endobj 426 0 obj (6.2.3 class description) endobj 427 0 obj << /S /GoTo /D (page022) >> endobj 429 0 obj (6.2.4 Adding new types) endobj 430 0 obj << /S /GoTo /D (page023) >> endobj 432 0 obj (6.3 TC.SimpleType) endobj 433 0 obj << /S /GoTo /D (page023) >> endobj 435 0 obj (6.4 Strings) endobj 436 0 obj << /S /GoTo /D (page024) >> endobj 438 0 obj (6.5 Integers) endobj 439 0 obj << /S /GoTo /D (page025) >> endobj 441 0 obj (6.6 Floating-point Numbers) endobj 442 0 obj << /S /GoTo /D (page026) >> endobj 444 0 obj (6.7 Dates and Times) endobj 445 0 obj << /S /GoTo /D (page026) >> endobj 447 0 obj (6.8 Boolean) endobj 448 0 obj << /S /GoTo /D (page027) >> endobj 450 0 obj (6.9 XML) endobj 451 0 obj << /S /GoTo /D (page027) >> endobj 453 0 obj (6.10 ComplexType) endobj 454 0 obj << /S /GoTo /D (page028) >> endobj 456 0 obj (6.11 Struct) endobj 457 0 obj << /S /GoTo /D (page028) >> endobj 459 0 obj (6.12 Arrays) endobj 460 0 obj << /S /GoTo /D (page029) >> endobj 462 0 obj (6.13 Apache Datatype) endobj 463 0 obj << /S /GoTo /D (page031) >> endobj 465 0 obj (7 The SoapWriter module --- serializing data) endobj 466 0 obj << /S /GoTo /D (page033) >> endobj 468 0 obj (8 The Fault module --- reporting errors) endobj 469 0 obj << /S /GoTo /D (page035) >> endobj 471 0 obj (9 The resolvers module --- fetching remote data) endobj 472 0 obj << /S /GoTo /D (page037) >> endobj 474 0 obj (10 Dispatching and Invoking) endobj 475 0 obj << /S /GoTo /D (page037) >> endobj 477 0 obj (10.1 Dispatching) endobj 478 0 obj << /S /GoTo /D (page037) >> endobj 480 0 obj (10.1.1 Dispatch Behaviors) endobj 481 0 obj << /S /GoTo /D (page037) >> endobj 483 0 obj (rpc) endobj 484 0 obj << /S /GoTo /D (page038) >> endobj 486 0 obj (docstyle) endobj 487 0 obj << /S /GoTo /D (page038) >> endobj 489 0 obj (10.1.2 Special Modules) endobj 490 0 obj << /S /GoTo /D (page038) >> endobj 492 0 obj (modules) endobj 493 0 obj << /S /GoTo /D (page038) >> endobj 495 0 obj (typesmodule) endobj 496 0 obj << /S /GoTo /D (page038) >> endobj 498 0 obj (10.1.3 Dispatch Mechanisms) endobj 499 0 obj << /S /GoTo /D (page039) >> endobj 501 0 obj (10.1.4 Other Dispatch Stuff) endobj 502 0 obj << /S /GoTo /D (page040) >> endobj 504 0 obj (10.2 The client module --- sending SOAP messages) endobj 505 0 obj << /S /GoTo /D (page040) >> endobj 507 0 obj (10.2.1 \unhbox \voidb@x \penalty \@M \hskip \z@skip \unhbox \voidb@x \kern .06em\vbox {\hrule width.3em}\discretionary {-}{}{}\penalty \@M \hskip \z@skip Binding) endobj 508 0 obj << /S /GoTo /D (page042) >> endobj 510 0 obj (10.2.2 Binding) endobj 511 0 obj << /S /GoTo /D (page042) >> endobj 513 0 obj (10.2.3 NamedParamBinding) endobj 514 0 obj << /S /GoTo /D (page043) >> endobj 516 0 obj (11 Bibliography) endobj 517 0 obj << /S /GoTo /D (page047) >> endobj 519 0 obj (A CGI Script Array) endobj 520 0 obj << /S /GoTo /D (page047) >> endobj 522 0 obj (A.1 Intro) endobj 523 0 obj << /S /GoTo /D (page047) >> endobj 525 0 obj (A.1.1 rpc wrapper) endobj 526 0 obj << /S /GoTo /D (page047) >> endobj 528 0 obj (A.2 CGI Script) endobj 529 0 obj << /S /GoTo /D (page048) >> endobj 531 0 obj (A.3 client test script) endobj 532 0 obj << /S /GoTo /D (page048) >> endobj 534 0 obj (A.4 SOAP Trace) endobj 535 0 obj << /S /GoTo /D (page048) >> endobj 537 0 obj (A.4.1 hello) endobj 538 0 obj << /S /GoTo /D (page049) >> endobj 540 0 obj (A.4.2 hello fault) endobj 541 0 obj << /S /GoTo /D (page050) >> endobj 543 0 obj (A.4.3 echo) endobj 544 0 obj << /S /GoTo /D (page051) >> endobj 546 0 obj (A.4.4 sum) endobj 547 0 obj << /S /GoTo /D (page052) >> endobj 549 0 obj (A.4.5 average) endobj 550 0 obj << /S /GoTo /D (page053) >> endobj 552 0 obj (B CGI Script Struct) endobj 553 0 obj << /S /GoTo /D (page053) >> endobj 555 0 obj (B.1 Intro) endobj 556 0 obj << /S /GoTo /D (page053) >> endobj 558 0 obj (B.1.1 rpc wrapper) endobj 559 0 obj << /S /GoTo /D (page053) >> endobj 561 0 obj (B.2 CGI Script) endobj 562 0 obj << /S /GoTo /D (page054) >> endobj 564 0 obj (B.3 client test script) endobj 565 0 obj << /S /GoTo /D (page054) >> endobj 567 0 obj (B.4 SOAP Trace) endobj 568 0 obj << /S /GoTo /D (page054) >> endobj 570 0 obj (B.4.1 hello) endobj 571 0 obj << /S /GoTo /D (page055) >> endobj 573 0 obj (C Complete Low Level Example) endobj 574 0 obj << /S /GoTo /D (page055) >> endobj 576 0 obj (C.1 Intro) endobj 577 0 obj << /S /GoTo /D (page055) >> endobj 579 0 obj (C.2 code) endobj 580 0 obj << /S /GoTo /D (page055) >> endobj 582 0 obj (C.2.1 httpserver script) endobj 583 0 obj << /S /GoTo /D (page056) >> endobj 585 0 obj (C.2.2 typecode module) endobj 586 0 obj << /S /GoTo /D (page057) >> endobj 588 0 obj (C.2.3 player script) endobj 589 0 obj << /S /GoTo /D (page058) >> endobj 591 0 obj (C.2.4 client test script) endobj 592 0 obj << /S /GoTo /D (page059) >> endobj 594 0 obj (C.3 SOAP Trace) endobj 595 0 obj << /S /GoTo /D (page059) >> endobj 597 0 obj (C.3.1 GetAverage) endobj 598 0 obj << /S /GoTo /D (page059) >> endobj 600 0 obj (C.3.2 fault) endobj 601 0 obj << /S /GoTo /D (page061) >> endobj 603 0 obj (D pickler example) endobj 604 0 obj << /S /GoTo /D (page061) >> endobj 606 0 obj (D.1 Intro) endobj 607 0 obj << /S /GoTo /D (page061) >> endobj 609 0 obj (D.2 code) endobj 610 0 obj << /S /GoTo /D (page061) >> endobj 612 0 obj (D.2.1 typecode module) endobj 613 0 obj << /S /GoTo /D (page061) >> endobj 615 0 obj (D.2.2 pickler script) endobj 616 0 obj << /S /GoTo /D (page062) >> endobj 618 0 obj (D.2.3 client: invoke savePerson) endobj 619 0 obj << /S /GoTo /D (page062) >> endobj 621 0 obj (script) endobj 622 0 obj << /S /GoTo /D (page063) >> endobj 624 0 obj (SOAP Trace) endobj 625 0 obj << /S /GoTo /D (page064) >> endobj 628 0 obj (D.2.4 client: invoke getPerson 3 different ways) endobj 629 0 obj << /S /GoTo /D (page064) >> endobj 631 0 obj (script) endobj 632 0 obj << /S /GoTo /D (page064) >> endobj 634 0 obj (SOAP Trace) endobj 637 0 obj << /Length 882 /Filter /FlateDecode >> stream xÚÝVKoÛ0 ¾ûWÛE£H²åG€ÚnV`[‡ú´¶×V£ŽíJÊ’`ØeÙy´ÍŠí°ÃN2EŠüÈ2u–Zã4´ A cÔN§vDíˆ`„ýÈ·ÓâÚ}çEØEÞˆ`ŒÝ¼*y­&ÞÈ·¬=ŠÝïenó ?¹7¢QìÞsué1…lj³å›¥(§SÏ×ðb¶–an¦7×Ò»M/:D JBX¶G4@~ÐÌ anÙ*cì3;ã0è}†|“θœ·€0!—Æ»6ü'ÏL>­Ï›y[ñUºnù‹ÖSÑÌí·«ÈÔÂÈ»~>gs^\f"›Ÿ•uQÖ÷f;“½ú²ß>6ò`ôZ¼çÒóáIw‡–F{b–ÎBTÎÄ™)ÕNÆãªÉ³jÖH5V\*Ü–ùCÅj×NÇQ"Ëù´¬¸3ª!©Šf¡~¾„ïn/Ò&±Ìpg$bp±01¤u*p±zo«yXÂAÒiGqˆp‘ýpB¶{ïî´®ËtÈê~âä3QJÕ´3.œ¿'¸3)ùPDdëÓà¼37Uî¹*Ê\ eá«–çjKçÖÂy-ø¾v PçöÚÑ@Û>•>—=ÜCÈ¥h†p­9ýá¿aA''çM±¨øÉ~{wž(e€˜‡Š1DýE„þ ŠJYÖReu>µ-æñKWm’^¿éH¨#‰¿ë)µC4#5S³¾•Nÿq0Z_™!Æa’þ„"ÂIhü—h‡Ýló j»ýSi R }jr¸DeÞ|/‹ô])ÑçñFsûæ•*¼ÒžgòßuÉ“)·­V  ILµ®¾è¡zzieê„GàßQ“äð¨<­*}0t—mSKi˜ n>¸ž¼«,WÕÚl¨Y¯‘ÀԄƾ;m„ÙË!™ X1}ÇXÍçC¤ÇL•§Z@“’F¼Á˜ ©z£ºßmêg0 QÕ~ F*·Ãyx¹èQ^çÕ¢àÒJë}j°À6Ño šϭGëúÛ……í #?‰™½Ã%ƒÂÍ­ Œ¡²®¬¯7#8?ÚqtÖ¿ž¶À~@Ñ?E ( :˜~ Ýáœt´´-‡Ë¿2¤š÷•7b ÊTæšo=Ž’ëWÑ*ÓM4äô `P kendstream endobj 636 0 obj << /Type /Page /Contents 637 0 R /Resources 635 0 R /MediaBox [0 0 612 792] /Parent 358 0 R >> endobj 626 0 obj << /D [636 0 R /XYZ 72 744.9066 null] >> endobj 635 0 obj << /Font << /F26 6 0 R /F35 25 0 R /F29 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 640 0 obj << /Length 738 /Filter /FlateDecode >> stream xÚíXÛNÛ@}÷WXy HÞ›¯k$ © *$`C«R„\{I¢&k×6¹ôë;¾$-Å$Tj)ÉËÞΜÏέrè+ø­nªâ–e¨þJ Aºs‹sDl6£ëöí¦ßŽfÒþ ¢jÒ ójBi=ê.å.!ÕŠbU³‹îùe×óÝÿD%ªF â¦ÃK§¯wÐ׺gWnWNÅ8NDe3ŸŒeæÖ‡G{­až'.ÆY8“ CpœÅA‚ât€‹ 2Œ£‘àV“—lWÏa«bYÇöÉ;^Íf3ô=‹4@a> endobj 641 0 obj << /D [639 0 R /XYZ 72 744.9066 null] >> endobj 638 0 obj << /Font << /F35 25 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 642 0 obj << /Type /Encoding /Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/notequal/infinity/lessequal/greaterequal/partialdiff/summation/product/pi/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro/integral/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/Omega/radical/approxequal 144/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/Delta/lozenge/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 214 0 obj << /Length1 1624 /Length2 3744 /Length3 532 /Length 4584 /Filter /FlateDecode >> stream xÚíTgTSë¶éAú¥I‘P‚ôšH@z‡„“ÐDŠ4)Ò¤H‘ÞTŽt,  ((ˆ¢TiÒ¤Þ€ïœs‡ïüº÷üzãeŒ±¿5ך«Ìµ?A~cS Ö©ƒÅ$@’RŠåéì7Äb.KhbÑ#g4 rÔ‚‚Z8$Œ€Âb 0R°D"HK jA@ ëåC¹ºsKQ11ñ¿,G.€³ÿ1rÅBÄ$ëå‰Äˆÿq ) Ü€ ´ŒŒ­õ¡º€ˆ.ÔÐEb80ö&¶.£àH ) ¸`qú×€c1ÔQkxI"—€x/$E CúÁ‘^G8à…Äy¢ðxâ;€Â®8†@œ  0p´7⨢Ý{\Kôð$bD2c,ž€‡ãP^€˜Õ¢ó«N‚Œp”"ÂÖ…è‰À½Z:ƈ4D”CaðéG8ÊåŒ(¼æOÌM$ó¡ŽËðÆ£0®U à®0Äã‰4Dî£éüÕ'ðoÝü¼ÐþÇÑØc¯?k@ðH´‹$5Hš˜N ævEa¨/-‹>Æ €¤~ÙÞ^`>HÜñ€DŽvF”X Å ýÒ…úK ¦Dþ3•%ÿ9‘ÿ‰ÿÿyÿ;q×èß>âÿö{þZdžÂ<‰ ðë’ˆ· ¸ Ý3ÀÑEsÕù¿b`ž(´ÿßDýîh‰üUéÙï˜>F‡Æ•(‰HZRê—…×Aù!Æ(Ü p¡‰Ó:¶›cH…AU=(1HJê7ÌÌ ÷À_î„Ä ~¯(Ôqå ¦f&Vúbw·{w€`æï…þ'¥!ñçáˆGSëH€A€„´üEࢬpQø7i@ aʰ•’”’Äÿ?ž¿Nö¿ÑhcàXÄÑΘ`qÍþ4Ápoލîñ—OlúóñÂ#‘~H8õ‡a,\)Ü=-#ðý~OĶ£ DÖáUTmö /¤Ûœ5¡Pæ´W!YÓ¯xÐàÿnÞkúÒù¯ÏÛØÐ­©È¥\îÀ³¢íyLãBMòb_C/8Ñ¥/XÞ X~{ùóI°”Å×ɾ+&…{§xú›dp”Ë[¢!g}òBXÏmzÑÁï>N8ÝÌXCÂü0~AèÎìÖ¦p׋g=Ý­«äíÓ\bÙ T‚J>'é„bC®fs©Ù˜—DŸSÕ~ÑËDcwG£_`,€.(ÚG”oLöJÎÓë^tejRÌ …*£ÝK#‘§Ïõ¸ÖIÎM0ÂlBÞ]׺5ä½;˜ž^Qú©§Í®;^]²œ-œŠr ¤¥“mzÛn]:¡hàZÀ²÷³†&ìá>tâq§jg²ÖiNp§ÃHþ=ízc¸ó—<^>½‡f‘äGV~ HÄquëe­êeY¬ÚiÊì+A‹ S÷Bƒ“­ò¤K æUà ÃwîÓUìœüÔU®¹ý˜{È«rUa‘9v4 Tm™¢ì\{bì<ÏÙnÀæKŠ:4†Ò›^—ŒÊ[…ƒÕ(Iµ+eÜ?p©÷Gò=njå¡‹±tŽcõ‘ö³f ub­›9­ér%Ò.} ‰(ý<À]«ß±æpÉ5k©F^¾¦±ücX¹©Yesä=IFî™Újæ-A^î+‹0\õ¦K:Ù~g GrR\Ép‰Ž±D±{×'zyÇâú“ä°O½èïáµÙbûjÞ^Wãôªú±!§k¯UI‚li‡/ö76µTÚDaÝW'²RØö~.Ÿþ€Èg^C„ÜÓ)¤8½qS /5ª‘Æì%xOÈåÓ­¦ß&§O3X³ üãü»y¿œ(†€ “)‡í‡t‰côÜX|çõtÒ¸J›Hsz¾Ï?Ý’nÄÆQN³Ei0߆Ð/b‡F—ÖXsö,ðè¤G´;í‰ø·Œ-;ü#äÃ9+–l¬a,ÉÓžcpBäFA%[ýã h*gkAþ¹´ûŒžŸò0wð ù›§=’Œ:¢Ò<†\ÕvÞ-{R¤Æ6]ïJMßYlVÐ7=Áè¦MÍwƒ—Îú*àœXöÈí0nx‘âC1¦:(b§¦}¾]s¾ÑeClŸÉŒÔd°ÄƒÕrò«¨³•ë༬Îú;’•Ë{çÊf–™nô…3•ÐJ2»øî§­ò²Qô}üO¥{òKúÉöãüS:=õ‚!øÖŠïA9ö·c8;"•4Æ\[Z¡u‡—\÷Ù 1%uἆ})íd=Á¬`³¨ó`æþÙÓàÄÀ¬ 54”Š6ñ‰¯Õó6§SŽù“Q†VåN+yœÑµEújÁqAîhZå$„btY8/+?8W8H0õ÷ ï›e·ÌæR‚a*ˆö…ñråÄ{¢ Õ™ÃbñRv§ñÅÃ5[=fwÉV{¦ìz›*£ÃOúÅžŒ[ô·GXƒ,Y¿öëªÝ˜àjæ`â «ÛYfÖSí1q*°­•Œö£ã¯Ø9Mjò<à!»yå ,Ç××—Çð¤º~°S»¶Bý>‚nJ¢ìË4+œü ò®ê ™8@ß¶Òb”ÈEƒØ[Ї‡ºuºÔ-ºP^5Põ ~ÿ¤À¦î˧ëK+À°ÑMQ•ùÔf¯†ÌÑSéÖ*.•Lï–µ$åû1/«ú¦î~ŠÙ̽L >Iê«g³T(s3x=š#Q.Wëžèmóŵ*ttû£ð\ÿu’4!‡ñ¸!©”'zx¿Ú0ŸÕ*eU£9H9äk|–™ù=˦åšîÝŽËl¾iìËКWgÙõÌrõžœäûºež3{3ÖM±†ú§¢²i* ýÀ=ð rÆIP)›´»/Á ËJ"¢ç;›ùYwv\/ƒN¼oC=Òs«¾D @8hÕo/»G§~>ògìÕk(üÆ™²Ͳږ—Ì ‡oëý«ZëÊe­éìchÞòþà_ÝwI¦g[ûÕ±îUtŽ ¾œlñ4£%D¬Óx'qQuƧ6p1”)w»‚xR¿¬#U§¹·ÑòŸ9À·u),I±å•mHÿí<}qAa\¢î¸¶PyöäW‰“r?^H]÷ÄÇáá7]_ÑsCߤøâ²*ǧŸ¾´·{`þ=+Ÿ)]ïm­ª%uY‡ITüIì×®-Qñ MjË)úÛ[#¾ÃäY·ÜT¡­Ç×Áe·ÙÊ™›Ý¦›Qù¨ŠÊ]²ÏÑ™ì²M=)°êw€SÑ\CîH×j7–í»ˆÐX!cöáÜÂ4›¥Kõª}³›¢›?3ƒâÚúu‹/%žÈÚÝå 5ü’½§\)¡7˜`–êÛ;oGJ¥K¦$ƒõ›*ttõ)V“Èýðž"A–*l2šÚ´~“K=jú泓Hv’ú„Ù .Õü7J·Bëi]öµÂÎSÒ† #¯5éÕo·½œ dß­+º³k¼Ô5¯ÝëfÅKƒ»ÍW~BQË.½åƒåÓ*±ýöÑ^ÎÆú‡#‘9U߯ºhzÃk§Â/2uÄ£]ÄMÆ’t÷Dìžê>:Å1/%E©}s˜ÏJx½Z¬v½á¹1Ç—aª°ôˆy°²‚«sZàÌ‹µYšÚ¬BïÌsþ¤ ŧóo*×6³hè¾jø‰×jsn+tI¼5RQPë‘Ø¡ €¦8'„¶ˆÄ/†×y‚Ìšc!  r ÍËÓAù5uå%‘üBÌ4–ɤ9˜zͶwÍEÔvî¼³A?fni%%ú ò ­X¾ëÒdý@Aað¥ÌÌ>5ƒÛ‘CG‡"e≨m˜}ëê8Šw®è¼ä ]ºZæ¹Mæ.pPÁ -÷õVÊ|”$ç_rɬ³€¾+cz)ARö¾ ]G+¹êѬÏ>yÅl c lÇÍušÄƨ<­‹ÝÛ7š9Lh®¤×©ŒY1 ¼¿Za¾Æ‹ÒÑÊCV Îj9 «²”–ù%O Dš}gB´Ÿù¡×ÙD=vVVŒL£Uöù¸"Š ^g#®½–¶ÕO[µØ0¼2‚Þ,N²¿“¤—œ Þ_ô®f¿ßZTÒåT;®ÍÒ¾úÀQy¤‘D;¡(7¨AÏE87r~ÒÄ\UËþiù¶ˆ!èü—B—3¬æÈ¯_-„ùk´}°áÖ“[¼Ä±¦ ÙV;`Ž<Óz²Ó{^¹ P!?`ç­·üâ{M–ì ¼”y®gzÂ>‘ Z—±j-”¾&þˆêÍôÓŸïAp9W?wº#›ëqßîåÉß]“b…¼Î·òÛâh¿"’úTÎ{gò}žò9º;J: ²ò¾Ù™º ëKYl¦êÓø[Ç»oh®9¿z|]»Z†E e4›d2¦À¨éŽþôe³~º nÙ ðW ± ž*²‘i÷·:rC ¢n0‡%pßËéˆà1äñ`3ýí2ä¼ )\iý”¬¢ØŠfן¸„¯úÒ`RÓÛ,ûÆ/±­&ËlN¿“^Ó—ËÄ`ÖçAŽA„¦Ù†ŒŸ‚ž—äL4IN„ÓÝ*ž­r’_˜Š³æn«ÓT)=5ˆp:ÁÔçüžÿðý<0Ñ@:X§Ø;ôM¢(!¥S4àÞØe!¶u’~eD[¼ô]è7Ç …¼ïly:‘»§_'[j÷gk:m/N°þ4w~zŒv¿^šÙ¹,Z¸/þA[|;Ãþå‰ÎØÖ¥eaÊm¯É† 0·õôõ–òüobS),—ߨ¼Ï7lÔû)¯,§Qû›Dƒ¤§0•*'a-ù ìÒú+ÁÂ!’T¿Ã,>l˜œ+ÞùE§«Èë¹:]M‘1ƒÔæJËÝ[Û{íoó>¸¹“óVœç ­èz b§Ó¦µh’-»êù½ìRÿåúÿ þOÀÑHŽ€õ„á<¨ÿòÖªendstream endobj 215 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 67 /LastChar 89 /Widths 643 0 R /BaseFont /NSTRXI+NimbusMonL-BoldObli /FontDescriptor 213 0 R >> endobj 213 0 obj << /Ascent 624 /CapHeight 552 /Descent -126 /FontName /NSTRXI+NimbusMonL-BoldObli /ItalicAngle -12 /StemV 103 /XHeight 439 /FontBBox [-61 -278 840 871] /Flags 4 /CharSet (/C/D/E/N/O/P/T/W/Y) /FontFile 214 0 R >> endobj 643 0 obj [600 600 600 0 0 0 0 0 0 0 0 600 600 600 0 0 0 600 0 0 600 0 600 ] endobj 127 0 obj << /Length1 1608 /Length2 5859 /Length3 532 /Length 6698 /Filter /FlateDecode >> stream xÚítgT“í²6EªÒAŠ€b¤F:Hï½H‘*!%‰Iè ˆ E:(½J¥÷*Šé½£€Hïà}ÏÞû¬÷Û¿ÎÙ¿¾õe­¬õÜ3s_sÍ\sˆCï!Ÿ¼-Ò¦‚D`ùÀü‚’€ÜÅÆó‚ÐâS@:Û8£9¤ˆ†A°p$B ‚…I&0[@ îßÀä @‰òDÃí°—‘ 7ï¿,¿CÏxp71p{p÷ásF¢\`,â|ñ! ``€Ü(êꙪë¨\ª:F€* CCœ=Wg8ЂCa Œ°C¢ç¿‰°…ÿ. ÃÒǃ‚Aá¸k0( õÛÅ  `h8ƒûàÀ A`q=À"8êìjû›În‡üC…Fâ"\p>˜ƒÅ@ÑpÀeÕSRù‹'Ö‚ýǹ¤.Ò uý]ÒçÅBà €…y`ç²¶p Êâ‰ËC¡áh¸bàû1àÐ0{ÚÖ†Áà`pØ¿»ó¯:ÿV=…röüsù'êŸàX ÌÙŽŸ|—ŠÅ嶇#È~Š: €ÿ²Ûº¢þásƒ¡ÿ4ˆë÷ÌpãH@l‘gOÀfG. ƒÄâR\ÿ3•ùÿs"ÿ$þü‘÷'îß5úoøûžÿ­âêì¬qÁ À_ Àm  üÞ1ÿW,Äîìùo¢ÿhû‹á¿QÇBpmGØã¤äüËǨÀ=`¶zp,Ô°ƒ8ãzôÇn„°…¡áNË?møÀ""ó:À¡NˆßM•øã‚!lÿÎ'ÏÞfÚ¦Z*š<ߦ¢ôpªc =Q8bÿU‡6ÒöŸ‡ß HÀ›,&ð Šá›  !,áûoòýÿë¬ Á¢á€9®hAðŸÒÿëÿ¯“åß`”P¤íï9yˆ… lq£õOÃo7ÔÆ)úçµãJþÇùÏÃ`0(ùÄ(*蘔ü[ΘÞõYɼ½LØ„z[a˜“å_ŠlñK ™—(²>/ â¯ü"yYç9²ŽºXÖ¸·ÒÝzÝùnKl+“Õ—“»-‹fæNƒÏJ€€Õ[Š×&áÞ?‡µæ®˜‰ ¯,|Ö7°Ê;'fûÒ „&ýyÄíÏé–åOûEùšøþC#u%myöúÆØoG‡w;{>v}hÙ!j[¾Á“öŠ $åv…âN˜ÿ“´²fFEÞ6yàØÎÒ¸ÖmF\B3ã;׫愳5²ŠBè¤÷Æ;X5úY€·Ú™ÕÔ‚ÌÜVݾÂÁ“¹ñ@ý䥳Äx»×·ï³.ïÛõEÊ>lWרò_œñRË{ÁrP·ý¹PC`±\8i½·Ï)E¢+w)¸¡ÒÏßáŸÍ:P•¨YõYºŒ,F•Þ8cã>+üLönÑ÷X‚c§Ê¡Øl¿@»§~Ò—ËýßóÜrÑá¥U·( žbß÷mÎzQ ™!¡¬/ÅœRÇó:ß¾kØÛsË]bßéÑžó—øœ}Æ&?€£¿¼#®Í-\*•+¸y“‡ÆÈ%¥GèØ•«ç C¥¤L@šŸÔ8ô“A< ¦)™<­cÈæ»–aÔ ›û1µSÜŒå¾ñ¤U_¯`AÈ#Å@D!?Iÿk¡b4p+‡‹Ì ÿ;8iøXý½DIªç¾žÁ“²³kÜ~ÂÞg)tî¶HÛWîxnµÍbÒûÖï É™jw@6~az‘‚»fKûy_üè iQÏ'ecžÄŸÖ”4b¥Fa4ÌÚ[ ëñÉY$ø‹…Û‰ †Ñ‡=ªì=‘P Œv13úæÕûJ÷»Ç2jô•eCð²½;#IÁ[2ŸÆ3²bFœ‡^å:ŒOã.–ÒžòÈ ‘ŠAΠͿ7ÛZ]-¿G®ø’,¼¿å‘RnñEª×ü›(ÀpÌ&à~îâŸÃ߯f?^À*æL×½¤¤57«}}€CžJÛQ'Ñ_ã»zS´`ܘ´çk ñ5hqH]‚FÓ©ßä !Ùí/¨Ú2êÎ^Š• ´_£ÖæxÜ^†ñJ&¡0\µ% •#aµ³\f¤8eâÓ7:“ÏòŽ>í›såYåb}VøÎñgú†œ­ú(5b¢_b>–[=]Rº_ø^$húº¡Ù9R.D"—ìŽ ;7çÄ+Y¦`Ø+Ó@{H‡5;·ŒQ—¦(y)_©jÙwO¼dÙƒS¢R/'…ìŠMãbê/ï]H;§ñë²ê: 7ªîeßòZ‡¼'ü`àYíN-þÆñ ž!sNE³QíÜì‘ã º ÖI·»Ê¸9*W%pØu+¶vÜo;ªþYeè•ÛÇÆí¡¾ºbÝàzGs  íQÁp…ÌÔ¹å±}ÆŽ:ÝÔÑZ;àPz?\H'®¿)HÊÎ ¹NÕyL‘óžÝ«Û†ÞJú™ŽcW¬Ê¿±¡®¨œ2¥5,ÕU®$&4Ÿ[ÑÆ7›¦Ó!Ä@{ImVZ 'ô(Ü]Z쉷/z½auð@VÝC÷wéX'!›9Z¾ûД ²x2 ´E_(ÂôÓÚ{ÍZ6æ½µ¯|A8UIàÙ #©~ÁÙU˜±—¦WêpZåìêÕH:ï1GƒÜ·ŠÁ={ø?¨¡D£ßîxðšÎÝ‹—$㢅jžÌM©£§8ZD—¤E}ÝyEŒ^ú$ºÓ[ž8í9 #aˆÓ:S3§˜J2ñý´íÍYíH·È妶.Ú V/u[ýX <´Æ1ú¡èÆ·š‘v˳þÏ•7<¹âñ¨ TsUnQÙ­X?9}iIÌs³­»ñdt][š²×ßž¨ŒOÞ2¤¬áé)ÜŽ=é˜#YÕ-͆‹&„ò€Ô9 }dä 28kÿq$Mz}êÍtíÜç ¶•zy¯L§±` B0eLâf —ܦõîÍÔ*dè󭃉}‘ ˆ;3™l‘àÆRõƒ>!ý »`óš¡í—ÍGÖ¼³÷² ¢â(›ÄYNÇ^¢ñÖu¥‘§–Ÿ2<ðÑ‹¢#qîÄ-µÁµöb-‚7”tb¬¿×¼ªN¤NÒÜrm?øRQ&z¿ÃQÞ=ÆÏ\9"•Vf ¡¤”×þ^Kob`ªB™Ï+ZCí+=.ÞÄ%<](+¸w£J¤Òþ¢¹Üsn·Ìë6ð ñ+ÂäÕCb5"–—9³2-²‚Ù}¤‰Ý.TÆ&Aíƒ;+–aîLWs‡\.Ñ™ëxøWõjÆ„ž4¼´÷¿“bTð܈ïk_¸™:Ò3i÷ Û d)ñgtžì•êL)¾¿°vAAýƒQ-E&o/ؘ‰$Û–~Y®îµç`Æî‡™Ž@·o`…8ÓšgÅßå‚Ë!#WÙ§ì&cé*…S‰³íÀ+oãx$WãDQžÈ‰4zíè­§gÖ$)ÌrwÔ¯Î|{¶Ú!><üÄf?¬®ø«•ÒRîV{ðûÈÁF‘c[V²ñ&š [Êꪥõ‚{‡>ãQ™;¥.naŒ=<Ú[¼ù¼œ×Ì¿”_–+<Ðéb·ýÜa—Ð+tYÀõª*Í™B!{ST•¬Ñí%µß ›3Án²wr7ÞD§y”Ø•CÿUe¼üÞÍ.©ñü.˜AÔM1šý É‘ÌKe¯ðÇþ"â©×}þª€â¸æQ¿’~)¬§úX|¨þ.AjµžYÆåôó^£Éø í»åý ¼w‰¦”¤{äæìz-nöˆ¥ú/ª>w6UúëæÞãQ+W{óŽœxÍiÝJˆÅ ªzê¿OÚS`J}Žq°7º®{+føî @U¥È,=ë•I·v/1>â†o™’R£göŠñìø&¤uò>ηŽL%u9#â.zÛ=zyÚQËËWŽ-˜ZtÊœç)B U;ý¢%ù|ü¤ [Åó=Ç”mÏ+%¹\³Tv HèÎÙr'³¢l½rkAà3ïì"ÏÓM}Ô˜ðµ'´Ñ”¯¢t÷ûMY“÷Tê°.è<®Q¥¬ÛªIqÌ¡ËíiQlV†[]¹È'6EÏå Ò?˜ÔžÚÌLçÜ J_äl18ö3ù«Š‹ç°g öƒLb¿Ìû&ÔÆ^-öÞŽÈ<ÝY¶dÃj´o0ÓÜêŸWx¾ß˜; ³oóøf ˆÉp±ï¢µ•Í{~T ŸMÂ$‹F}/0*eÞÉêøÎµ¸º¶#L)Sé¦z%˜‰IÙ€ EfÜ“kª|°³“«»ˆÜ¥mïÇúŠœMºýš¢ P3™%Ø_Tàvëâ-³ n¯ý5±-|®%ÛCÝ>ó¼`£oî:õû™ÜKLÏÒ¶;F¯9ærI‘ª¶È?*À0ìÀb¤7IGën*½Q³b*Ýõ®.¤Ÿ˜Ú­”Ó¡žÕ0@=žó o+.÷k6˜ÞrõLÏ¢-Aø{¦aØio'K¡¦™OÈ\ÌP þ¨±þúö,Ó‹™`<‡û|:ÇíÇÜ‚L6ÿh@Ü é£‰»ûÅõŒ’G¥bÅ›·ùÌã%©é]!bÌ“­þtB¯‚ /myÀ‹ Uyµ£k§òmQý·½Ô¯¯®N•ÑòTxmM…-‰Ôÿx¼ý•AeRçÜõ¼6±gýyx­j¨:íhí—á ‡FýiëE÷líl¼œynÌDC‰Bµì‡Ý‰ß[;Ž”‰vADÏb•OF¶6CšdT̲Ò\‹Ê©N% $½GºBô¦Ÿä_/¡&ÚgO†W$Ll¢giO™Ï§ü"Œž@D½lƹy› ·Öúž9ѵŽ}î·ò¡+Šú7u(#l®iuüL]7¼-Åw—÷  I^ÂÄÃ8¯èŽ]áZrúPŸ£Y¹ÏóÐw™Qw4"ô]ü­“R‚éýЪ fª7õNù-䱃êî4\]®³5*LÉì`DEqÿãçîÏBcŠÊô’/1Þ”îû p÷¾Ò;nÄ·hçnøì3)7_=.+}®v`:ZÂ5Kè¤ó¶FÁ‚ƒé’Ño”Lç#±ù9S¡èR!³ù‘sÅG2oûÙz CB;¦©†TˆW_¥ÛðnFíϧƒÆ]ßÝ‹ôPëÙŒHº0<ÿ)Zi\~Ÿi ×N±»|]ع·ùåeøqlðò/ÅZó`ôlI®Åmǘ;dCí¦¸(…}ü’ÞìSˆÌìÑX%ÖP\aê<þó²§ùx£×.RRçWèû¢À¤_—ÔìSµOCVÔ¿j$©œõÝ;#²‰“./ÙÂÈaÝ/âÀúÐZÒ“iЭ´O$dfé»@e:Wî SÜJΘt‚Ö ÞNðœ‡Iûˆ-›tOëŒõB½àsf˜NÅÏŠö¢úpó|a…´¥Þ®m„Òˆ&›—¾÷k­ä+ð%¢–H üÁ7?5œIñB3ÒŽÔ|(Oî‹;-Er£Z?·1fÁµ7nýBæ±ÜUr@%꧉ŽXÒJºðoäå˜úš6e³yÛ‚e•E(ùÒêÄáõ3ÑgÓ16=hyô²Â³ôrŠÜöjfÃëœI‘Eå¾¼M1Þ} ÿyЦÍLm=Þ02•2ÏÿcRµèG|_;ÇË·o¿ßiÎtïÏê± E/7g­¼~ÿ¸iþM$ƒà™øaÒ»Yƒo,‘Y·4] >€v·^]1ùôdû¬;ÓÞÇÊ€óeꙎüå¼ÁbMüáªE˜x¶OŠÚ6x²©NG9LÏ x Ú™ÎYÂ’–ùö 0¬h›§v0¸BјÐhø%NêWj 6,ÕAî&Ì‚÷©:]Ýëu£•ùV yÈË¡É_ùºjzÎm‚¤©L!Ƭn6ÕT1Doᜑ‘Âdº·° Ú™fgq´l{/fkívƾ[~*yî /ÕÝ#/^ãÌÆ¥È[²ìÍŸ"™sÇýØÓ¾O7]XŸ$ç$ÿø[Ü–/H»)ާhþY¢(ñ[&•Ù@âIó©UØmÕ:ùsê±®  [þçì¨îp˜ë\R”AºW@Ç5w'ÎÞ¤í´O¼?K÷®‚”y¬ÖÂWD\œ†î ƒŸí©‹îÉ詉jG{¨+Ããsûã o×Ýàs’eæ›yÍ[}OÊ ©'÷_(§â¯þÀž/y+Ü—VˆïšŸ~´È–7J~r×OSèðãõ;(ñ‘ÅéßSâÆˆu£öë¡{ì3TNºc{ÇœÍV\Ø~q` µ9ÛšÚÍéR7>ç~—Mªwf˜§ä'¿œY¸=ãÓ•û^Dt¢Hæ®/Û‹Ö!8‚ÀaZÑ­,¯ªßŠŒßëÜ"tÛÇ3•‰³îo"s•Û”ÎâwX<Þ6ÔZLþ&D£sÛuú”?‰g6çq¿ÔŸd÷=[-ŸÉÂóTßC’U{Âw€!£{£ c;†NÑœ²bÇhr§Ü]ºP;Ø.´ú悼‡õÈ/) UæÈ+†úN‰ÕÙ•Ñ*ùprÒöGÚÓEv³Ç{óÈ^ÆÿÇÖócÜrŒÞ®‚K¾›ßBÇ»Ò.FµÊ*&—:’ÙÅTW›Wk ‹w-4¯ÊŽÌG…Ü'¢p6Ó‚­@‘‡úS9¥Ÿ”3!| ¿”3±”øX%»ü7œ~%É'%`¾×=¼®ÂÝ R‘ÇN#Ÿ&È SÚ*‰drGÝÙäÇ!1Ú¶á/¶\™DVÊ®»Q‚zwùMçW)ÃåÉ ÏïMý4P·IO­±mùeVóÚ–'–—ß ¿mÆkÉåáyØJ;j’Øðiœä£ÙZ…ÕtîÉD§Z“©h»oý…®àÿòGþÿþŸ€:à h,Ò‚v"ÿ? 5óendstream endobj 128 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 65 /LastChar 88 /Widths 644 0 R /BaseFont /ZMYLFK+NimbusSanL-Bold /FontDescriptor 126 0 R >> endobj 126 0 obj << /Ascent 722 /CapHeight 722 /Descent -217 /FontName /ZMYLFK+NimbusSanL-Bold /ItalicAngle 0 /StemV 141 /XHeight 532 /FontBBox [-173 -307 1003 949] /Flags 4 /CharSet (/A/B/C/D/E/F/G/H/I/L/N/O/R/S/T/U/V/W/X) /FontFile 127 0 R >> endobj 644 0 obj [722 722 722 722 667 611 778 722 278 0 0 611 0 722 778 0 0 722 667 611 722 667 944 667 ] endobj 51 0 obj << /Length1 1606 /Length2 15094 /Length3 532 /Length 15945 /Filter /FlateDecode >> stream xÚívstg]“nlÛùÅv§c;;Û¶mÛ¶“ŽmÛIǶíÛïûÍÌ7ë»ó×Ìüu×=kµÎ®ªýÔSõÔÞëÉ)Ò Úè‰ÚX;Ò1Ñ3rd̬ô¤m¬¥èm, Œ¬0ddBöFzŽf6ÖÂzŽFœU#C€°‘€™ÀÄÁÁC²±u³731uP*+¨RÑÐÐþÓòW@ßíß=v:˜™XÈÿ|8YÚØZY;þøooT428šŒÍ,B²rê2bJ1e€˜‘µ‘½ž%@ÎIßÒÌ ef`dí`D0¶±Xþc0°±64û«4ú?X=€ƒ­‘ÙŸmF®F¶¹h¶FöVf¾f{=kÇ?=p´˜YX:þEàÝØæoB¶ö6"¬þøþ€ÉÙ88:Ø›Ù:þd•ýOGS=Ç¿r;˜ýqlŒÿDÚ8ýUÒß¾?0¼ŽzfÖG#WÇ¿ré Íl-õÜþäþfkoö7 '3k“2 Ø™èÙZ98üùƒýWwþY'à?U¯gkkéö÷n›¿£þƒƒ™£ƒ‘¥1= 󟜎r›˜YÃ0ü5(ÖÆ6&ÆØ lÿÝçldÿwƒ(ÿšª?$ô m¬-݆FÆ0 26ŽR(ÿ{*Óÿï‰ü¿ ñÿŠÀÿ+òþÏÄýWþÓ!þŸžç…u²´”ѳú3ÿ¸`n€à¯;æÿŠÕ³2³tû/¢ÿ5PÕè ÿ+ G½?m°6ù##=ã?Œf¢f®F†rfަc=Ë?=úÛ®lmhdoifmôG˿۠cbdüŸ’©™…õ_Mgý‡ËÈÚð_™ÿ‘çoÞ êê?dÔhþõ6ý;JîêŽJn¶ˆý[Ò6†ÿ±ø CPÐÆàA÷@ÇÌÆøÎÎ`gcòú/²ý Ãôϵ´ž£½™+@ãOÉŒLþoï?WZÿ#bm`cø×”(:êYþ¬ÿ0üå6p²·ÿ£çßgýOÁÿ¾þ{ÄŒ\ `V—l ¸ÍS3Òk1s†&„5úz˜@‡‚lKê• ó}«mº}RC·9*tßk‚è¦8?[ÝOm?ö%©Fz0,)º“.óð¼H¨zó‘7ÈÛÙhü´KàÓÎT#=®¤¶À~~gT9Ø™WÐ.~‡ÀŸjg±‡ºz¢ò%qÎ÷E#}´Eð6HùƒÞÔ„R[pzFžpüôH10:<4Ø}Þ»K“MÆå Oák—Ë÷S¹Â#Œzñ0}lƒÿŒÑ¤{H‚ýãûZ(S(×FÅ‹×%æí±,¾"ì°ü‘Ó¹…½»oÂl/Î@|û®_ƒ1y'ÑmUûšX•“ä©Þo¤c×ÜT 8ã¥Ú¡( ç°¨¬ÞÜ(`G˜þ£Ç(îí’h$Aññ`¦@ Nÿ«0™ÌD•[eJK4iÞ÷9}y¤›jgR$·®Þ4ŽÊdzØRTÖLôZOÇÅ“àh"“Sä´9¼RÏ›®UrÜyz·Ïâ1e—ÁÇÀ‘Žƒ¨!?UêÃz.E]ï®Ãgý…a…ê}n Éî9µag T5-=£KP5ôM· ò€®GM1X Ò%›íŠì®*ë —uv€rÍwîµCnŠ…ë€Ïßu@Lu—,­ªœôØzÍCm…„ž¼GŸÁ›ª*¹ð\×ù¸žÜ÷H “ÆçÄ÷Š(ã±°P‡I޵>¤àë$!¾ág‘ÙÊ<Ðæ‰2Ãå9f>¬’yl[±eJÞŸ½ã‹¦ãiinÕC5¥2¿/Ñ g]•ðî ü\1 >Ø“U§ÃêF¶Q`ù̯ÝXSª”¹/5'®3kNRô…°qžNØYfLøMà½Ó¬—Û3\gž¨': öT›¥MüùÎýÎÀúó¬Ý;¬é–‚µEèéÝ[,fjdÎ>^§ý"qOI±dÍÖ×3ó"·°$ÛùhPš2O…4ò.?R)ŸuË3üæ~îÙÁ§ŽçdXõ.Ô¬ãø•ÎþVÛüìË:·iâžÃrX±À#©jw9qr`gÁ¼ ]Ûñ~U'N»{ÇÁ·«F ©!Ìp÷¾bùL,-ÁM{Ì2c˜)eì¡é¨×Ý ’±Ân¶©´ý#™;ž•PÚ1{þÞÜÏž«©ÙBŠ›ž^#(° Xѱ©º ?qUd<*qà 8ŸíŒMú6œóë ËïCµP€%éã‰w›MÈl¡C! ïV¶çÜYÇ¡e¾-2ö~ÌØÈ…Í~½Ù4å³€qí†7Î땹.zHJÛt§çÒ[áSËœÊ( Ãí¢!êo2 ½>Ä΀$€á¯ØÉ(ôã-÷\1Žû²v"B>êgtßU<]œçÌŠ{Áü££”5؈<ÌÐ’wÒ-¤½ÛY9\måˆèË’|&H%6¯j”óÑ"9ô B¹3`Â"¤Ñ.ͯ&ú°(1Ùäë0WkÊh¸5xZÔÂ<€›¨81åø6‚ç牸E tg¨ ¹°cwMä¬å"À“}Yp™8»IÑÞxøö)9SE19—×W£s–57t¯`z6™RhY³/ÏçnæÛ}““‚‰ª§x£Rø]¼? Yrï÷Õýž3LD!ãYÓkùêaWhÌ>Aåוb&@uy±®ÏH†~V¢•·QPöæ°æš¢¥¡ŒÂרøyö&û#tÊEKZÛ{ʃé€cé\Õ³6Ü×¢Î^ªqò#é<²{³ŠAÌ«îLWÛµ2p,8ê(^¥Ø‰ÖîÍø¬@à¬-£M¼­õ‚]z9Í83íd("ª;¸ZÝD„̇ ½µŸèZ9Žò—«&Nù÷"l¸p]äixÜ4¤³üÏñw¹”j¤'};[ñ3<‰Àær¥ø4/œ:ét~É«&Ò$×ßQ4Ýæ´ŸY¹¹2vèã±X¢òs¡$Ï£8Zuüz´paT ‰BÕ8ö0J4ÞlD/ìÛìBÛôø¸²aó’"¬iô5Ÿ'—à “ ¸|шl0µÜŒXÚ†¿Ž¾‚[Ç%3s0ªƒqËkMÀtÈÈžFÉKqfQ”LzÔÜßX‘`ûñ_†¿†ôL¨° ÷Èø‹7è§Ñ3 Ú6k 9°Ô´øiV²Á&à ÚϪF$½Hªtt[ÈŠuEêÅ'qki©Â=%9·¯DÓiW…?gÞà ÊhºƒTôxR]ì˜G;¨'@_Ú>]R6´iðí ÓÐmi…uÕxæÖ1fú9â[¤¯]9ÕV‚cütªIÙnØŠ'€Ok}O‡ÎTbX0&ªÙúèYÙOX=Q©-,j]z²Ä>C‚ŒØ áNqoÊdEÈŠLâ7w%K7ÖWÔ…bm›Lé­$bšÛ•zº–V0¿€òS231²ÅQó¢U£aŽu‘XË"91:èwg‹•ùžötF;Ö8QÕn~û«(nâ$¬Ƀ–X[Xò_E”œFÆUºÄQúÑ›×y¿;^E×ñ|³K^"±ö#À/.Éã'k H6l©lÜÄ ¢âQ­Ðþv­]æt8†mmöNW‚¥Ñ=Œ/CƒUÿÊNô®ß?>B‚5×­ ñ ¾w„ð‚ö$kÓK,s›¿ögf[×Ï‹ÏûÃk ¯``™J;"ÒpV¬ˆõoùß Ö7'LÜÝKx™æL‹}Y¡¡…§êˆ\;¿ÚC,XVÜh{Æoú€ã~×Âä" ccÖ ¯¡3|5Ù0eÒ 9ž. £‘‰Wÿrª·•à·/|9%ªß¾Xº@„ê[«ÂE§<™´[îFüÌa«þdVjëåó«CN,‚(dH¶'Ï—8yje^Ú>Ü«î ;$Hö’ï*­m -»œéRÂh4ØH§K¯z{ÞðÒ¨#KdÆÖ¢LQ¬ª eáïOé —c«U"¶F’á5dWSTC¯\ܶcÅîîUÂS±…Ì_1?¯YGA áV”Å×Ë""É iÓò§¶zBJ7 =náYª¡»Ð%.!ìY·¹µA>¤“ €ê"#8a!á~#Ѳ÷šZ2vÁÙ]‹ g_¶ý¤aûBÈ_RDÁe^â:‰ßÔtkÉϲ©KGtSÕ«?èÜïé/éî»{ú®ùP1#‡Šz"J$²œ£ü¥Ÿ°,a»ã´oÆ!šõ÷Ê!…Å$÷;Ê|g]áZuñA€ŠÉ)ž¬çv&¶IrØýèFÞåýÖ‘ï±±üjf†“›NöÁo—7´$çê"¥ ½A1ͳκwÎÒ-DµàNƒÏ×¢0z û]FîU¼Ú- xĺý6ÞÁàX^PI:4ÌTâœîZ‘G¦YCýpošiÔA o•ü&a|Áã˜=|>Ç"bêó¦­¶ŸœíÌtZ± …ð¹b¥ ½çò,Y9Ò̃1[nï$ׄ¶ Ò(!qQïMÎ(^2 Yu¶ËøÍö‘zݳ/v=\7'p>ÆÒA©É“PöÞ0oºÒŒƒ #V)NŠtaª_ ±êuÝ—ómÍL¦ õ’)å;ßî†2çj ºõ—¦?OHSû%B;0C<2iöW½»£EÍ•Ó(ïÛ³dן{Ÿ¶¯æ€9C=! è>ËxG›b¤®fÙŽÌ*ïÕš%>îv£ÀˆÏ0_¬Yt”©cµ¨-"OŠÌ›öŒ*0uµW]eX™ –‰H)0®ôÆ7¼cý‚’/gs ¦(4oëÞå?ܪ‘¸rTb’’rÎL^7à#V·-~ÉWÑ”ðH‘JáÉÔ±[*ë;ÚüPɰ«álüÅ=ú9…þ”W#‚ª#ÚÑk¼÷:DtóÃ|\®³? jFéóƹU4аòÀ+azý»ÜõI‡#¤='"–PÀ7‰¢¡¡èÙ 3eø|K’’(¼}zAŒïU`%&p”çœ÷ú\¡+a‰¨”!o*› 姦 ­´eåŠõáÌÚ*1…àê… ;/Ž$ã˜cxÃF?šÏ7ùfžöò±Sb,˜Çèô¦o”gÈq7¸&Ê÷k†`°vVx ½öŒÜË(©Hek ¦> ;ûrÆq…ë:Õ鮚éÞU±x/íhŠéPòÂxaÇM…zûë[UL‚Üdá8É-“eCÖŒî ¤a—j+s#¿WäÊ“e'¸lHå)û9<Âæõ9„þ>nà" ï%\ò¯=ƒjÆ;á²RãÅ饗u0´×ØNʘċ€F¦1—cM;Ž…Èbv„²fª'\e—-Á¨åé*ÊÛ¥,uÎ_ξ†ëJÈ?˽᪷Šä–U~ÅED=ðK'¨G—SËéû”‰½XÒ)f½ušð”W?»Å… ’Š ¾B½õ–ÔúÉŸÈŽ&mnBqOG™ U,†dqfz¬[$Àä|*Ãës!¼ŠAÐÉí KEB§Ô1¿Ö…Øž‹nG‚}ÿƒ±¨xðká9â8Ÿ™Ëè #«¸¢xS¯×–á¦#o^3~Ï_Î@Ce>,„ÂèGõT{T ÷›œUHâ&®B¦î^.¶wIsº³ýmÁâ³øÔ=1gZ“=)Š®SšÐ¬7Ñò5¥¦Ò‹D×¶mk›7®ÏÅ쯚xiÿˆDGw’áü}çè Ê9Ó”Jª.Œ—£1©nçܲâ ;ŠŸ'¾¶r\ºœk(N˜¼VÞxB1”¼EK ôÜvºoÎ#( ¹S³dû‚šßf¸K½æè XÖSx;޹Ÿ8Î%ó§ûOg°˜óÊšMñV/z¾òÛOG-·š4dàí㕺Å#Íqæ± dÀ”w#À±P‚ Îþh]鱬sSdKø¼§‰BÄÇ®¡À‰±Ä ã1ñ‡+>16xC@’zò+ ÝnàTÏqWówI¨„·á6€j$é„XõØ72¼´¹8õȬÙÃv…1¶Æ;b¡ÔãVáŒZŸ[ú+ÔÃ,Ø(Æ n3PPѲ7´°•-‰¨œ&Y˜0¦-¢Ñиè´©:L˜eœîTbj›‡;÷­Üàý­dé;QõÞ«t/M!£ñ\º²xºª8kòp[‚~©»ªååt–šåœ|>5YwÃfïÙ´@nöðÅ«øJû‡ßd–M¶FdÐô.‡Åº¤—ärj¼mÖþư%]Ä çòƒQ6Çb)f­h.¤YPOç±à÷3¼¿Ã‚SÀ¦ ¨ž÷µ~б˜©èÜÁ1È­Qeûî~¼€<ÔˆúÊù…æÉ,TgÏí‘ _ Ô¸s2ö…·L\HwŠäf¹ç*wP5*Y¬,„·?hMŸ!S k\Ú3O?@wå8=q®$ÚÈÅÁ ¨‚H" ŒO¨ª¼’@L@³îψ®G‰ñ×Û<¦… £rÝš•ÄÅ¢‰yq©³Æ°óñ^¤’£ƒ¯Šl4Ncݸ‡ÚU:Fûß¹é¤daLÉó.‹ áó”T 1/™Êjg*‹¤P]^´gêºËž©yõM«ïÊúIè(ýŠË x,íËs2ÊòµAþ`QÙC¿d6åÿµ"äJ'L–¤ÛùWùA^,u[ª†\di·¬áÒô[©¹2Ã+܃ ¨éU%&=æ)¹£9Ï3êð êUËcû’<Ë/Ôfñ…P"„è¾Y hß´õêáéò¬¤mu ÐË éP-eÂŒU«§ªÀ³4Dƒ4pÕª‚|`Û¥„;Ô’ðøÁbégÊJ't÷Cý«[š±Š–3¨Ë}ƒj”Übùm´„æõžqÀ‰„éâ>ëüS[%|ùm'`†ÊBPãÒ˜"×Êâ{—8Y¿-ûF뱑ÝË8Ô×¥òü|ÜñáîŠÝ$Lûš‘l¹GÛ œ}z6 ·•줩“>FªS·'"¸„P+DcÀ†À]>í÷Q‡÷™”¦Áïzm4ï5w¢„q Vò´œ*ØŽ»ULJ’JEÖ¡Þvâq¸/1eærø™4·Áéé)Ñp€‡ḵ¬æ¶ú¶f ;eÈ×Þ|€ZÞ6*KdAhA :=®ñ,ëvºh­Òžqw3ô=¸þ¢g•þîñù/äQÞ²Øúú.÷g™jÝŽ²ðéVB–ôʬþ{Á”tnIÉc¸´ó  D“†c ×ì±÷ïÒõäç»QÙjß3–ªÂÝt ¥T}½à–LØ;špA7Q 0+WI‹ û±oëÅ&¶—yµ®tyLûS¥Ã ±œFY£G*ØMN0G#8¿_c51æ¼y¸}ŒðÕv»ë¿Y2Ø—œ5j°á­¢-žb­ù¹]=ùJ ÄÀ!®ÙU­8tÓŠnB¦P G>»Ï(çØ Å@%ùc¶wCù¢Æs -ý(ßÈC,_AzS-¢yyÞ«è ý}o`ã<)Íþ±uãÓü'Ò5Å]’Û¡Èú±óøD€xï¶Î‡î¸Tu¥*ƒï;«ÁJøÅhÇteC0‰ýj§1.]å èIÁÓpù˜L(«BÓÿÜ=a´TwÜSË^%÷äUäºpÿ¡ê§dÁ †ªz ¤¬â˜>£M/†¤þC÷%PÇQpî—ýF!c>o‹ªP8ð/»Ã]–'ÉAB¡ÚõåÂ*b8ñËÀ=×9¨û7ØØ|æ1oˆB ‚'ù9_~™wP¹mA æw0ñ‰ÑWI½X¯œÝ‹øò‘¼Ë®Øìl“‘¨õ 8þߌ‰üWiküÙ™s_ˆ6àÞæ ³ ˜¯I©HËû“Ãò¹~œË}°P‹ù‡.®bÙ ˜AEë,âÆé0nÑ,í@>$«Ü™¿:´GÙd…ß1ÚúKKl™ P&áºXõà<5béI^–¥žè ‡K~r3¦µD T›ÏÅIÉlGêåÖlˆ3Fqœ’v©_ ˆ¼8h®áÄû—cˆ@i¼ËDÔ%ÁFhJífŒœ®€ˆ2ß]Ü»}\TPøY7w\táÏ4.êny­ÛðÒŽ,ª,?ëÚcçq{€’yEÎÞy_‡8Ð0=€Ï"Ÿˆ8+ÞâIyЇr8câuk_·Ð𯽋Ià¼/§)t”hå6°Ò’àg6ªˆ¸ FB‘WÚÐLQÆmUc{º¿5v¥1‚¯9žW²Ëîäöàñ²ê±¸¼‘‹¾Â¸‚º_ø¹7©·¤ùUðŽ••@ {äÙžòifôeß§§ÐmS*W”žuP”ã̬Zà›ï¥1ÝBŸÊø#™Ä{˜(ê„Âβw´ý.˜ìrñMÒe—ih‘Îkqÿ ѪxN©@ŸB´¾»ÞØ'_±¯S»ÖÌÍægò€+~$5,zæT%ÇC­Ì™â2Ük©êe—Æç`J˜¹‡e1ó7•1¸V†Î¦·ço9´D=O8$$ÆvuǨÕ( ¾P§.‹}L@GV7d×4;}1Šˆ|ä¨äSÒ.q#Q˜) …2Ùj? ,E‡ä"7«².:‡rlŸî7&úb1Ì¢'02Úˆè˜ÈzZÓ9õ¶åGõã Ò3z­4I3À÷ŒI#üÞ›ój„¶u ;Å©£ŒÕGŸqüž0úºw»ñË]·­K³ »¶sbÞwËŸÖb¨Ào/éÚÐTe_ŸÝowá%O_Œ)Û}§k•4&DŒ÷ë`>YÿÁ…òý7Ϙ›{ÔRhIŸ¤Ffq¦rꮪlœ,Äø(ñßÖ¶]s+ʼnÀÂ&œ&¾¶0·¤ƒ4Ô `ޤ®ÙK²l2 ¬¾%8¨ÏIb[ Ã’ÌA_Ì lm®×XðH$Bh'ÇwÁ‚®ac“˜„d‘0JÙ¼z[ø?Óo~ÅËÁ@Zy"ËØªãà ­šÕû@âYWÆž0\ ¼Î†ä ˜Ï|¡duÞ!Aææ€+ú:2CձЦâ¿ÁËÆöä;ïŸÁé{ºa´ØÙIªüòïœ5Q[Klê-Õ)D;~;"äÖ.ɳäÍ#À3ýÕÞþçàBÎkã³bðÔB V¥Ê´itò~þ–NêF¶¼œéB_¦\^a­âJ]L\.oΜ ]†}Ï>g±†™¸POO¬º;Nm· €yË$EÇ$¹Ú8¥Ï»Pÿ~¢8ŠJÆìšµÕJDuk9ÔïcÔ©Q\B$SH£)ÁmY0i¿¥Ä:šQ|ÖÂKq?bžY1ñrì„5üTë ãEµºšiÂÖiüØuª¸%rñ9Iþqbšé¢°Äªf¦~~®«¾KÖ ×$¦¦Ž¢M™GwžÚTS³‡m¤ÊöÉ­äÉjšXm[Óà£~{h 5“ìù‚ë"¼~ª´þÚïΛTEÿ4­z Ò¾åƒ í໹¿)JaryÄTû(Ø?_q»˜D kˆ|%›(€[k$˜4*_~ëg’QKÅlñ4 Ñž+FýpA8£,!²P~õxé#¨aŠU£WÜ»XÐb}„í]NiöGËrê-Þ×$•§,\{.ô+|ñÁZ‡`°b=Ì î­î¡¾žÅvÌFfuè s¼ƒíh÷f6bmpïýö©À[Ô“³ãп«ÁŸÜµ4ÉsÖâspǧsLL&6ÂÜÆ“†Ç1œ*»¾ã+‚Ry«zЭ¸}À0Ù˜Ã~-¹Áù¤_ä²·æªÈ棎‚H 4y µÒ§¨]†¼©ìPr—{;>æä'ðˆáqšÒó‰¿ð©‰ßìO4#U³õi}¡¹ú®+Ó?B ÙRXmÂyÍéëòLÍ®þ˜oª„Ôz(à Ïy»Åôœ‡tL·yµÖ ÈWNVKm§ &åIæ±ðMA¶ ÄFE¨qH€^‰Š)]w˜]p·@ó×3zËš î¶eÖhá>]°¦,@/OÝf?¨›:]cÞr¼lfÄK†ýlü6øsèz5sŒW"ÚØÞ5j÷‘à È*ìÒ:†>TSº(ÐéGP ºáçm=Ÿ]Œ3œÖ 0ˆ“NÎTÔŸ Qæcª&žIõuàQÀ'Ø4&ø8ðÔ•ÑNp XEV?þ[h¤ýy–tqi¯{»âA‰•'æ'±«àÑÖ/e”Dîï^Í-h7ˆçØ2ª‘õSŽräèß±ÔaEÜcC…ÓLüîÊ*Ûùl&sôš3ï,ûÂÛ›^ÔÎ?#ªéaÀTfA«üÀ3ÎHEtõà–GG(Ë#|%Aˆ³¹KIŠ#ß™­óJ¾^JU\ÀJb &Ú¼_e/ô:A· -dBäJÝ÷…†ŒjGÕ,[øPµÇ´qæ›Ó¡ÆÞÞvŒ]uªÌâJQsõªÔ‚ Ð> ¤¡í¶*¯ÙÆ!÷$Žœ9 0„rà?˱"}A• ß;‰£u¬“%­Ló¡i}8xË?Лs –Ϫ,òHÙ„PÛüüZËö5ôûté鵯kÜáo$¬”õ¬ä®-ÏA?]Ñ3ɤ;:#4UÏhŠ<½}ûvå¸ù¦š•5»_.ãU“¯²›Ð¥ZH• “é<ëhÄZúmiùdÄ?Q«zùM›åCžhÞV:ߟF¤·}¦xþæ]Z÷L~¸Õróñ /íROÕD¦ªð»T¨Vý$T$2 Aχ¬… ™ÖsÅŸë2Ì€þJ/Ú,DUTÆ«ïøþ¾¥cT3¶Ë¤mÅ—g¶?íC2FiöÙ–Ñnì%2@ïÄ‘n‡6.Ú_`Ñü·pà¹åìe¶¤Án*µ}OºÏ´*•À‘d´IÔÌkŽI”DÙmY:ÎÅn7â­&ÁZ9aH(ár§7f+Q†z}{„ÅäÚR|ÕG/Ë(“:!Σ¢&‚ɢ†›ã o•Ó;ys¯8kP Ða¾`Z^Ã#üÂÿ8º |²Æ”ÊîòÖk!£=à·rrRWÂô„¨‚Iß±N-ýçÃ¥¿JBƒÆ¨ù3xÊ‹Œ©Â¤¥k +‡²ÿ÷ ï÷ƒ¨blfÉ×hˆp4$¬RI&öo'{£öTbSvêT†rÝoAÞ mä»-Ô¾n‘cÔBr±\{9²Y7™±“s?© 1öX‡ÊÄK¨u¼÷l8Ñ hvÐÕCËõ¼C_ݵÔô»vYu5v²Â=Eˆ÷Ü÷*’EnçQeQí÷’¹ÓNk±Â/4!¤ŒJmZIÖ ñ#ŽÏpå9íE'vÞ1ÔN÷W×áBûã¡ ±?A>ùž­x!ÐE ËMR4£Qî|zzéÚFU¨5RBggÄÅ$ŒkÉãÙð{4^$8šV$ø]§†`^GúDú¼º½DÂõá‰ØË){•ùlT¡¾$²‡€©ˆÞök+¿ÇÚÖKˆbã™ÄzùM%WÂú¤„¨%:25cU £NJøÞ˜Ç-©Ê²RNò³§p5b¦Øí­3‚Ù²³Þ{äœS€ín"©›J¯Õ@—jì ØV•‹âV;4¨ñ­Gx·RH¬D%.BE#Põˆ›_Îc‚ö>ä¹¶6ÆÚv ©LQâê»ûƒiî’[š~ÿt]“2Ópuy?ʸý¶ß0qÌÂ,tp÷ó¤Y¥Ï’ߤv¿Mš8æ’¯¢9>2t¾²µž¢ šCnÉMŠº© ¹¯kÝ%ðøÂ(?æ-JÍøîõKέòiÞ'aËA>ýõ&ðº&ó4©ðE º’òO­Sƒ‹r¼açÃj!ž|‡Ë‰YF R ÔD õ‘ˆQ¾À Wó0nýˆ6¡ œ‰'FÆ!ë{üú¦y‹Ø%ú6[µ¢3‹l‹Âë7åA¹.“Üê#§ µ«¨V*ºLxè šm´ÐšÈ^¯>Ìá²1݃KXˆ´!܃éâ§.“í'IÕÅ—„tbÚWk$žÝx’Õ§Zø‚·Zê·©+¼gXühP„¾üV<‡pÈ&÷pr bؾ;¡5(Vú$*Œ8gAnSïF·ÆÎbIƒö«ãžj‘•2 ™A¿ ©ŒÑ¥´!ú@Bÿ¼ep~²2ÆkÖyŠˆk«jdíxŒäªpL9-:’9Xø9ð©ÂYÞƒ+âudÿ€`Ô5²X”Ke‚Îs^|{Ë×òíý¯Ûµ& 5RÅ}Ëi`æuÙ ˆ§2-È)Eý· Ê÷9ù¨©AÎÔ÷›ß3“zÅñ¢Ì¡àEÍ%  Hëï±cí‘@!¦;îx©É÷Zx B7¼ÐìéÙ …ß©Ãöm¼F§¨'?Ié}èµFÅ¿µ.ÀÁ˜ÕÄo[‰±Mà¯Ô1› +ò]£W”ú†ÁM¿ÐaÓ ÁòŸŒEJwUÀf UÛ¡ÿž †)Òn¡ 3AOC™GÜU±z+«>¤Vo}¡®›;¥Õuøi|‘C êákÖÇ͉sc.°>ÇÝãUîmÕzÁÑ >mÈ¡l5‰æ,kàAh&|Äô½j—µ»>J踞ècÚ×É»Œ¨#$ÿä áð¡…nÕŠ9E¸ }‹:_ýñ!gF;}þØ[1Q £9ÏEyÆå‹phoÓrÅúAéò¨âàYCø6¸IJuM_kѺì¦pìz^“/JMWå°Xõ¡q+#$Ùã¼[F>Bûë6Òh&i Œ„AÀjìåØù;GzÂF£ÕïÍ„w% ÷mË`"IªzðvL/À~é\KZ|Ÿo*Ýk¬B›Pv)1ž¥’y+|Y3'f®Øn /GŽD§5°Èfꈿ  Ë“ nke÷ül„¸ÖM4+þ–:¡Öäç –)k„7wÍðn9vÚ#2vø‚Tú¼ ÖM1wz=ÆûÊË´àFñ9ÇîÂõaÎì]YšÜ@‰!#p˜ð4MjÉá!üv=õ=|ý¨l¿zèÖ{70òú?Ù)ã@/¶º·LÅ[¥L °‰ð{ݧwîúÞ~~ÖðÖª°b˜ªËôHnp59ˆŽ¯þzFr9gwÓ¥ÄÞÇâr7ÅGûYõêºùjßÇ×½ÿÒIÚÿ]é,»¨w%0ÓòSG@ç‡(|ÊøÇ7lÉ –íŒkºG²7Æm§¹_¯iU Ld2“Ýxä7în&!]QâÃSà±è;oÝf 4Äh¯~,ëµ±#à³" r7z ÙqÕ輫é€öR†Å#\*£Ö”66ç|rRêJÚ`Į̈Z[ÓÙ¹HBïß=’oNéz~Ô´pHo¿L ýž’Fpõ)#[8ÆÐ"Í “ôpDE2æØ/2¸1ßù~3½í½”Ó°2À–®›A=Fõ…®·‡€DZ²ø>Á@¥ìä²Èq ô}!I»…¥ˆ ÷9—•g6Úe„§²¢ 9H-é¯YÆoÔûX'œÆöŸ€™ ôæÄZÑKô3ô0™;«Üø¢õ6œ÷Ýã‰YŸÌ¾]°sJE¥î„ aúñE ­ª=®ð.rƒ»ÌnNb)Ïl!YØž(,ØŽ¡ÅèUøÙèO«D0¥¬×þÞµùô%àß ÊM)¿âåŸÒÇॳ:eϦ”樱çn™xIŠ‹ÿç“(™òêzŒ¯ƒ‡pˆ€ àå鬡MŽ™#ƒ=oªšžßUpíôÓR ®/CãŽY侑‡íC®y1Æ™0£2ôîá6o‹GúŠhI÷/½Š’º,ÂÊ®…½›•§«HÞvùõiofy…Ý¢–›ü[½®”C¤©gÎxÍ/L¥þ…w¼]²_{îÁèÃgæÙÃi P6‡Z˜&.Jôßû“䆦éÙ7Àù2œ,šƒå¢§Ôkî&ÎÉ» ÛsB@•”¬¾™µõ˜ÆTiÊeÚx²E«g–eC/%«oð?úuý0›ççdàp…YnûV€›\/t0Ä8훢1-}ìªý¼‚¥YâìÐXôEÒ AJä©TxÀ¸f[©Þ¡¨…ï„×ÙmI8‚{beU±éØÃ ºÓÀO%x]›ZU¾Ù=»)CÌ öâï'lcg xM‚ 7˜=ÝÂ/ žlµE±oc±2©Âë8ß0S|FÍ9OU}ù•Ç®«3Nz.ž]„Å““ÉÂPÍ_ Í‹ Z4>‰¦ýŠõc–ö eYó(5mm7361Ë2ø¢…1 .âË>ÎÊ8~YçºÏ]aüi †Éó#®Þò›6´%¬ðY¤ð•&ÂLuñmTp1/ÿhìÎvü‚¾î.¥d“°ÇFôj㢠îÉ‘™ò^5Õõ÷½ÑtÚÔ H2?Põ€‡%~µ™eƒa“Û°ŸÁ–€E¿“»Ç¨!Eh”i)引|•žLl†þÕO–XõQBC‚MÈ>Ä«ÑS7²¢Ú§ïVýd.‰µÕƆÁÕóH•§Ð ?º³IúµË`£=¿»Ï;<Ò€L(gXÿvv{BåØ8qNj‘ò¸Ï&4b¡°¸Ì¯’‚ƒ¼vo º'‚ˆHè4³Û]g÷=8U胡•^`>µ4:¯8‘.¬¡¼h‚ô–[ùÈÏ÷Äø9ˆ2àÃP7Éf÷ùÁÓ»!m™ip¨5äÂÝ’áâj aNîÍW‚N{SÒð.Ò“•Žvěω™uzedšsøc‹r¦‰Ltj©¼±2²|D²1@àmbpÉ{…d ÞÓƒ_\)ŠhÏÃ{>°´z“$(ýöe¬úG0óÃ|¿?ÒÑþMèD¶ø´ÒñJ›PV©¢½HÆt–¨[W~|\.Fùâ–?Ýk‡ÛI´*˜èo;Á68„>ê•··•0”¥ýñ€4Ü*‰yGZÚÉ ƒ96FóKáb½fé% €”gðA!Ž]Ûž9*†÷ÌÞ‚xXbqdp†fˆIªiJWL•A6`eÇIzß/xyy-…üM?Ü1¢‡ÆU°:tœ¬I[í>S‡N¶-Žd•*zŽŠ’e:·&X/¢‡³ôô¢ne{SÑIe¯/XÀû±8Û~K*ƒ„¥cÕ¾´rß`ÞØÙqá©,¯%+ù­ØF†7$;ž¹D‚$Žý؊܃ö©¬#Ã0#Œ¡üruÎ ý}œ ý“Ð é ý¡ YÓdì`¾/¢-Œóƒw$‘ ¦XqÀ$Õ®éœRµûÍ+ã%W?oø"uÙŸ¸!oMl#)›ŽáÈô#M“)-©×ÅÔ”dâ$ãQ hÛŸ¯ë᪄w•6ì;c~þÊ<9Ê<í¬ú;qäI6|¹@kO¨Å+ ÇÑ@AX°s÷uïÐ1js•RŽDOKÀ,ŠñS‡mƒWä\”Døº6J+É$t*-¯‰Fü‘VÜxcšÚŠ9Ÿ‡—¦§Òä™õ¦‚Ê ‡1wÚ/J å}£_f?üùLN.,sd}ÿZ›ôݽyQV¡DÜØê½ô‰Î×)jñå(Þ ïQQŠõfçji­|®šõÉ’8Œî<;±BDŒçštkòA=WN;ÚI(9αâo¨ )ÑMå] ]î猬C«ôÚz<…Q‰›ä“ù '] \w/äyÐvàcª‚ˆbk•gưKŒ^d±ÅBîËŸ1`M¹¾%&Ôhša¬5‚ÌGÀ?Ô%¨`zi·úFÌâǃ<ósˆGšç3eáéØ_ià"Cáéµ™^Ì ; Ÿè0|/óJþc>­I„Vpb.6ªÊ¢:Öæ…Ÿ0FSPžò…»©7 ô%ÇÝRpXpzÖa'âˆ<ñ r›Ü=e¶Í×ÊZ®HË[³Êµè8A~ËòHŠ!Ð4˜Ëh\î“÷‰í&¦øó®))`m$ÖŽ£j‚ѽOû>i{iŽ¢ýK6§ºQË4²xæè\/eB=Q,Ò²(ó°YòÁꢸô9È+¤ž7: X$sÅs ÌÞk„vÎë ­ýÖÕÅl…Ur§É]È^÷ƒô{Û|MVÀ¹ºÉÕÜy¥¶‡©b± Vd9 Ýé-õV ¦˜™³"wý#˯ÈÉ0Øÿ¾˜Ì‡tHFÆ[EXÁe$í3ø ‘EG8­‚¡bíN~Ú¡Ö‹Äà:Ó \am©äÞŽÅ Ú`ÖÌ·ecEª–û.Ô½Uæ2Œäë¸NkØM|ÆZ>gc‡µÄ.T,w+Ò? ‡à*\œz\¬9|‘\å-p³rV°?Ü_¦ä.Q&I n54ÔD<ýdÝ0S ÷cK 2‘„r«õÁÚ~®|R¶éWá‘™˜ŠLš0®4[gÄ>ÙS ÿ¹÷»t»›Â v/V`é[­‹ó<;³‰RÔkü$Ô>åû@Çßc':¥WÄ„§ñY+z'¡¬ç gXæ%”^†Þ>ªÎ'Oœð“ÛziŽqíªG?D8w”ôÜËË7oŽëf>4âƒX:Ñï¡«þ]‡ ïÐ̺Š8P @o0Ö]¼ûud‰¸«¶°}\Ç9Ü.I„íuζâ}~sCë•lÁ¹À¢DÏž´Óë…Jø–¨ðlh0ßK9nZpU D«-g^†C[P×Ö‡l‘ö̾°†æšMáÝ ¤Ôê [†Ü˜AµuåC°;í|¯œöÓkà7‡ø[EÿièÖãqaû>ÄÂØuÆÝUN> ÇXÐÚŠŸ6öŽL‚®3úÞrRQ†ÚàzÔºS½ØÖ ³ïõ+K7ôfP#Q¯q?¾®gÛÖ‡/3™à Œ“†&9bœÂ›(È™µ~Säy9>º\Ѩ¢²!0{•|€8§?«3ú²ñßz¯Ü *Eµ’¿„«í|û„©'‰‚¤ÈHÖ[¾ù©c˜dÉ;_i> úê ÀÙr¤óhkùå×Å£Aî\4ƒª¢9æý³‡µ¼Ì8[ÞÍì–2¿TM76÷–xvÒ]4¶÷ÃLÉ¥¹ÑIYëoìzpÂ>Þ”Ÿ/ö·†ÐkÌcµ[­u~‹¿…K4ælÙÍã½Ó³õ03Òy(ÑáõYw ŠŽ[2˜,.…iŸÔ<,eòåDÓ1ÁRpe†Èù‚5é›!Í^àÆ…Û‡t–ž®Aìö°COP#j–Mb!ôuÖøfÌï’]cùéü”1jC ƒh£ÇÏ~Ή?È®¡¿e’Ô7:\zÓKÒ ­ó1M%õê>dЬ?xÉ‚ÍQ(›*mŒOQدyip:k=’ë"'ÿÞ•Ñ%¦ßÝ¥oM¹\$åËÒîÿ‰±®GóáÎÔÕcàÊýyB©ü¤¤hÓN,Wµp²R=CzSY+Ïî G xáÆGOf{U¿*ÈFGw’§C>!ýr>Qh2“ƒ‹Šë3.Íß‚¡j\˜?:×ÑTcužala+Œp¿¨Æ&d4UqÑÜ@k³án—Rd>y{7yôÕ;ªQâåºÃþq8ÃÓ ™2=Ó®y'ó=ZŠGÝúƒ¿îiKÎj(ã\áºa–fM[•o~ `¡GeJ·X ·¡cD± îú¸3rFzŸê1Ói¶³Ç+h$­³š¢Uqô­~¬BÚƒ«³ú1“…Ü/çöÊÖV©8{®t9weEžMØ?T0ðÛ3›Yf»Kv ð¡™ÚøÈ¶'˜Ýywœ÷ûàRÝuû¦ÑÞúyIáΑ2áuõú'¥e­ }ŒwùÒ'ÞWÄ¥¹¨¹•sAÌ0“> û½Ø4cA䌻ýîùhWw½D쯄êÓâïŠ×õ8dÌu¿ƒ_f˜aù…ù¸ÌWÀ)òJÓp¤Ë™aP— +~&Ü…qÿÚnþ ž+Ñ2¤Ž¢áô§}Y¨C‡â0|*=ÊNŠ™ó'Ý4½`€çù½å óaœ±öøihGë…¡h™Á&ÙDêÃÊÚ²†Ðˆºõµ±ëÜKû^_øq—š3Á̱JS苆t(ùô9Hûf€‰Ðwû#ͨÎN7jN Þ ikó.tX„Ä÷ånŠÊïÚX­–ã{¡¢b§¨ŒÿÃæÿü?``i¤gïhc¥goó)Cendstream endobj 52 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 40 /LastChar 122 /Widths 645 0 R /BaseFont /YIYKNX+NimbusMonL-Bold /FontDescriptor 50 0 R >> endobj 50 0 obj << /Ascent 624 /CapHeight 552 /Descent -126 /FontName /YIYKNX+NimbusMonL-Bold /ItalicAngle 0 /StemV 101 /XHeight 439 /FontBBox [-43 -278 681 871] /Flags 4 /CharSet (/parenleft/parenright/period/four/six/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Y/Z/underscore/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 51 0 R >> endobj 645 0 obj [600 600 0 0 0 0 600 0 0 0 0 0 600 0 600 0 0 0 0 0 0 0 0 0 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 0 0 0 0 600 0 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] endobj 31 0 obj << /Length1 1647 /Length2 13517 /Length3 532 /Length 14398 /Filter /FlateDecode >> stream xÚíwUp\Û’¥-f.YÌÌ`‘ÅÌ`‹KÌ%ff‹™YXÌ`13333Y4º÷u÷ëx3ý3Ý_SUqö^™+3÷ʇ‚TQ…AØØÖ(nkãÈÀÂÈÌ 7·6t)ÛZËÛòÈ2(M¤ ¬…¨ÐÀÑÜÖFÌÀÈ ÐÄ€FVV @ÔÖÎÍÁÜÔÌ@­¦¬ACGGÿÏ¿L†nÿŽ|x‚ÌMm”Î@+[;k ãÅÿµ£ p4LÌ­€QE-)y µ„¼@htø(BÑÉÐÊÜ kn´i&¶«,F¶6Ææ•büà ; ‘ù‡ÐÕh÷D°:X›ƒ@ÏsÀÔÁÀÆñã mæ6FVNÆ%ð±obûwBv¶ÖØ™¢-Èdä`nçøˆª(&þ<Í ÿŠ 2ÿ€¶&–ƶFN•ô7öAó:˜Û€Ž@WÇ¿bÆæ ;+·Ødvæ§á2·1ýgô ©ƒ±ú ùàþëtþY'à?Uo`ggåö··íßVÿ‘ƒ¹#heˆÀÂúÓÈñ#¶©¹ Ó_ý"ecb `aþǾ±“Ý¿cÎ@‡¿ˆú¯ž¡ùHÂÀØÖÆÊ ` 4A`’·uü  þ¿S™ñNäÿ‰ÿGþ‘÷¿'î¿jôŸ.ñ÷>ÿ+µ¸“••¼õGücÎ> àcÖd +À_ÇÜès5°6·rû¯œÿÕZø¬ÿó_á„¶1ýPˆ…ƒ‘ãÛæ qsW ±¢¹£‘ÀÄÀêãðþÞW³1:X™Û?Dþû|?œ˜™ÿS537²´ùK Ž@@ã­áC·¿+`’•UU•§û/¦í߯Š]á¨êfü[$ 9[ãÿXüE%"bë ð``áä0°r1\ÆëÈÃÊîõû7Ë?×rŽæ®fFffÀÇï¿ÿ¹úþ/4_mŒlÿê#GãÖû¿`#'‡Åÿž•ÿûúïKº–æmø-RÒS«p²ûGÅtº;Y ûƒìŠkU ò|+l;|RB7yÊô_*ƒëÆyßšÝæŽí^w¥i÷;±­¨:’€ç¹„^d4]yhk”­\t{þLºÅH©'‘³²PÚœÌê{[£JʺE/0Dã­lp4¾dÎy¾˜ä÷vÈÞFÉ5ÑXm¨u`èUùÇ'”ñ‡÷T½Cý}WÐ]»tYÑð|ÎPH”¾öY_´ÕÊ<¢0ädëËÆgÒú9–ÁˆSÙ»RŠŸšÏÀ¨ê¦mB‘n,ç·òÉÈî~ÄC’yÌá¿ɅƒUŸ×p–ÿôȾ?ÙoN(B¸›÷iWw¡ùÆnS×O·J|͸éUºD½ÑÈ®v{CwfÌÜìˆcÆ{íiŽeóÅÆÃFÑÏE‘‘aåVÍâvP³Âýáâ̪4/@DÔ2QP\±ÞîP7ï)ìÄ:źˆ$?"i«u¹QÌ ¥ª>¥8áÕw ÎN:ÄT¢HÏ®¾wáÈl÷,‘t¢õR 4©´ ÚÌ„MQ{ÉÇé²Õp N~™ ÞOyî›3<Ë ‡?,% a† ¯t¡Ì;^uT§°_¬•#ò­¦ê—€€²lå¢ÃØ,K¸ìv×ä¶ŸvèPü <Ìtü~Ðú3h¾ÅaóŽùLþa*X†ßÌ{)ŒZ„ƒ‹ Án}›8ÿù[çÇú>¸  "»›iˆ•Y…¬0ìEøÔ•]¬!*¤¬ tf2Ùó ËŽO—ëIrWMÎè×ÒBgG‚<$÷X|¡*©“Ïõ­9‹5LÄßÎA×¥3¨ó,”*;@‹\ø ŽB@>‰®×Ôe­¯NôØê^¼ö–(UÙø‰8LDS?{]8 “:nÂIaš}¼¶/ªÓ²Ì}9z½Z«‰Ý9‡Ð >Ä—AU¹×“Qï3ÃQÎyå9ÞBÒ;—61ñeÅÁpïmÐKÅVø©æwüLß[\ûµ½ â ÿ¾0ܹ,öoTÂÙûº’*uÐ\‹Ÿw®6Û©ñ¦‰ïaSе³Q…òàĹ5KUüœÒz3o×Ökàó\ßôÛ)àÊsn-ÈÓ ”w:LÍEÇzj¾[LÜèýÓ/ÂÿíFÅRs5å*±òŒ¦²#ð\z%<Ò‹+ÕEó'´ ¢_Ü£ÑÖ×ècdO×Ú* zÖƒÿ]Ȇ."Õ³÷¬]3‘1JW#£U+Æãš¡†x8qWVjJA©<×eòŽÕ5ÕÔ@-îaŽ»¨ú’ŧòâUl¬øM—Ýö„_ÄÂ?'¿)Ðjçè87”8{pcîûBÉORÛÊwu7Ë-°ë éŠõîuup²BÑç C®·!Å+”M\ØÁ³v)OþŒ°2¿1 ªJn‡7S„çPÊkÉpâê¼vÂ!ÝV éŸóq¾õ—þ«Û×î Œyèëgxd[IÀüÚÅi¬3“UPŽ<ÁÙƒâüëýLZ¸eƒ)M‰¤Ý«Å=¿íe¬uXk!'îÞ±OÁötc–™™×qó4ã7ÂŽõ¾ÁÚC­Ïs (2s-}t‡Äqj«`ƒWf»Ýàð=J)ž1ôÆÓiÚšô¾‹]w8rÆÔd#6ñKˆ¶ã3ÔuF6Gìš,M ž&Z¦qÙ¹”>”Ôe–fnU}øÕã§Y\cKmK5yóZR.Ç:y1ìIʳ%·MÿH#²WØê¹>.-à{Pà PÏx‰ly%0žÁÌt\¬§,oZkÛ†bª><ùºí·†Q©ÅK€ ¶†ÕË'ù¯È‹Üès±)¡ê?vqñ²yhE¤ý„ÛÛÙ"ܪ©å<j¶æ‘#‰—ŒÇmä«i‡ÚàÕ쇩ù6P¾²–(*lÛ´Óx3ýi\šD ¦=ÕH³ uÇ› Å4¾Å¥KV#ELhßfä†iÆõùSl2$òÙ](0]¨81oÜs¥+9Ž.Ò ñ ÀÒ.™WqðŽÖûwÁkêùÇóH25Ò±bÁöxº¹i,Ûƒ{ææ0mó+l¶(Ÿ¯.Ès~¡<½­3_=´µ<ñ‘ Ät¾‚ÂrM-æ¡ô…¬p/^ñj¯ÿp Ýê˜!;`Ã:2• ŽLŒà én­ƒòéù5¨€‘‰¬¬Ná'5`m¹wÄiÚX$‚§m»6ÈÛ­Ü öó!OGÙX Ú>SÄ02¼Á•\‘€+-)äú ¡kw…{šíi™”ŒÄ¼z¬åà¼ø1E{§ r7𓟽SÛð'ýlƒe Ùc|¾IéZ-[êô_MÈP»ÅįE[Ô&S-±¥Žî ‚ÍšÓvy]Þ/!ÌB¸žNã|_3Ôá¥Ùtðâˆ÷ .ø#”Ô?¯½ÌáË£ëO¼A©§Mü©aR+ÉÄ Ž¹‚t0ºG2o8Ô¢¡KfÐû} †]¦¥7ˆ¬;ð!À«ÈŽB.$¦Öºü3âê 3¶Í†å„%½‘ºÁ{{ÕÌÜä8eW º©ýÂ2  â%ëÁ˜½)òò]¤%öø…}¡Ï%£¹ÜdÑ’›ûJú*&(¾²üKve˜¬«ó#¥Ó7²ü oë‚âs“g«Ê{(Ý`si)4ð?~¦2¸ñ—l¡Í"°;Z]ûc#_–48dܺ»Ä´'Òã 3û±ŸY¶ñ¨ßc ›\xß“ľØðç³·iæ»Ü]ÆOx¥Ó¿Nz4ÏôÓÕDéâsœ:dðIõ É‘¬ÀöšôN!âÀþ„þœÖ·È*¹iKÌŒâRy"’q—éz‚ÚA)ÿ ÛßDý“lÒý–ò.ü8]Âî- ¸¢Tîðsµ"z‹ÑÀ†‰ÎÓQYÊyow>^…µ¸¯åEI¢ è‰¦‹ }$ºÆl'C®k¡r¨a¬ ÏÙÙ±Áé7]_둳¨„ˆšW°Íì´Ðö±³çÐò*žn‚¬öoV¶å¨ÑÅP‘hº¸sò%Å_÷¡•ŒšØ½ÛáfÈÖ¾­qß_é,¤òb)Ç7s&û½Ýæ“—nÌhŠÝHŸ(qÒ´±šã¤üoTÆuè¤Ò s¶öRuŸß!ð-Î Ö^?›×jΦváɉ‚~2+Ä—¥›¸Ju¯\Ü ö,.F.ýÙqy'œqWâSvˆýøÊâC?°¤z&©¤ QnNBËD%‰t†ùo~îç'\¯ë Æ4޹¨RÛkÒÌè®_u WøÚÇ;£Ï,·yðð¥HŠ&?Òê4;+ö§÷Yâ Ý¢Î­Ó º¢˜Î€ã`‹©ÁzH|šp,•Ÿ_ ßIµ?c]Zb­Ç}:’ƒ`Vs­’&«6#Ü¥:þ„‚iˆ#ÛÞMõ}Ü»º÷ˆˆcÃÙûÆ2y V÷iLŽ~ä^00C2@K‹š[—ªmõ+?xˆÿ­÷Y_Mµ\_û889&Û[!AÐÁÇvÎsð“Ûª}y³éð œô¼”4Z˜eMálrbNФ±yiu¶¾ÎÀ:Ñ¢&|fÚï¸&¿Ãr¿7ò ƒ!co£÷K=>F¹ÕŸêC;–su=„Ì©µÐA6Û‹‘oŒL1‚»•e¿šµù#–`´È ’8â;Ór•`2­àö+Á¥ ^ò£.ƒ Èlš™K‘Ö¸fg¬úÙ9ÉÞŽÒ"3yË“SJýáž–›: }£ðï>1G×\ÿ¹XÛ5ö Ý:tyX^›5r*ž¢ åS1:fæ™÷„/po}§E­hòS¢iµ—„‚å2ÝØ«±Åò°W¢t`þ C9×]ŸÝGúË·ÓUbôhÅÔ+ÏM›âÇ;Eý{æ$ë-Àc•”©ReFËÖcôÕB¿Ôq•N!àÌü™-žíMÔ¸]a“ÓSe²·RS§ØõY$IýÁ…ó!Í'‹R’-×'J®Ó+îsWfEâòòÔ‡rñÖ@x´´'̵?ÁÁÊUà•ïw+¸?©ß‰k…$Ý[[··Ãl,½ÇcÛŒ­àñ†ÞÁ²±¬ S%÷#ˆš!ÕÊʇ›ÞvÜ…é(¾Ï‰xë=Ü µìmŠ•hl0Ǻ‹u«¾–½ž‹™ÃÔ î" !å£ÍÑ@ÐägJ­°Ä|K²è"•—Ë>Ý™Z T§I&5¦8‡—ˆ nµË"ëp Fa„43 Z@¿„ìS÷Íz4LÒCS´êº}A >æš±£­åùîi§êÃr©#QÔBgX'Ä"¤Ç±¯çjÕ ßÊA‡œ`sjp›(á3ë0ÖqH‚ËÏ£?Ò u('uÇv_°.î§!Ì‹nÅùл1—²Ì®°•—o@q~pB 7†Jyb‘DJ¹£7Œ›|`ölþ¥¾©‘î«€=ßìo•à)Ó‹V†¨l(["ˆ2]Æ9‘3yŒhOÞåMw8Ï,{xø«Qw;1i-o#2Cö¿Uâ*Qû02$ô`}\ÅÙÄÑ\Õ®”0ºž¤ SÁ…*¶ ªLs;?ª ¦‘vöúJƒÓ@©D»¤3L™~ÂHŠÎ–ñØÞ(=:ɹ‚ ©r"¼ñí¡Íl8ç¸ë]á*¯Ý÷÷8W¨ÉÍLš;ÇØ›hËbÍ/¸Öz6~ª y ¢ež¤çC7­î;|ê‘2E_Ÿî™'9ÎÇ07æj9 `Ãzô 5‰ø‘”•à©¥ÿÔŽ÷€Ã#“$Ü$j€ Ñ×qÌŒÂÄT—î‰vÚÉw¿ Ùw|«¼ŒÐŠoJO´ ½âº[ =9H3$¹±cfÜÔþš>qr†2/-&-ÉIŒ‰s’¾äˆÒSA½vË%èì˜õ7™±¥Ø½î‚õV×-µB§ÌS“ø9î®nxf('é˜îEE“"ÿ5Ÿ)×ÚjøËx¦>¬Þ/ ÈØòÛ ™¾µømÝáù•ycP™@®³ýÛÔË9õ§ÓŠâ·dd%Û'fÖ†ðs—´+ ¯[“»X?c5øó &¬ðô`©ôUög-нË|&!œzëZžiååa–Äê÷{…{MÜ îä à wÎû©yz5=Û3)3¿-‹|5¶Ûviû7qWêÓ2¯T< tªº[ÙúÜÁ\n%¹RºXÚlHy’†a ¾æÂTCÆA¶6©£Í$΂ÝwMY‘:öãMÁýx ¼ç$}$87¶øýÍoöAhøÇNâø‡«ï·¶á™`°?ÝKÃ?ñÙæö„æ'Ö¿Õ. €6ñJ­´ª] ¦vvL°ÊDìÊ~@+9ðú(ÆÏô±W´ÒÏwšÒL{*ZY¬TGaO\TK˜ bîºpŠßñ¯b–ûµtpÄ’h4~q É%;mötZ:]Ðÿ^ºƒFKùué.aÎÖ´Ù匰vÅ»]Ó êÛ|Évï‚!.†aÄÆî{WÌ÷Rñßeo‹6EÏvñ‡ÅHsa§ƒMì)TGñ© Gƒ€’öJJ}²&–ˆ)“¢$W?udÐ]÷†x~?/g }üƒ?¦fÆ, ¦­s[×%ÆÐ›‘H@«Ý޶,qjØ;Z‡ô¬óõCÜ퇺¿f»¢~ɶ4Z®+Ðê"l±W&¡ì¿™“ydh›ç©º›41·¥Î\®Ã”£&Ê>ÅêÂRåþyúR î5*¬ŠOÂÄÅf”˜ûØaÚÜŸ°¡ã|us½O°•döm™¸ºW~æóÎ1ÞÕ¯`Q¹Á/æb<«‡0%v¶¡SuPEx ÕpHö+ø|ÌC7÷ëà›UÂȭѬÒs"*ƾ~ÿ@#¢À'|æ”M”X¹OoÑ¥U¤6¼ù±xVWo$«–%.΂žãôÔ:ˆì…6×:kÖ!ĤwYo⇔œ4v‰TÃ’ŸGú­G„yìöUºÀ–µd)ɽî_,ßQmœãù™Rð½SÈ•VIo©9ö˜$ Ü­^ÉžôiòßÝSÙií± SÊ$!ûÕÚ´Ii”“Q‚ãôg4媽Ñiî(JÓ'ÅÀ‡ÝÃe.¢H©~ž8¿Ëqo؆&Qx¾lZSh+- ?C0Àµˆ5{·´— 6vFŇ‹¼€£&ü¡Ú’ÛuºÐºZÿ„s:/TÏtßoÄ2µ¹ûub Û‡ŽØT÷Òñ)€$I¿W@‰;D‘³Ñü e9)›láD~=]’ÊPw$O=bê¯ÇEÞ¹vÜoK?ÌNΓ™ž§9áþñy¹ÿOJõÚÃv€™8¥ŠÚóõ­æ Ý·5ŠXeò â=Ì;á+ÖMDŒb TíÚ™K]ðã<2·qn Œ7ž‹„r¼-¿¢GžšÂ%°Ó('HÑ=Ñï¥R3ØÐz背O%Ò,YÅEw»­ŠN9ÖÝúy+»bßÌ¡­å?“f7¼UæÅ9ì—À±1žRû¶kŽÄ{¶FD]•˜:¦2BƇ`x—Dh ë(ÑœËú˜-SBDÓZ’^ÇlŸžLã$~tÝ&!–…dL“·ÓñÍ^ûð†S'è»|ó? fÙ~XÒïÐ)SêNJˆ´@ÑøÌ±n¡ÛA °ikìh)ùšw¹œaY^ÊHVj|y—Vg?AëÅ+I¸i`BiÅüø™çÀs^{;É[äÛ]V­lêÌVŒT«•²»çýS ˆPéÈX¯SµIÿ±ßPÞ˜ï»t;P‚ úõu/>¦`¨1¾~ ÑÔ w£ý s»ÄxIði©)Ú÷ÿÚä´¬bÍûL?G§¢›Ý,Z`Å–-ƒ‰“B©wíˆwÊnËÅœ gZ€†Y¯-XâeûÑD.Ç ~pA‹Gé/¢o+ëDH9EnÎÁ|*K°’ eŠ>®u#è2ä|«úžt‚‡à\â–Sœ¼-z’—?_“P%×Õgqæ-Ðhº{dá+JJ­ý(d$?‹ÌbÓ®µ~ÄÚ5J+ˆü „Ž´¿5 ãˆ$0–ó9Taåê]"Ø|ð$BúJw7ýW‰Qº+Û½= ÈÈþtÂ9‘¨ Æ×`(è²0Ç2ˆÍ'{¢§sÛó‹ÞÌáí4ý¬R%úÀθ–n*²L ~ã¼ /æÏZ1eòrÅ+Ozý¬hÃñ €¯ê{ÂcNY÷öLûúh‘V(OôSŸIÎF{s<K¾ï§Á_ɋЩŒ ™r°OÚ%‰”…~ó%#-kd]ÈÀ¡7@"Ź0ÒäË›biý?¦Â”wžÈó¾=^NòD¾»­ÖjøsVÍŠŸ-áþ¾áèÐ?kw ™åÐ:~O%¬9«”t¬®°3KÈ(÷@aß — ²|}FQX÷å$‚‹I—ž6¸w´­î%4$I]ÁDñŠÚ£gb¤[ÔcKlú1’{È/¦ýÅÓ DŠ[^&,þ¶JÍŽõ Þ§uóâ¸ÆPHVÚíÖl¾ÃL· ªÃhßÊÉOüŠèåPjY#f1˜É£´ŽvlÎ6ñÒEš–«Ú¶—/ÞâhÕÿ¸.×Ìë!õ¾À+\;7Ò³¹\ÊØèXS—³CîuâÇÑÀLI‚ŸÑ~Öʈ?5É«7b–Nµ>L9­dësÜl‡ëÂÇÀeýÒs®}^Òw’¢à& Ëã=àÍ‚û2|бˆ,® IÉ}¿&Ÿ'ÆDÃÒz¡ Žå7–Á0±l5E'%ÆB¥ç2áÇ[=¢D–„jùÕI˜ñsM ¿)zë-Åb¼©õÄ÷Ë”KøáíÁè6}ÿA½Á{.ÿËûЮš;Æc÷üÄ ÂpÛìæ±±ƒ€Ÿ× Rˆ{²¯U-/¨éD d:8:Ïq[T‰*î'óÍWÿ ­Ùöuw(TCA †ÓÀF†—ðûfd ¾E»GÏJºÄFÝ"O äV57÷Œ¾|ÐÕþÆOwfí±f &avL?l¿\‘óX¬ò.Ä*¹]§¡üÙ¤Pz$w<ÎI\÷§;üƒï­m¡%ÏvêùÙÚfsõ2È5Á(ŽääÓjoX[îÊqB¥-„#û6ã'ÉÆç•uFo%=IÓ*E;ð9 ‹ãëÀý»)'†ûJ¶½"7Û+%ÆpÇZ ›ž³t ¨WIâê!ti«Ïá•Ýnýji\* C°"£ˆW³û>UK^Ú€ºrËÚG÷7Éø¼âv§wD¤µü›ÍÞXù¥zR¹k.v}7pR3È]_Þö‰»@s.íág¡3)N‚„@ïÈ ž›üŸ§Ï!–“¸ížaE½|‡‹-,ãP“ñ˜óéäåYüÁ´Ýþñu8Zý‚€¾û't‘×§WT°1!±À¦|OÊ^41tè+GAìò©¬z“{‰ŒpÚò/úOY[ûâÅȇkGÕŹ°„£‰WÌV¸È-¿øPâg}1 ä%šqp¥…˜a~•§LÄBÞ%Vìlô i/pêŠÃÏ›-ªÚ¸òøg¯#¸+>Óš€ÖË^KžJŒ´oÓÝÙ¦ÎmßÛç5•8õŽä0–/Áö»q’ 9Qé¢'RÓÉ%)ˆƒ^ÓÄ Ê^§­0Y|[%„‹â“g›Æû‘…æh7ù c,,Xs,îiKÁ¨»êÌþ»³×zPE0$OýmƒÈ„l;VHáÅ‹;È<¿[J‡øÈ2“ó®D¤BdºýDÕ29Ð>TnÃ#וŒš|¨…ɺÖçðê%Þlóf@Íbò'¤>eG9%[ž‘¨12‘óqJ­^ U^‚¤ŒP›ƒR`œg7yÇÒGÆ+Ú+ÏE1re-+Ž ¾È_vg«ˆÃ™€X m|–'”Xõ\ÔÔ2¶ ÌÆ¶Á²=(½N?W,[¬3ãÌS#;!«¶XÛ÷¯7ص‰œ @§`ƒÂ øO¦/QYŒ¢Ñž[øø6t9'ú‚b7…ùœá÷ƒºrü©p[/ÐGjQD¡Þ,âh}´£ˆ‡^Òt§ƒìÿÜ´¨®‘ò·+²`Åæ’‚ƒe®‹6ÐÃdú·k"9Ý…ð~´:ÂcÔÃþRÿ×és¯¨ï{ïP_¥¥ñZ# a-—ZvuE‹© tuÈŽÎ^Eè“ÒŸ›zÝá¼`›n¼¶ýë`h‡5XÊ…Øó›K°Æ0á?‰áWO¶;a9Mæ'¸÷`@Û6ƒÎ(dœD–aD EoïGµßÚÉR¾³2_%VxÛʆ›Wmp'* 1³¤Ð ÚG—àä·óµ(,÷r¥GaGÎâw 1l±´eH|í"'o»ÍM;wja¹vå—+™V’ðƒ’¤‘ÚæÙËCãoWŒšÇ¥æFκl$<9G¶£úœ÷x~î`G/™—a Õú¬RM¯¾áM—#ž&íi «\9’‹öä[ßïÄ“k’-ù™‡‚¿Ò {?‰|JGª"lþ¬A¥»÷˜-ïÅ9\6þ%-¢/ú†²­Üä‹ýr¨‡”Ÿù×f-s]°•¬’އÅʾ äBÒð(Ìî}VŒàT‚d_Ò&áG[ÂQ²ð„:aE'$¡zx‡,œB½z“ê\ 9ú9A(çߺ •7|ÖG!oG‘ç—»Ã?x—ÁC`¶|É:Ÿ×øÒv¶ƒ8ø`Õf§ññæî©…b!ûÖûCÜÜ ¼~¶‹ê½=¥èOŽiâ¨EóVø:@ R üÐÉߘؾc¼f‹U¯²dnØò˜Æ.~Õ¬õ62àç[Ï!ÁÖ.ö‡rÝ/8²l•ù‚Ù>M£ æ)[üZ¹†…óÕíQ“‡ñÌ?“»ÀPL 8Vh>ùån.@J&7¤¼È#'¨¡TˆD…|=;éÞC.а\5mx}\J[ÿ·®æ; ‘ꌓºä4cÓ”qYDcÖçÍB¸Ó¨÷¤¾¤³ë9#è\%”Ò`SõÇ ýYöçsÎ3’bz ¿ÿÍ7.YŠBmÙPMd}9Ï=ìïŸý˜\3°Ýèâͱܓ¸Ó†ã ³¨ÞPKC? ܼèCýS<ÞQà$Áo«$Fr8aÞåD˜c²Ÿf Å“TZ**3•ÂvzZ^;I-»Ã}ˆC9ú8ÝÑ´PpA2Qú_±| í÷Iêó“‘±“¦EÎUbá·´=‚Á$µƒ„ dÍF~|òUË[‡- &ÐZO ÔhEnBTQaÐ=ÎÆëx&=ìcFüD4qÌ=0‡åWXã2Ïd‹JÚ;¤\íúvÖÀðͨu¡^=,4•*€ÌÜÔUUT’L˜¶ÁÑ{{ r$¿gÃTJ¿VÙbžÃV&ùè{§L|x)^‘ây™™î¬žÀyìôÙ$|lˆ7%B_„ÄévûvžK¨"Kd Üœ²0OC,Í®‹ÑÁÀ³Ûõ°h|B¤jsZùéV×êNÙ¯sʯ®Òк¹—4ôÓºú~[ýp¤}õоm|åMè%JØ_ÕÌ«"𸬎ÖHýÙ/1GK6˜¦†#‚óGÚ9ƒöÀ1Æ8“Ê‹k™L,!äßÃ¥}´qØëÝeé±2±ªL7,#G9PW¬¦ÞÚtvHf4¸\©„³µˆ'c£Ûµ g,~ Øòä! ;¨±Hzœ¶ Æ|{´/àDÊÓGXëín‘¾ö¿ô帀s11é_Ì-©ÙÙàz„VðyàÜ’Á ‡q p—¼Ø ÌwÔ3¼´ÿ¬*‘j•vØòK«åÚóü¸(Íz]³ií:©6žs‰Éäqèç}CeŽ4qezý>ER šïpûuS¹A.‘ۈݢF:76ÓKdÏÏbviÀ÷Oë/‘öB½ A舣={èùœƒ' $’G½òG} Œ~fæùÆòu /ÓÚ1"©‹`‚¬gãz”¯Þ„4æÜ[Ú°™É¹¾¯ýgZä@YhÇîjÏa@þÍä™G°-ÓÁ+k‚Ij‹÷3£ñÈý´ÿ/·áœ_zöÅUàE(r°ùÛ/ñàz‹,]a$l‚Wc±Õöœ?]?= )DUÜG>#?Dò·&•b'×tW¬Õš/›:' ?ò7Çýq~MÚ2‚.`1ÔmL+÷àg#šFB2hŽÓÎ1T%+Fn\$l{vtôËŠ¼“dŸ×XÈÓ®ÈNLƽ¼SžÞ¥þ0û¢0«MÇ&A»ųN†rÅÚ[:» ”RvF¥2a§¼ÜÝDÇWÙߣZë!V|×{ïPÚÂ⹺%0S2ÞÉV± :x±yŽ–lŒÖ³Phê:wþ!.9¿ð«©Ò¸kªžŒ8 .+ût‡tÒúÅ !ƒÖ"¶êùúéÖ¨%¯NÒ$¹vü}‘Èåûãäð˦™EF×=Œàô%3ª¸á: ÔwSª-Ì(V¿¶³Ô½Â—óÎ÷ÝíUÌÁV·‹¥ù»m`Šœ[È:®7.Å Ìz¬"²KŽ}çmñØøž’Yœäí™—˜ý ŽüÊ'ÅúØmÀAÌùÆ™‚ øI|G!-#œo?Éár¡ÌuB¨c6‰Týþapgæ í‘Ü à’yHJ«ø÷K}ožÙÖOÇ}DÒófGÇw‰­©xyÏ©´ðtìYʇ͛ª²IA)¬+¾b\!´]q{Zy›ô°ꊛZ›IøÊ~å{»€pņKýïb3kàÃç‹¶,è³yÇ–È¿Šð `ddkðàéðÔæî»ð{W< Ø™' à½æ>U“}©;FÓˆt¦lPâ«£aþ$þÝ+”¡¢¢%´Oük—k¡±Ë…ôÛ¢<¨©—NÜòΘÑÿë:!u5ꆞ‚1[ýdÚ ˜¤hùò¡ÙÞïP’òŒÑ±4W6 ÌíyõjÕïzŒÐb­v¿Lj©übƒ6îe…F&!$‹;Ûýóü]ª?è¾Uæ‚\jûÂy\]óp• ÖG(#Ȉ8²gÛ>2Ô¤`X|ÜDWÈ£/ŒxzD*» ¬^DöéS®z)èäk òãÖG^æ†JŒ \”¸¸è.¤¥ãJîžá)]!phn¬.w¾’~{ÄÒ0ßàkÇØ0óŠ©ÇßÁYmø˜?޾¹ãÙ‚á¯H×2T·2É OR,RgJo&SгG‘í$]le13ÐáÆ¡ý»Ë ‡P”Âݾ8H¤0óù÷B0 D¼ò: ÅzvùžM·b«Êf%­jþ5œ^•Çé°™q . ŒÇ½—¾Ù%߃†¤Å*Ü‹!þëp¯¬¡$Í–M9>Ä`nEê§ï³TÅ%)Èsì9Èn잊0¶*wW7=t56Õf„Ý–l"±g?­ÑrŽÚÜÒ%™Õ ~ª‘’nŸ50þú [~X“‹˜@ K_¾’e4chqY[ ‘ú{+Ý9й°ÍÕ#üTÝ=Ž#jFyM€v§ú(A e÷åE—îlw8• ³Fà=1?~™X{xa2máeW,!ô úšâ¬ãªsÙ‘2[Ê2«œÇï¼ Ð½¾®<˜ò\&E Žzïð9ÛÃE¸FŠ©Ñ¹t´^FˆÓf#WN‘C1 Uõmš›À"ö&Þ5lᤢ_ÎÞÕâ?»g’ Û›àQù]Op'<” [J¯Ó<™N`8hXÑÁ+˜AÿÒv±¼£ß‹Š—ÚÛX½‹ô!øj©1QÔý`»øÁGq£ŒïF¨'BÑjO0]«‹Ø™p¤žR‰ùõÓ°è Ðé V ›w1ƒÁ+ŽOˆ^ë¢öó·A>ãÓc”Í£¢ ÁjÚÑ_–Wœ)]X¢^½Ë¹£§¿¹nÚFK‡¿‡øž…¶`ÍÖæØõ Í¯3*cÄ©n˜ò¥Þ9nRÞn‰4¤‡hìïž6¡ 'i$¶hu"í%/ª¹ˆ,ÆÏN˜ L¬ž·áÜíÔ#ËsîV$+E¬Y¥§í7^ L¦=ÑeÀì…iì{úɼ‘ Ùøç÷Á~ÌTCKñMü2„·ãK‚0ŠN— Yl…†pfYÆ´ŠAÛ ^’ÍW–Æ­úǶ /±š>°¡.§ºIµ,=€ w|FÙ°{„{Z"DìÝ q9i·ˆßèì(ÂÒªiYvJ·•Y,€:"LØ‘ÆÏÓ1EPÃÖþàã{[Q(åe (4¡)_?Ešˆ± Ü;`°¡’âÍs@ʵ³ªÊÓm‰ó±Ö¢›Ý¾8´„oò`ºl,:˜Ï[OÆn¡Fvéi@Ξæ±:•Ñ’à׉ö<|K¨×IÅq0誴”5½ ›­{ïûA¢ðüãU È p®†û® O“!,UX!¯0[HÀGÙâS÷ÀÎ ^TæŸ#õ•u†¾Z¿-ˆ.ˇüùB¬ïº.É'+¡©º¶¤uvá·êçžîé¡Ö5Qo·d‹/á3¯–}$ªóM0ËàÓ‚Bt‚ø’êüìÃæ,âêÀ?½~MZÜߘú®xyºy”T¨Skâ;e†Ö®¼2_æTu’z¢4ЃØ:ˆðºÇXwŸô¾±äÃrmrðUÞ_w29$£·"Ó´ÔlÕZƒ%)ŒL:sâÂòÅ µè|ˆbÁ¡`"«…­Ø¸åü:»Ó³)Ï¥1öð"u¨Ùâ&ìÙ©ÆÑ`ªûìF²—Ä1DÙóŸ‹ûêYµv4,|òdVm­¯gUÌÚ0Íûm;y¿™vAl ù[ +-ߥd©1H^“³}ØÙ§Ì,ÚL·. MZ…oL1|=ÔgÅw®̰êHqA©™œ ÓìŽ÷R|î„É÷ÛIªê˜x#ø4 Zhëð †{ ñuF$1§!T´¤Õb,bˆ.—fˆˆà‚£‹þö I`Sg1<éUÁ{²ôrµ–/(eê~·Su¤æý}Á­3;ëwä)ö—jV÷ÃåÕ¾gØF\䜈åÆÏÇîÐ(šmˆôQGy¸üÈîd®N’½:±1ÀH j½¦] ²z‹Mfžj=ðÛ„…GÍÕtrg…„ýwþÒühø,<^'_\KW¥ D™ P–9£®aH–|%%ÞfO-”£½FIjJÙ¤aNW±l0Xûöæ ~ìáÓöŸÜžYX¹¥Ð½ÝeBÖ¢{¥>ºn¡ßnÝÞ3ò¿Ë^-«ú$Z\Êšg‰å'=&ú„¿p¸C rî—Õ£:¯ÏYÐî¥üÏ F‹è°æßÊT+HMuêjÁ’Ó8ýYæÄ‰’ÕX‚ž¯¬ãA4dª”XÇF?ŽÏÇÂø.äÑÎHæãùCÂíW©m©µ\¨’9ù„ñJ¢nO· ‡Æ4:!5+Ö @˜ë=‡¼Ònita¦+Ý–wõX}fɯàÜN¾lß6AïUox ƒøÈgĘ̈Yt=EªÞt·6› ñè¶ŽZ ¿øÀ¯â 7Dš4éŠÏÐÈœ¹¶áx¬Tò¥ú¾”p“p9â9N6Tc­=3¹À¾3öåWžÁ9:¹:ñâ0ò+îÂ-çð:pPQ¼¬ù.á—IñC4÷5ÓÛ,jцœñ.\Òâó€ÿ¢T ɵc*ÑümQ¼mÜëãQ@ Ý’n‘˜ãÀn|¨V}{íþË.¡$±jÑ;½S£c´>Ä)ƒe’WÚiô­uËŽ§Ë×ȃsy ˆ³‡B Ÿçlk³•ŽÂÌÉ[ÃIãî'SÅé#q½Ic [úéDŽ Îo ¯Ó¸ùƒBÞ˜|…¦÷ÛpÛ–‚‹ôYpªVraQv-o;”òߪ¹ákê”_hÞ„EMN³0£Úr¬û‡jB³5ëÃhú’Ï´ûU>nu+eúw6A(ñS˜¦¤ —ñ¡câ2zɶ»(ƒíß0kšÌ¡í“4C†Këlɽ>ëÑ=èt]|‹XÉ$¢/> endobj 30 0 obj << /Ascent 669 /CapHeight 669 /Descent -193 /FontName /LLTTGF+NimbusRomNo9L-ReguItal /ItalicAngle -15.5 /StemV 78 /XHeight 441 /FontBBox [-169 -270 1010 924] /Flags 4 /CharSet (/fi/asterisk/comma/hyphen/period/zero/one/equal/A/B/C/D/F/G/I/L/M/N/O/P/R/S/T/U/W/X/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 31 0 R >> endobj 646 0 obj [500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 0 250 333 250 0 500 500 0 0 0 0 0 0 0 0 0 0 0 675 0 0 0 611 611 667 722 0 611 722 0 333 0 0 556 833 667 722 611 0 611 500 556 722 0 833 611 0 0 0 0 0 0 0 0 500 500 444 500 444 278 500 500 278 278 444 278 722 500 500 500 500 389 389 278 500 444 667 444 444 389 ] endobj 24 0 obj << /Length1 1612 /Length2 19028 /Length3 532 /Length 19939 /Filter /FlateDecode >> stream xÚ¬·S”fݶ%ΰmÛ¶mÛæ¶í Û¶mÛ¶2l;2ãæ¿wUjûÖ}©{Vkkô>æXm‘)ªÐ ™Ú›‰Û\è˜è¹ å­ìŒ]åì²tÊf®„…lÐdd"NfF.VöQ#3nB 3SBQ3BffB&...h2B{O'+ KBJ5e *Úÿ’ücBhìù?5=­,„ä_ÜÌlíìÌ.!þ¯UÌÌ],ÍÍ­lÍEµ¤ä%)%äÕ%ÌfNF¶„Š®Æ¶V&„²V&fg3*Bs{'BÛMì¦Vÿ”æLÿKșЈÐÙÁÌÄꯛ™‡‰™Ã?*ZB3';+gç¿ï„V΄NF—¿=p±'´˜Øºšþ“À_¹¹ý¿rp²ÿka÷W÷LÑÞÙÅÙÄÉÊÁ…ðoTEQñçébiäòOlg«¿jB{ó¿–¦ö&®ÿ”ô/Ý_˜¿Z#+€3¡‹™‡Ë?±ŒÍM­œl<ÿÆþ æàdõ¯4\­ÿ•-¡“™…‘“©­™³ó_˜¿Øÿtç¿ê$üߪ7rp°õü—·ý¿¬þWV.Îf¶æôÐLÌcš¸üma€føgP¤æö„LŒÿ–›º:üO›™Ó¿DùÏÌPýMÂÈÔ`ëIhjfÍ oïò7$!åÿËôÿ}$ÿ7PüßBð ½ÿÿÈýOŽþ·Küÿ÷>ÿ'´¸«­­¼‘Ýßø÷‚!ü»aì e ÿÙ1¶FNÿ/s#;+[ÏÿƒÃj˜ý;Éÿ)£¿ÍXü%„‘žñßB+gq+3SE+KBs#Û¿ú—\ `jædk0ûË迚IHÇÄÈø:UK+À?­gû·Ê `úŸÉÿ%é_©3¨(Š ‹KÑüçNý—•â_î]T=þ&ö?J‘³7ý_‡0„…í=½éþÞ@:fBö¿9™˜|ÿÑþÃô_g9#'+B¿%32ý«ðÿñü×Iï?`Ä&ö¦ÿÌŠŠ‹Àôïxý/Á?jW'§¿¬þëÆÿ-øžÿ5èfff&Ыö&ÌÛÏeýhÄ}¹£tŽð®·«¥þ€Ï[›Sê.ktoƒ8"c¤‹t­†iwp&óÒ]–±4û*ωĥ ¿,kóuõ/ØÔ]Êšæé9Õga*Ò_´†Ÿ£·°5ß‹ÍÈŽ·ÜiËOI’”\*yvùÝD» â&Tx@¾0EkêÀÔ¤?14—©u·É.©¾&÷–t tX⬄䈑úq%ÁFÆ“À£/eO†ë|_ fzìӫνÎÃ\‡Ñ‰¡ç—ŠÌn¨1* Hm…ì4‹GºÈ+[_5Yê~rW¤ÅÖ•8~ŽMnÀÏfGðòÅ¡Çè‡u} @ë6ØèŽ&óß–ˆýFÀm>u&mÞGáA½àE- cy»3±='c›` ”¢b\­ˆ°Ç`Åo댋üI¢ç{WA™OœGOCš.‹Nñ3’:ü¢8ß%“üRâp׿戒ªFlêíˆ/H¦)¸`ªt¯îBwG±¶cB¦5,ùˆ(QrP¢Š(H ¨ßîX‰çêÖ/d7ûöịòFÔº!o’G-›v@Ø×~.†z{ÙðK6Gªjµïä‘14u¤˜ûD˜Zª05¼?`’Zf¦×ñ({w‰gJoè™…iñcËÃÊ&@ï๡“ªÈôSßÛÀ¨† üp”¯ÏŸkï/I2|?¿°¦Š‘ãlºõ[ôõ½M½¿ÌiêºPu?ÌöøÚ5»FÜz¢ÇÚKq>Û¥ošì~þAþ°×¿¯…d<Æð#C2~ búâžÓÚª Ûd¸L%§¢be듎|Gùæ@ûH–Ž[”Íìïw¨‘\qL¾Oª–¥ê?ºiÔVÔÁæï4fÑY1–-ïíþ ßÝß®eJfà,¾s=²´â u9³Ä¡n”ùœ9•ƒQTuQ:ªŒig©Æ…˜âbÃZ‡¶ÇĘ0’«ó~š…f»Ï‹+|€v>BÈÈ1ÙC¥”²ïò%-þÙð <Ž‹á¯F³ÕšÎšã\;à™Æ!?cEÅ !*ŒŠ-:úç'/%/H±™®FÖŽÊÂoŽ [K 1ác-´ò—«‚ιP+#;4mJÚ²³ÐD”xLj&‘ZN½gÑÝ.À½¹„Sè06ãøËVvæèYÛ¦Q•gR:?¨¦e±VxRv‹¹–ú³yq—‰GÁ] #¹$ýÈ»Y–gn§‹³z:P4 •ßíéßxmZaT_/db ¬—š±ä¦ C¸.™*Dyë på"i¯bsbC×*‰ Ve>N9¬{߈;ñ§“¸ö“A±4”¿@K†]¨7M7\ã«ÜSRڵ̢ Kݘ¹ˆdf"8ãrûýè$òW°ÊdÚ§ÁBžBÓò[&oäénwÐ?ñ °.¾?€Ä˜Aó])߯Ý*ß<È;_½—Ø¿¥&J‹9‘“E=Mè3yŹØ6Ŭ<9‚z%£õ×^õzT>™ÞÕïA–6¤!ÍeŠe=Ýdµ§4Xø¾7¼Ò¿*¤6«("”‚×;ë&º]˜Dî¨×”ñÕì’œûbÎ$D©¡þäØ70‘8›¦Ê½¦\cÊìÞ+.ô\y‘D#HÈïÍ *ÒQѶ1zt´ŠÀ%eIµØ@Æ)$°i¤9¸Ê`Ù¨ÃÛMMZsEš¥IóÆDΰÖx °D…¦lØk¥•»ng€ï¬ºe±èí^f_‘ûÙêuç.â’‘ßö˱Páb`Â!Gk·2±·²µ¯þ‡OS’v"VNt$wð€GÔÄŠ&spÇçÕbq»l”¦I#BR·Ê󞫇‰¶Þ瀟sè3ÎJgNh0¨>‹°ÓâÑcª=˜B©ýñfÉ¡Ä %™©Ó#©%Q9¯¡uë#½ûüض8t™¡'40›IeU+M «úÍϪߗ¶ L—†ä=ë]/ÅÔéýSC†¨¶ënð-±ƒ83Áùò”–¿¹‚‹Š?zŸ¼eÆ!Û| ð” ¶†,lÒáÓ7ѽð¨ôQÞU6vý‚Ìq&\h)læQ£»µ &3ñÈöòåÅ×¢[0-/+l_]yiû´×âñpþDÖ"Ãæ>%=ÇWòp¬G¶[¥¥Ö»²;CÄ«61â\¶£É¼œ{†AZÙå›ïž‡]Zæ«Ç$" 5úÌãGÌW Æ ¹MaÆ— ªÙÔŒÞAXû ÂI-Ï8šp4|ÍÿwR47ùëéÎõK%„ë°,¡ 4ð»5«%ßáXmúxâ@ÜÎ]D_Ò C÷ÍÿÛì8¢eD&i`0µ²QJ’û2ÿû5c¯N ¥œ×—•L¢÷NX ´ö 6Oöƒn o­'A’³ë> Z*i‘aжæÙGòQJR…£¢­ãNlß»`ò^ê÷hLŒ4nS«F‰lÖk*YØ¥ÞÆÕÀ¥~i¢ØÊÆ`]X¤K­žøa‰¨Ë¹E@­9‡‡YN¦X(/é&æŽn¾döôíƒJ=T¿ísõÖüÙ×ÿŽëÐÒn”¬Gf¤>Ä"ÄÑÛá@{ÀqW0ôE¸§©«Jú¹ êNœºüƒdêÚžäSNŸC©ºGèf&ÔQ)*%"›§D=¦æ•ñ}ľé'c¡~ø­5ФàCæC&`šEÎs\7¸ù^Ž×ÆÁÊ»›ËI¹Z¢ÕâHÏm^MpÜ&%c/>Q§E ˆÄqPgd%u“ZÀÖÕ²[ãM™ŠÚ£ºœ;fÚœ<ƒÝbZÁ=1õÄù¡ÝûŠË°ªÁ š–‰ø'zEœƒ´„êÉþÚìøjWÆ‚Q¨–nPÁ­ðá8n·ZŸ¢¦£  aüž]™x ~[qcÓ¦¿Žc Æm´Id0ð‘)R >N\0u–¸k$$b£NÊ“Fcª«¼úìKé`¸>íd \ÜæÅʃQ]¸Õò8ÓAí]”vpn1e–âbw§DÎ&ðjܹb #µàêTìÝc^®â ÄzXîƒnìXPÑL¼r Þ;¨Ö¿"úÑLêiEðû·JUߘl‰|¼ha#/¿}êÓ‰‚ f²Eäò+¨…ßêÙqù]ÍÊë‘ðîXÐ]#kê¶Ûâ"mI=‚fE`EñV, ({&ønjûðÅ™l'×­m>ø÷oø!\(‹ÛWç mCež~.p´‡×)á—%³pTÙZR‰ªJ¹$÷²3ëáHKM–ƒY~ “h iñÛÂÍ’,œÞÕ/ËoCcßÂ胥kqðz_Š©tR¦ñØ«ÓôÌ";ç³þ"Ú¾ŸX¬™Œ³¢í¾£W˜lÒ„Âã~«‡%àÓ¹Ìy®!´£*ùˆ r!›À %ˆlÙx¤k@#?UãðB¹>zÜìê:öžýF{}3äðù6!è`´”L—`(â…4# 9ÞÅ1¢á_¤0µƒÐË•åý˜0F²Z[ýìÛ Èa›$¡¬<:ùNh‹N‘ÕPìe9‘6O»ã‰'ëøOlÎLV"‘÷8)ÿf¥aþ–t4ã ’ÕD¾ÉÇêæYc+ôL¶g±S±QX¡Ë ¡*,Y’Ž€y¢¦KÏä»TKjö¤;ʃ;#H{YÚÄôü`ÃÖ‘Bàû¢KÉ7'é ë”Ƈ”ãªo|áãBC»”áÝçà +®²cK‡XTcJºuÛýÔé|F›`µœ°»ú ]º?ÉÕ?÷`cз ÈÀó—-¶§BÐû.1=d¶Ð6±#>§êzçÆØ¡Œ% ¶´Æ¢wfI[ß´#¤n°*>‹'–; ’òÓ"¥ÐCG¹@ÊŠ–’z÷P³hýÅ×ÃÚÇX}•¿Mm}0µ­~b ‹V"¦ƒ%'ç(»ahû!ƒ .‘útâÙqQwkïÛng?zïEy²ãÚ­æZ¸¸3Xe%¾–aJý^{´oÏ™9îšlrF1jt“㸘bAŠŽêré¼½ï’Æ'‰ÁVò¸Ò¼0&°2™ÿzDÙò| ­6ËŽÀn;ú‘^Ì’kíÑI1“k :´¼‡e+N3ªÖ»‚çó„ æ¬>( &†Q­Oy2 æ dÁæK6ÄÂèçØƒ(®³©‡—ˆ:Þ 5ÿöiuoß|+nYH™¾C˜³©E¦å¨ôfœF‘FŠÑGô®Á ÈÓI^é‹ö¼pAqß> S´ãLÇÏÿ=W°^wËiØ#®>w \D½<2OÀƑ͚×uÈqÄFò‡H^Á¾)úƒÁ'…½síë¥qÔ7àø~9KÙÛïûã.ªª>5ÆO‹l°‹ÁòYèÞcnàïÊ䟞”T í*Fß÷ñùê«ØÕ¢Ê78pTüVªè£Îzëa ÿ<[Qv²Ú3z\î™’î$ fxä©kGçþ:+ã-·JàaçWÊ™”ŠƒFZ#áD@Ü_„öí÷#Ê '¼-'±j»¶è]üZã$Ðýê'ÑÛkZW5TÍ?YYÇVåd íÔâöåþ sÉJ©·¡—6ùwöŠ‹‹¶"lÉD‹ŽK qºý$ `ÚOë„Ù-sfðV+NíÀaSÈÝŸÈ«y)÷vÀ†½üñçùCTô€b—ß݇¤|ƒó=<ç~³Ëk‹‰ÔKC!!“Z[!6í1Í:NÆ9I†VjÕ{vSÙÒ¶^èð&ù6yã àv?¢ù‰,*k WÍ-³HtH݇öFB·øø­+,U±Ð;£Uñä&@f^V‚R:@ ºð{ Ì«MèqôW³t…ªçÑy ‹¢ÏX¤wîHâAš•Fª/«´ÌD‰±‡=å›;×|B"ƒT²ñí2ÁãK{©’/4uÚôW@ivšBãt“Ýjq¤÷ÛÏn‹¾õÄC}+Ásɤƒ™ß1_MÎ^ÆÌGüÍåµêíükæ(îM deÚ8ñmŒž¿¬‹–¼_WáN¨˜Z{sÐÙ½ ªðP—ÎæsFÈž¥®A‹¥öÄÕh†ÈÂö )×Ë­+‰£³%Oc`ˆ átW´™ÐÁc+ýX1„D_£âœö·Û§Mk¶Gèîöbˆ6¦ÁÂ{UÞþ,?²³t‚Öx|èžZ•]Âãd=÷ì—ÉM¤¤—š§öÙ):nfh3¶£JÏ\ Ù~‰:©UdÏÊ÷ãŒç7©õGr›ÃÉVñ÷Åö_§Ù:Ní,1^“¯cee½@¼¬AXý)™b&ëö54XÁ‰kL¯ò!­5ÐA é&©8¬ µt>ó¹äD#¥Z>%ŽGöW9p›‹1ªƒålóòcô?Ñs™Ç#ÍפŸM`ÈD—çYƒ†ãßìØÞp‡eX Á€`í¾AUINÉ–ñhô÷‡î¸ ¹Ñ1Pˆ¬ßد9¿c³ î#k°°á@Ù³f´¹ß¢4X"׺[?ßœµ×ÅRH7¸/û à¸/®÷vNMºrqÕQxë$“`’7…/èí CÑ‘$Q•اSà~3‹›âE2Qxœ¹´Cg—Ø~º°I$BA²Dð@|1Hã¾Ax|’`›Ì¿0GGZê#(=˜F/ ½ÚXDž[b3¡ÿŒqP-ÁJD¾Dà΄ ïfw¸aðR ,8ŠÒt‰¥ò–[Ùò¯|-tѺGsÁyú˜+hJ9FŽ`ãù˜Qj}÷š›Ú e”Ò/F1Ž'Ñ /†êû™ ­e_wFßü¡]¡zjV z<9)3Ë©h ûã=xÄt#€ÎÝèÔ†ÆÊ;¨«b6os^”¬ùíþ´µ1”àı¦µiẟM_'{n^ ¤qAÐ}Hš,®ÁÔÄ?2‰D\Î|‡ tSd%¨Õ CÙ}Áh67o“3ËI"áýʤ&ìf^Néeö‹©Íë:`ÑËH–v‹@tòvµ•êÃUpÈhç4ÐQœ”½È¦ç1è$4-[̲!@È]°ÀQ1…ž¿Š@“1xM¼pjW|“Ë"y«…ò'5½QÂÒ=‹ˆë#æšìN÷Dj¶WÿîÉ8ø]Y+Œþ˜_ÔD 7›G#¯!IAê£ K‘}mAÊaÚWSëùCˆF×6†gä屮-q%:Úçµ ,¡†hœ»—“Þå3ýí: p³sÐzî”2h?;511ì@÷ýó‰ÇÚñ—~îŒk«°HàÜÔ)ñà.Ò1|â§HuõêQ¿ ,“ªÛ?Ϥ¥b?õȨüéDv~ÿVcä*"tS¢¦N'º'á<ŒèQBûV£^z#  ŽŒðÞpýâŒ"ã²µHå=”©ü¡8baxhÑb~œt ns#|Os•€áÃà<Ç:ä°zCH+ÕL U·ðæ@-åH¾¤Û“ZÉ·gÝ%a36L½ _ñN® Q–H2nÈaÙ…DH%k°è£Ar×¢j ýÈÍŒœ y*ø§"¬O½^T3˜æ×[pe Fù{x{æ0×`@"%·P•ÈQ¥¿Eñ6uÊ\–˜ÒÚƒâ²mìk[c«%A¦^‹ 9M.E¶‘a— Çôépè8Ú 6 E®Þòu/5…|pógNü8RM<Þ¾`ñélß šß©Gï*YÂw äåsÈñX«Vd¶_<ª“Å[OúeŸf±%â­\¦¹Jâ§<\X†NºØðšÓÜÚœs)Äó(“д×ÑVßÕâ©%=´ââøCÁã8ÓtMG°4GÌòr9 LÙ-Š÷†&…À ?;T}ÃTÝÜÿ³y©Ü¯§+–`Á’ÿ à{SvKÆMÑ£ßÄ$Ä÷Æ¥}\äcCIèÜ}}:~µÕUØŸlQ7Û%ùTüK·Þj°­zÐì="EÛ³3¥éi}t.]Jȉ8‘ê|§¼öÂôìþ.-Ù=Ùf¸!ÕÚ#¯ðÑוhKÅ6¶ÈÆ7Þ$½¼™q¦Â2®¤ô\DÝúîi๓V[YÏhIÛ’5ÞGR|n4 ãúÕGó8߬J†}ÈkDv®µØ1éxù·>oÌ ?çp¤ÞáÍÜç N×…#˜}ä9Ê©ùÔü_B¦x3`ÛnG=J]1¯°§*#áV»ÆƒäN«(Jý,…ã~[œ(þ¸bŒWŸ;*.l³ ®Š |ÁØÏT8r_ÏÒtûììx}.à'»:2_y«m•±Ù“ûèoä {am>¹E&©+/ét5ÑiÍZþ\ùÈ-0¦e´]‹Xå Õ‘N®¾O?d†êүí7Ÿ— Òi Æ,Š)䟨ànn „È?îÅÈ僅×Ù4“W¸ìßbG#DÝ ­œ`ÇŠØ£ä*;lb¼¸žècçÜi[\ˆÀ*_Ýw°:7÷Ü›©«Íä˜éݳ…M²ÁsPÚq¹ÀöÜò«$À¬™9âÙòÇ‘/%9ºûPÓûb¼‰ÓO)ß#c÷ê\[Ø¢œKýL~8ø7ð~o«k]ÿt¸êlCZÏ‹1Ó4¦³pöF‚¬Qâj /ë&sÈ+›¦6Öþ‘Ú6t—~ÝŽ•¥nY› p?ì°5íîZ&Ð곕©‹L'a6Y¾±¤†Ê›Å’Ù/íÁJ ЕÚ*žÉl0kà:µ‰ÿ1-£×ÖÁˈî„î å<*2RÝ(¨§má\\¸”Å;¿f2@?˜šÅËÝnf?]²†vº9–šäMc'½EFЖ…É¨"ñ´†™ïÓ™¬g£÷"×t´Óà £¡&Ô¦X×óVõñÊõßó² ßsÈû m2JŸ?O‹rn¼ÄNÁµ›» ×LeJ´l¼N R®´ ŠÉ{F:ÛÅ&‡ÌáäÙꣀ°y$vŽYœÃŠÞý£n{ ¹ù¬uî„äî¦%Ÿ­hÍL²<»œ²Jœu…1ìà(d É;YÛi¢GäL&·ksx7›éxEŸùT³®V µ$gàOµ8 gàww£‚Œ!ÔöhʪîN&U=Øi­Å9‚ñÛ] õZôʪØ` 65w'×>Zæ3…ûÚ³`óÉlj3_NÅhx=/¨U¾mO§¶sñ'k8œò†—ùÞ˜†àLi3è@ª,Â%¨ÜÒñxs‘×TžækkÑ¢…•Ü[ge'šú€ñå„À¤øMȪ§ð $\uæe4ÔRH5雥_ѯ‘LZ<›ö_ÆûLÕK…eÉP«¨ PB€HlëÞKÎ\º;;‘$£6” …Šˆ:ì\{®kõ³>“ ‚²øÚCäÊës¸û^Ã4¼y6„?~¶Õ¬s¡àÝ=dTµ×ÜÊ}÷ æ{ÿ¦sÊlƒœÖfC“à<½ƒ¤-vÕFàĦØ·¨=¯Z% Ó%¢ÞTt®2‘`½miæ6’r-kºb=ïêÅèæ€ Uç0vˆåÌëß Þ¥Ý rAÄ(ɡƣžt+šðÁϹËAßø¸–tÊ2Í Öà,÷ÈudEqT­&OYHòáê­ ø«^ø*Î_ÄL}¨¤œÐ#Ž,x sÙ|jsþ–јþša,ü.©N°lh±È²P¥P;lJ ÿÚhXëdâvÑ4%`îŽ#S¯ÁÁ0Ä/³Ó?i ¬½§ý\ ïý³¼¤‡É˜d•>Z¥ô ;Ê0Šoˆp䣴îî•lÇÃB8o{½þ‰ao„’Ö¨ 2 EGî´I«7ØyŽ}­©6˜~@ŸÑàeü|Ë?X± '×BGÆËlo)­ÿøÍèñ„Kñú·íá¼i¼£( úå¬_ª6Í;pµ€:ß®¬ºdw1ù›¨no–› Dz.edùÈZ1þ/çü÷ãç/G)èmcÞéÖVZ¬¥RA,!ýÙ}ô0¢^Iõ[.Ñþ­Ì[_þ$nP¡$™ßò¿ðäÈÉNÄåóÞ§ÉN“.½Ã—>~|g2¾Ú™ÇB h¾¸"y®Â7xg˳=j—\s$‚Â1ù£#T–†.Ø^lšG´šö–jz @!ðÕ­mJ‹áÅ3ŒšX†¢7Ži#ÈÇçµ0@ÈÝ‘eÉÜê”±F¨T 5éöNžÇ߯áÓŒŒ U2ÇxÈ’›¥c´´ÛúÝÎùâ å}ôR{ÛzUòJÕ¬søƒ„!ÑqˆÂiBSHÈ1ñ„¾óŒòcǽoðj_®NÝM~GÇѽçg髟2À4^tn9•e9æÂt×Q^K$j#`¿á{ÿ 5ñÚ\Ÿá‘¹Kµ§Ï•ÉV›k„“‰aUêlØ8Cnü^æNýl×MB~?äÐd¼ ò—ò¾¾”E®­×8ð9Ýqés¶B+?½7ú·JW7€/ JD®¥”1YPe³J½á‡6,'3ñå° ‡¥êÏ! °‚¶PÚš/èûż¸‰c­àæVhΊô™‰+ÁEè<@ô¦à7rªP‹ÜÁÄ:/ »´ÞóH5¦ª¾–lՙΠ¼¡ZÔ°¬iù¼èXð=Um‰“0o ÛÝ<{^ص@Ï©7À—65iÜ…X•_ý¤ºL…gÇF£<ÞC¨ÞÉ,å„;m(ѰèHc'$®¨¯}UìSØÉ°¥œ,U¤ÚÏ)DîžÝþ ô–¥ZXWŧ ®êVšÐõ@ÉÊ}€r¶wl8NÁ % K³®ZÅ-‘f1/Oö¤›°—(R¬/þ$/§Ñ'Ô]ÔXjã2üó¯*G8»þ¨ÕájQ³Ó²‘7Ø5«ÀŸi:IoƒÙìÊwIlg#'–ˆç\ºì‹xIÛŽwÏ—çÇXi©ë„)(ìíxoî ö˜ìÝp7ó2á9EçÊ×dÊ&(ƒô¼{í†5Ò Z–f]ð¢d’öržÎ$­4OMÊ‚µ­½LI½ 7“Ôq”·ãûèw_áã\the•¼FÕ!âø´Ì„d–•ס¸Ã`‡äX~“ 3ž ½^š%o‘%/̨Ψ1vL¸åYç†\ÕÉ$páUp~Ñ‘Ž¾ØÆ“¨ûJ=îÁ4­[¯6„Ø`‹Ä¡„ŠÓº£Å‘ù}«³ìb‰Œ A÷ 'öÒçÇp†ëa“SP9ï†ÃôÄ(À>êþÌ ï°B.,ÅóK®£×ÅóÈg{—Mn0«ˆ `â«! 8±¨uš9¯y™ÇÉ, 5À±Õ{t‘+¥6v×7OFžãS*¥ ã¡)X¶ÓU\PKp$设t÷—‰(ºŸzA[Ù0¾'ûSo$—÷\CÌæ'(&ýÚReÎþèÉ8 锊è z×”’œÙdæà-Ú@%&™kÞðUÝXÿ† J–áM‚–y¨GKCH¹=!èÔÓ–g/fvL½o¨sV˜J G{«:¾nµ‹ /L2õ¯|UέdÚØW®[©Ö­=È °í"FÆûpLMŽ|4.}‚ æ=Pʱ UäNˆuj¶7$8µßË€gr±H8M‰Ÿò‡m kH<¤*NYGß ¼ÆMcź=9ø¤{æðâã¼’èöÓW(ÓòÆ¥•å(>Â’¡o|níRýeÞ×ê (‚¬3¿±¾W¹"wý˜‰á»®©n@àj¶×£>LŠ™ÑÏÖºi4z¤þDë­%‘*¾‰ˆ˜BèvîËë°Ûl“œt1tÕüEE IÛûß1n·È\pzëq<ýpâJ šÃÜÄÃ(¥6ü( ¬.Ç<ÏL(Öú{ ‰©Ú“éû&èýK«gqûÙý?™ýæ)ÚñÄMð—,¬d¹ f( /M‘ñ²—ËŽs¬ÙÐÕÞ­¿? Ê™ 3ð™èM`é—µDNé¨V×e ðOh%öç•ô/ÉÑCáÎÐÙß°;ìꊵ•úxÊëo±Ë9ì'w¶þòoƒ%…Âg²¿åF ÷.`©=¸¬²?â.MÙ*ç)Ý‚xËŽßxLü±¾Û”ð~‘ä1 E^7ÅFØ?O¡¨Ÿ­XÔÚ§N9½ æfÔY×HeŽÂF1ƒ?¨õ3ÑÐN›|1¢—O\)¬]ˆšŸQSq/Ñ4 #³ö½ó§í0ïíøyWà‚‹¾æü©0{zqI~ÜÙðõüú$¼v|i™¡h ƒŠJLúåŒÿÙj`ßirÚ}/÷ÇFéÍ¡—C!…ªä–7o–Ð"#·äÆ3c°Â ë4µË "‘Æíx d'˜„„åJƒ‡C÷U_Ê1šì…2‹Ö*˜ámž¡BzÓq›Áʧ4›8Ót>Ò¼¦±Er‘#€ÖdøcÆAtü×a£?Ë™vmƒ1«ý7=¹¶¡o"q¹AUwä ¥X•Ä+Ë„ë§ Ì¨ÙzZ²ÿúžç‚ùƒú0v×Ü3O8Ú… 1æÇŒþ Te—IÓvVÐ~vÝèÈ»×´érMTlÍijqâ8S"àçFÞƒknÏ÷2[‰!Q‹÷_ùœª:´¹Ö˜“sZü‰|¦G;¬U/¿3½×y÷3J¦µ ¦5ÈÝ,Ë Ai­Õ'¹<Áo›â¢Sݼ~}]“ü”!x`Dšö(3”îŽ5lòB9^þ“ùóì–¦%ä°S©Œ˜•×tGÚÿXÆW­Nš²œ‚ÁbÓµ›)(Ü@§ñ^F®£'³;¶4¼›h]YW¢UÔ}ž¯Õ¨DŸó~½y‹íOÇÍ’r–“kmôÊ-‰GPšýÀžâ„Bs¼æ-µ±t-°¢54F'Mý¾ýR†5K·g¾ËÞq'¹Z¡•³ŠÃm‘Þxîàk!³×0s«5B¹´ˆKÁÆÏÒº«¸àg§~×}s¡7)û*ÍÖ%ýûÓɃ/QõãòGŽ)óÐCðu/[ý»h,CöäI…q£yÑáÖCÎPŒ› x=Ôz¿+; (Óò*¯ÖÑÕ,pÈŽ;ì(‹f†š§÷j7" L+•gExË2 EùÜá:£‡-X5Ûó@2ºâÀ ÷žúçSÁ6øÔy‰ŸÒ<)Èj÷Ésð  “Ædk“%°?ø@”?Œ‹ƒ÷vÐ|_,함Æ'LE¬ÎEåËëD¦…kÌÃí™c-ÚñºÐçòrÎM¸m ’p¦rë~Éwà\ Äy!}†o¹jbÀ… ±waÿiþÕpBЛ±wLÚ—ŒÏý‘{½÷õ¬}ïÓ»GfÞðcÎTƒÐ*»;Ï´Ô{ëé¨x/~GnÓTÃX説ëùVóié8T³þ|Ú†3šX÷fqUØn3 T„úš(½‘=(Àœ«zCÆOUéJ ¢6‘†g)v;èÏN(T19+[•Êýîʺ" Vˆ¾J°ùÛrG&w‚&ÞéH •R áøÂeqº‰ƒUïC–Ty?ÚŒÙÒèpo5 90êV[32šÕΘômg–x; r ¨‘*éH79Ô“Fh3;НùCR÷£NŠå@iâî‘uþþG4]½¬mÇMwù›ÐÀY0ò òŸÅéçÀ´ÌHßD·Ax„ºe ÷îr¾ŠÐ)wç裂ñ´ž’#Û‰pá¬ze›<¶æ‘áç‰è¹Z´âÏœ~‹¼ˆJÙïöUÖ6ŒõØ3ØKˆ–dx'VõžÙߌœ,,ÍU›¿§~aS’±PÐ 5+ÎåÐâù:²éN^€¼,X‡—_½vGþBÙi˜Ð8!.Xå¦!Cü‰'i–Jž•X0ßÄTLý}ò?Ú3B“×&þƒ#²"w0(ë;:ä£ÓK” 9ÄËß‹öbí38‹)ã å)KÀe4_¦³oÙ)¸ª:ÏQÀ5?i[´üYÁ5zÂS$ß³O \tM5gòi~çRjClàÜèó&Ooš¥ƒ_ÔãCb‘yEG>PÃ\>•M¼À/„'º–_VN·×r@p!µ}‰æ.dõþÆÂ>4 :ÜÙÂ7ÔD¾Ç‰.:¿”.Ïít<@Ÿçi?×s×F&Õ’LÅnljø-n¤‡ âЮ{CÒ²È9&4ÎÏédnyF‘£,-;ôD¸È0&b—,! NlF²¦Ë‚:©¦kãý¢²ëÑÎâ-IºÀ»ß’ÇAwTr¨R$1pÉ}™¾w€È^Êdá]&r{þa"ŒÛ!?äéÄÎÖ&Kžél‘Àp#ÕVÊ›WH,cW1Âtp¿pG-GìíÄÉÓôãlÇCæpìÞÄþ(F(/Èy,¸"¿‰Ö;eE­˜²¿¤­nXmÿçü˜ÎßÌý1fYOdMŸõ¶éÍ=W³¹|ÇœúE4˰§¹.Å ù8¸³ûªJvn $ht"A‰Î¹i• £k©$´\Åp«ô”$HH)YºØDfWãFÎOa?Ðm9î"YtŠúŒÉ’j|0âѸ’GÏK—>þ8M›a{˜aÐ?k×ÐÈ%šLcú‡hì±V‰ 6+— Š~u™°êInIÔ“þé9ÅA‹³ñ)P߬O”ÉZh£Su¬¥"Ͷ.P ë­ý.ñELÞ^Ã9ꥨu“JqŒ„B;à“ü,Ñ—¤ã3YÏ¥Í)<ÔÁŒ_–GȽU Ox’_PZÝ‹PYTi¿¸q³n=Ìo/QI·/‚Ø}Û&£ôSѬˆ:³#{ñ´¸ªÈŽ’îG½Žd± œH=ž|0”)þpâqÊqQlIQ*¼dì½ôgEkÊ [y’.•FÅšp‰)!ûn‚èE|ZB&±*SÑnÛ¯Iñ˜æ¦©9¾ãß 6Ê……ýa‘â 8?z·Gâ¶ØgÔä/i7ÞMMX˜Ÿ¢ÜÞA±­Û3ˆ(=¶Lªƒ¾@EG§íŸç&°#ám9 fe›|s)Ç~qÝì"Ȱµa)l<]<Ñ•%; C$ÑéµÚ¶‹­cˆl`—ý:N†ûmuÈóšœú[kñ´ô)?—5T-nlqh•G'A3™íÖ¹ü»§¢+ ÃÍIñk±èKéAãuƒà-Îëº eX„ƒCžÑsv³rÕ7(kæ÷<:^&Ç&hßs¬fë—tºÇÝ~ÿÍ=¦¼:–j)snù*_è´µ(žv}pVæãQ/.ÿ!x«7Ùšzž1AKt„3ög=“ sþH_×¹άƒioÐp{lÅâkìÏ‘'1ð3Àté‰á]¯|lÅÜû^¦9 9ƒµÍmL°‹§Òžahë>«u ¬{ã‘%8"3±žœ»V7Ä›(ˆ9ù{Û!³Q¼CSJþ€ßC›˜ømwú™Í'®4ÈÐÁìŒðŸÜ·ÅÁéÇ÷ÝìÏ{˜åGè[¾3ÄhM(Âß;"&À¦ll#Û’¹Ü£CaÄfw>R $¼†aþ. ×;@Ì«sX5DË—Ì9~bXQ›Bª“¹mÃI¢PÁùAl#õMHÝ”ºfÓH“±›ËôŠœ=´ÇÖ÷" kcíu/C¯°¾vtriu{™· ñ•ÞÄŒ“û‚ÌÇûÛEc$èˆÌo|©Q©(3õߊ־Ù*‡’µÐL&¥|?™OÕzøÎ)HúŽaIì ¾Gö¡ßk{ ðÄÂL–/f};H¯e“[-jë¦užW—\ryçWTȶ•ÝÔyŸMƒ0t_FžÁ©±Ý‡¼Ñ}Lsاք(ÊÔÑ”¨ÿ¹éBÚq²†,lÞsm­‰…o²v9½ïü¥§èpl $»`xâvÔí®µ¹83c;ÿ³í*Æ­è»&T|&îÒ\×€Ùw9&ÜPF¿³k„Ï®)1ø‡¦|zçÏ€Nƒ^M“…JFµ ¶³¦Y"Ʋ‘Ó7n8ewyÁÌoÞ.Ä‹´1üÅzÝý§ô:¦ âÈê¶ëqqÈvÖç!t.‹{"Æni7ab:´r­ŸÂ =±ÏÕÚ‹f)QO”Q)cÄ=~,]5¤5 ý¡m*rJJ=øV2Ð…Êñƒ9ÙÐÍÂ-ŽÂ}EJìKÏ·¦_.´æÕù¤ˆßšAJìxÎì¦#ŸBH10K²oŽ‹M­nTkþ_çýa܇8›PER²àê#y÷v¡Ü®‘ì‚Pªõ¡_²Ž«,y´zð<ΑÚbÑJcRg¼e^FälN"­ SPü97A'uòÉßpzµ¦ç/×ÍJCq‘΂4¾¡¼KІ«©û‹PÐxÒ*?L߯™»”ć|W÷`hÂäöºzæ/1‡´ðê"$ÛØ§‰Òdw ¹»)û¨îoå†0˜dz-ZˆûF š¼¢Å »7›¢ØbTŸ|xí¬=6E¹þ“Њ-npÈÇ@S¸8¯9H‹I=¼ßØÁÍ‹ÞÆÛ„)…ã³p!3¼LíøçÆ}ÂQv„¿•ü©˜-r›OwÄFN¾Ð¤ûù ézx8ÐFd¿üŒÍ’²æ ›|‚É×0#øñPQÆ)¨;¤HV‚àF©T˜bQÇ$¸'ºï±ËÁë­²µÆô—•±ËÓ¬f‘2 åÖYñŒÓ£†+ƒyè8ˆ×Æü¥×2ùp€FA 3å®N¦։õ«T©8+ô44ñ¡ºyñçÄ”V&ćwJ /¼†Jº™õ~€¹ò+n˜Il¿}éÎ>G\Îqj—¿uO¥K·,…$eAišò «?¤F&˜N.Ä1݃Îõ>Ý&éMuÚÜ÷#þ*fÆÊ¼:ét¹z}2iP;òA|5ˆO‰Ì 5šÝz—?³Q"/A-åo\€µPA®4¡xž™sï"`DRš¿=Qè8x)±jâ wt¿g“IYè I’ h9åpOtl+`ŠVFwz`‰Ö Ô"»j º$²nœøƒ]G‘'LcÕ¥w^K ¦“º°hŸ`]ÛK‚SG _ìñèá‹´(»Ê'9æì2üüÿ´3×ÿp8€îÄtÇMoÇ©ǘΛî˜cjjbb“ÓÝy†©1 ÓybN36íô±›æ«ãý#ÞßÞÏûüOAß®áœ7kÅ):]%­D<˜‚­/gB ‹K ãDf8¬§2Gã×ªÛ ™.Á¸m½‡ªÃæÎ¨Ã«Pº¹ŒV‡hOÙIq ~²X¸ß Œ}þމå"û>Áyg‹¨}í „èþǪnûë<˜†²bnåHgÕ|û~€Ù»úë!IyÃ¥{ êí9ŽrßM¤—QgÓ±Ù‹ô‹'ñc·€Ðâ˜9ª)À–ƒ^G¼[[ÃibA5¨Äv~¦sO5ç½À Ë]<2KŒïŽ}îK â³e–-g’ýUI¿`=+R_̹†Ž»\1ñ`å,[¡ÉºTZÑôOöuÙõ^;Z²eX_i¨¾¬£q¦-sÿ´àA75™äa,×$li²f¯ÂšmÈ=µ´ÛªA^ÕÃ; }Ñç»+5ù"áC€;蟕Èt«üAWü-D&²°¥e×™]¼©êOIg¨;Q»=.&.A‹X õ£‘dð¨©äˆÛXBù±®*©U•£jìp4 Óñ®I!ñR¤x”N7O0ɪú‰Uf6È~ÂRØ¡š³Ã/cµÇrh˪4#¾xÈöxYdbòÊÅ3½¯V€Ú>ZÙê~÷豿C0ßzã²kÌa1¡Æ€ÿ ׊äáéU‘dʼ¼’°5°:9~‚àkù«Y Kmª|²3çL”ÔÞIùzïòhØzùú¡‡T\O­øóy÷+v°qYÖ Ëñ 2õ%Ò8Œk£è¨;A\ŽgO‹Îknbg•¬ß0ð1ÛXnWÑœê¼s¦ç%“®|sÚæ!¥WƒÒ³^«™Ô.XAŦ>¯ŽVž%ýØ aåmfˆ!eâ›±nêÞž¯ªÿ —\¼uùÎãzçtŒŠ޶3C<Í"=¤<#Bò o«„eV݈“$×(Ä=h;E‚æL:$Úô W²šË€/Ó7/83¯Ý•nÑËnE©Üv6ÂöÿVœtqÌS>Š˜ÊhºmßÇæ‘µÂ“·'>€¬Ø¥&5©ÓëefÑ‹BèCº³šƒ±ž‹’٘%‹yiòFÁñ‰rKé&ðg¦¥ÎE©FMqù:¾àwó æñ–æAW¢µ`3'Ï{DaØ÷®ÃG#^u¼Û…vCÒ×=†—Í3&÷JQš_~P¨)ÿNRÌ]ˆ ‘ {Ÿk; þp2ÝÐ,ŒANyþyuwÛ’—ÄN!îsÌõEÔñÕÓCÂS^ÕVaÃÇ¡2ýr´X§”TÈ4o`Ð3Êfe7b Ròk»^l’˜EDéá¤Ajc¦Û`þžò«0¡‰bæ>–ßÍÊ:$‰ŸÊŽ‹}\³_Ý&Gi™5Qs%\øï×þì„ac ˜¸ìËGÛY wÝ’¹ l¾_6}>­¶2¼ü¹t¨I´7œ­8³!„oa`¥;ñí ¬[=‚q#p=×#ëÎì?b‡k–h¨¹ì:f²Í}Uõù'¡íù§V¤ Mt¬=_>BóR? škÖXïö üªË1á0þv"ÈÈ é©qw ©”Ø'`´Z+5šÿmA--” ~”'ûɨV£×Ïíë¿,ÞéòPÿ‚‚ÆDéÂèÅJ³¹ÌSßߤЙuê¿oo#”7û¦^„‘_ˆuM 4ÁÕM1µg‰ròÀ)ûÁYGÔðžQ4R:ÅŸÓìzY³ƒpš:œðº«T•‰‚Í«Ä ÿN]†¢rå0Ô8]7ɳëGô÷ñ7œ"%vZß.Më4ñ2¿ßEãu›ÔÙZñi$#I°|Õë΂bþr2DBé¢ïeAÕÞCð…cÇÙíØPÿåAÓsŸòa´NJך/š"òïí1-F×G—¸ŠOµ¤PVÕö›É}Ž}çx)zÅÁo#lÆÂ(3¢œÕГÎÕzdh¼¶Füßfé÷M¢HÛ(¸‹Î4?+ú²R²¤ÞÙY6~º¢y|<]© 3z‰î߈Iõéû ¯áS¬¨ÀÓ³èÿM1¥›Hþgø/¾0ûßsh‡[ó¡Χ«†Äìù”;×ì¸}šàÄZi”vvKK…cÉIžrÌ6ðùgý¯’Õa¶‹ay˜êjÊ’³ˆ×a@{³üz[HFsA°`0¿gÌY™Í×Mi!Ë ÚYlãû‚Ÿ¤ö»Z¬¢cZê*{–PU|¬…ïÿi O$nSGiå¸ÁÑQðô+Œ¹ÝÔPa©aÀ,~q‰è)Ý[ƒ$È^þû^me;XPZ¡¦ÌR–x&¦ñµ:Pf,W3¢ÏáN²~òEÚä0ZôåkçÆ7y4qMÕûé ñwz­•Äò¦)#^è!ûUwØ›n>tCùß|ÆßiÒ)Š+04e -ÞûåÂYçó÷9v}ö_‚piyÚêÌR‚™±Åàk! á4MóÎW-´®¾ë– "Á2C=d6{ \9Ä¿Ø:†òœͺ9•‡Óë¥xvƒ*6ÜRѾ3;ìdùdYF‹„­ßRYÙ\2îcŽœ'2X; ¨“Þj+Àf §ËT«ùy÷Àý´‘âÙš8Eìð³.HÐ#vŽG€ÎÑý,µŠCJý]j/LàÑã€k¥2¼Fš"1ï_—lºÜ†’¨UÂw|“–À Ü€dŸÌ'³ê’^U¦ðdf$!Ï`|÷õ{i˜”+eSWL´L “-ñƒ­^î6ŸÆù)‘lB„¶'ÉÌØ?ÎâK :©å¤žÖU«xé•ïn""ò49 „êGˈµ›ÚKæS‹QŒçñµUêkô/Ûm÷QâÜÅ¥¤I³p’ðì·ÝÚîu'ÖúáÉú 7Ó´|þß°B–vÙ’-¼ÔÞyÝï¦àÈýˆiSL¦ZFËæ7 4ÃEZ¹±Ba¿@Ø~ÜìËèë#ò¿DúÿÁÿ‰Àî­ƒ—‡›—+éÿÎ!”endstream endobj 25 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 33 /LastChar 125 /Widths 647 0 R /BaseFont /SPFBFI+NimbusMonL-Regu /FontDescriptor 23 0 R >> endobj 23 0 obj << /Ascent 625 /CapHeight 557 /Descent -147 /FontName /SPFBFI+NimbusMonL-Regu /ItalicAngle 0 /StemV 41 /XHeight 426 /FontBBox [-12 -237 650 811] /Flags 4 /CharSet (/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/braceright) /FontFile 24 0 R >> endobj 647 0 obj [600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 ] endobj 21 0 obj << /Length1 826 /Length2 1115 /Length3 532 /Length 1713 /Filter /FlateDecode >> stream xÚíUkXW‹"´-”(Ý#’D’L0¦`Õr‘p‰b‘K& „˜$lkE.VQT@Qî”›ÈíÙT) (XZ(˜-b*¨H¹)>lÐv—þÜýµÏÎü™ï}ßówÞï<Ïa¬wX؉ԑÀ%²v®oˆ &›Æ`Ø‘(,ÁÜ– Ö²²‚€4@\ÀæYsØÖ\ìˆð( –S;³Ø„¡$†À8p…%ÁhÕE@@ *‰b‘x.¬OTŒ’‘¨Iƒ Ä @ƒ0œÆZp䌀· ¥áo©H”S¦€)eÒ P….ŠB4ÆâÔ^(åä¿ajysG©HćÃÚ/¦ôÃDQoDX¸T‚’À•¢$¾\º]2çŠ 1iØrÖY‹0Ä¡ÀÚÌd[r—LìˆÉP¡;&A‚A ,£‹8Š —[¡â[4²ßë`¿ÏËüÍ\IwÃ%{¢ÂQÀþ]½XC¿×TJ$&>l&› QBê}ûå·l3!„8Ü-&I8ŠF ªâ‚h`¸•TF9f1qBB-T4± i c…, ÁHD„" S“,°K›X$Œ "4ð_aË7ðÒ„éÿcÀH¨X‹ƒá?†bkKÈ¢-8VÀÂj e‚¶ûoBDJ’(.Y²ÝŸm¦¯[ãýž'6éó”%jTtéQFºþ4ÑŸucòìûìvv§‹SLÛ5&áéŸi~‘ …¹Ç°MóÝGùPøú]·Ô&Ù˜á£dÆ‹VA‘l*%Î ºçf¸ýΑѴ‹S1nê´&CÛ¶·[’n °2œ®îþ¨}Ð2xN¿ÝœZ'ˆÝg¹²f¸Qﻟ÷^®‚’ÿùHM¿0n¶ÍiÈ4´;Q,ß6³—žËt©?ãý¼@Þ¢Ñ-ÿÒÞqWi—ñò‚:¿su ÇUZ7}º18}”Ezº¹³û¶SÁ`BØ M½Ü¿Zšì8¿:­y¨ïX[8»|è êÈ~Zã‘7V!cX_ßž Ìž¿“œ"úì“ÂoF}v›ªj4Ö–oÒ®é8ûôäÀdåvû†úZ¬%Äx–ËÓ:Ïm€yBëÈ™¾«þÕ7[Úîë'Ï\öQ4g]±ŸQòOû6lOA/•…'eï ®=ðÂJ“UÑÞ…Çâ!@-{çÍìaÎT‰‚±NåY°zw[þ ¢¶mbÜd‡wIýÙÐrÿ„þ.GOh±'é@FÕ‰±ãŸ%%•Ï]è}iq¥¥©Óÿ»Ä‡aÖ+»‘ãÇ~OÍ™óL» ó×Cf1¶›6 ʽbtY禦ª–^n<Á,[ûñ§*ç“ï>ûªÔ†æÒòÔÉfGË}ûu=»º,åFÊW¾™'Çó®J¹íìÞcZ…‘;S¯Û4Ÿœù{dVé;*e+³lÇ«²ª;¿8¼ÑOn\|½Çg×{¸Fˆ©¯jÑ]¹ê•<3w*Fk ëhÈzÈ?$ðrÊ&’z÷{ñÖˆÐ]û¢ËWó”w"âú5à!q,m½á>sºqx¬èÂEü5¥UÐvÕ–j ·þ4i¿QÎÁÆ™³Å‡Éçý^ ž…­n#Å?vÄ9ŠêýÐç£aä¨}¼±z çhÏD9ÆñÊÏܲfOËM«™‘WCƒ¡9y%­ÑS¯7MfÜa% £ç̦ßOlöØúuÒ;›‘Ô£–?d î}Ye;­3«ü)üÒãxFA»¼2z‰²í+ö´¼r¼µ¦ºŠŸ£ã//Ãt9ƒ·âcåÌܽ»_7$)mÙ_«*ÊOþ››‰ñZ7ÃksS«ƒýw®›¬»ŸÏ8`×®'ÕØžü4¿Ò$ßµPinP1Qi<-¾\SÍH˜½W‰Þ½5×|êù/ëæ’/­Ò­SØ”A_lpÐŒ·J+J§k½ßc»#Ý®÷ªß­ô—>]ƒz0¹£Bë]‘h³jÇŸßÓ|ÒÃû¾x—>'õ›Q§ÒqýË£+š´½W^L~ÆþÚÿüO4 ®C˜”a0Jûr:¦lendstream endobj 22 0 obj << /Type /Font /Subtype /Type1 /Encoding 648 0 R /FirstChar 13 /LastChar 110 /Widths 649 0 R /BaseFont /DUEDWV+CMSY10 /FontDescriptor 20 0 R >> endobj 20 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /DUEDWV+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/circlecopyrt/braceleft/braceright/backslash) /FontFile 21 0 R >> endobj 649 0 obj [1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 500 0 0 0 0 0 0 500 ] endobj 648 0 obj << /Type /Encoding /Differences [ 0 /.notdef 13/circlecopyrt 14/.notdef 102/braceleft/braceright 104/.notdef 110/backslash 111/.notdef] >> endobj 18 0 obj << /Length1 1626 /Length2 13810 /Length3 532 /Length 14687 /Filter /FlateDecode >> stream xÚívePeÝ’%îNávqwwwww.ÎÅÝ©ÂÝÝ www ww(ª° ˜ú¾×ݯãMÏŸéþ51'âDœ¹såÊ\¹÷½”¤*ꌢŽf@)G#+ @ÉÆÁÌÝUÍÑAÉ‘WQhaøcçD ¤wšºÙ8‚$LÝ€|m @h`c°òòò"Pļ]l¬¬Ý4šjÚ´ôô ÿ´üµ`æýïž?‘®6V ÕŸ ½£“äöâÿ:P¸Y–6ö@€¸²Š®¬’4€FZI ]Lí*îfö6æs ÈH °ttØÿc0wYØüUš+Ó,QW€)ÀÕ hnó' èetúËÅpº8ظºþùظ¬\LAnzàæ°™Û»[üEàÝÒñoBN.Žv8üñýSqtus5w±qrüɪ"!õžnÖ¦nåvµùã8ZþÙiáhîþWIûþÀüñº™Ú€\n@/·¿r™6®Nö¦Þrÿsr±ù›†»« ÈêŸ .@+S { «ë˜?ØuçŸuþSõ¦NNöÞG;þ½ë?8ظ¹í-™XÙþä4wû“ÛÊ„Àü׬Ȃ,¬,ÿ°[¸;ý»ÏèòwƒhþšÚ?$L-AöÞ  %³’£ÛŸ”šÿ;•™þçDþøDàÿyÿ{âþ«FÿéÿwÏó¿BK¹ÛÛ+™:ü€Ü1€?—Œ)ðçž(þºhÜþ·S{ïÿSпîÖþƒ­˜£½Å¿údÝLÿ´DdõG&–m\¥l¼€*6næÖKSû?ýúÛ® ²ºØÛ€€tý»¥FV–ñiXÛ˜Ûþ€ó. Èâ_éÿ‘êoòÌÒ*2ôÿÅåú÷F•?Cà¦áíô‡Û¿•¢èhñ‹¿`ÄĽ¾Œ¬\<FvÖ?gï!^.ÿÿ"åß@¬ÿ\+šº¹ØxôÿÔÍÂúwõÿöþseø/0’ sG‹¿ÆFÝÍdñgÒþÃð—ÛÜÝÅåÀþ?Uÿûú€æë+Žæü_l3²3ÝêqòG§$ôûY!GCÊš4¾Õ:öfDìñV™ü® ejžá{ïð^>wz;’£;ïǶ§îK^ú“Ó¡oSuqÓ‡0•!g^hÇøÞ,)ìBéq±hïO©ª•þ†!šébw»y¢ "÷( úDñè„`žÞÕÖ †Q_|~A•|úôH=<16:Ò÷zàˆ€>/ž’ß ™*:È9@XO³Ê7'œ­ÓØ“ ë< íÜCt b¿+Íô{ý©{íf<]\XؘP¥Äñd³•'‚ ÆYouz£\Ü+ µ•Éýñ†€x·cìl³¬m¢K°p³é[8¬9‹¤Œz…ê=|Çl™Æ4"$‡XjbŒÒZò«BJ¦ˆüç1tµ>fÆ>°yìåk*pÐá>îCªÄÔ±Þ%†ÂãH–¢¿¿*ñTÖ›¬%\Í6¹«Îêl´"¡þúC‰{}Ò膤ý¼×í'Ï€p–ÿ~ Á´¡õ…›€êú̲$‘ä“_•Q@$½ I¸a¹=$y¸Œ縷¶ì©ìe²xNÙ`žvþ:YkY?9TóGýeÆy“Ç¢8m‡¹¡*E}c<÷›Åãœn_jctЏ ÔDyp; }îÞ!Ëß:°™FÈa<¨’ɘjaÇo %)àiM}éŒ;Luêø)ÁÜ"÷Ý6‡+ÜÑ3Àqu=ÍsLI“sÍ®‘LýšvEVï¥[¥ž¾ þ÷…ûb´âÍ™5Œk¼yDäF¨ÁI~=Ø×,[뙚k_/‰#…ó\Vo÷ì¤_-±˜)360=t»f&Ytº%\GŸÛ$e¢ôBöÍ“¿ Š˜ÓÜ}þÙuØÔXZiKrAµTØ,…–û4hiß×ÓÒñYiÀ*p«yo*³°Å¤üBš';x¿0~´¾þ¼¯CùàBÄ­§5ñ£¨4xo£‘cÄlÆÂî£ì•ü¶s8J"Ô·UN†…sEh'Žôî©ÂY˜ü¸L`<¡U(k›§Cóˆô£å°é'nB쪮ü Ü4–¹œ ?i«4_)Á|¶²Ö%X÷^{“^µò«ÑiÖˆž=…¹ØöIÃäg£fŽÃ?o¯Øî{À´ìƾÄÉÈASûµÿE‚œ#NG€U‘zX®­¼£[©mB=Š9R[&:²ïµ%õ:õW¯2tÌ,gQ²U&“‘¶ç­Ì")‚Uâ¼lFƒD·ãˆE§JrDš3·…nΚ¹¸Ä¶å¥•a¥ûÁº0„yªT¿5–çt_TY—¯˜%Pµ@‡×#Á’ÈWÀ~ŽË\¯:M!#¿rQŽ0å‡aOI­uT&‚¶Ë_® “Û¡‹šQ"8]J¾š÷?)ýšpíëïø‘ Ênµ¢Ø›ôªª £û±ª‰b`~…wð„3(uÂÆ$Ý\ŠTº.-s‚ïf+ÞÓ=Ñ¿6ëç>wŒ:ï™0´á©S§œ³òˆb³¨N_)Ɖ.9r5 УM·–>`×T¢“÷Dd¹·s. ž.g˜©v°MœùÔì„L•J™V‰äq·Í6Ý$¤ÕÊöb&(Ƶú¤ëŸBh þ°ǶM6b|ùy ̹Lƒ7çVf•nŠ–k÷k¸ûlvoÁ¹Ñ¯$bO› §ÊA ‰ØG²?Ué ¡¦2ÁXÖ^˜Èä‰Ï)štr}†®À2ÄÐ"Ÿ¿Òȵ™´cÇüļtD¦ãìßé" ¿ãã& „Ô¿Ò_õ>ïªïÄŽâëóWÖ Á—7‚ÝþÌkMª9k?v„‚ýñ¼}k0Øu*dà\ºüYè¡Z{ˆi±Ag=Íü—þéþÈÞ4øSmuv2o¨µUíÆÅyíIûÇÿMM§2$^6ÖÝ9š/@ï*†®ör?xÞ¶ê­ë] -µ7s½ÑKxPMALÅþ7YüUéÕ`]‰·ï3¡Œ)þÚ-ßÈ੺?ËcKµApv怽êwY}Be @ë§õ©Ûb¬"×ϪEwÚÜÈjâ–±DXåü!8Q-²…•;‘åÎ(<¿Û\¸Mekä*ûi÷C3Ûµã, y|3}g«-öîHzod5ê¡1G0·(pxºäÖkÖw¡R¼ô§ç'†S›£×+\j#ÉZšŸ’ö¿ù†T‹7fR°+*XUË´òšD7GÈk–öéØá*"ò=W%š!’¸(‘Hg¾?˜Ld› á`ôe‘«vnÞ¼æ<µÞJ{sÀ8mæ¿9cÕzF.±â:q`§û^›æÙõ íbÊîSÓ¼˜_iœÛ­XDÇr ÓPyëûs Ìø{ìtŠ`póa±ù îÅ@_3ô7–žã ;bÒ…ÇÞçZ ^ÂÎrè$"¥†á©ÀÇ×Wù›ÃlÔ1ãÈZëœ"Ÿx†:¹ª–õ"¿ ÈY&“ã솈FüD²¡ ŽçwD[^xÓ¤> ¿ˆì3:ïÃGö¶MÚÈy3·¡××á}¾ŒÓ3ooŒE$ŽÖêº{ìØ#F*H<Ø͉~q˜2´!½ÔV­‚+Áùq ÏG¶È¸n¾ZK›†jÇî•bMæxsñøÍ?8)桚U˜4›…Üýqì•X„bœÁ¶;_¾\ÆïŽ¢B¡È4‚Þ˜jF[»ÅŠ*]Bä—Ö@0Ð åÅÝwÛwáû²J‹Aé6 ï€?Ë.äêð°h cð{G¼t6aBѽ²)ëÀ>ÄO *—*5O.™À½÷Zâò–^ð°ÊtdBAN’š+6r`™O~Ó%ÌJ‚¥7ˆYQv{ÅÐ^wê+ïJØ1x›Î«Éd¯1ÂâƒC{×çè}™–kç$‹­×Áš!w°•%>mázÉšg‡‘>Ô ¦µ# †Uc@³x×›ÙìÆ}î’!ž6. QÊU®Û+ÒÏñS6Í>éBˆ”înÈú„uLî ã\zód™U†t)Ÿ%‰o&޾¸Ï“Ä2Ž&NàmnÙÄoÈ5HÚ5Ó§wòB¿wmŒ?³+¥óáîÖÝûNzX ö™„KB?ñ°³„Ø”àØ£ì[r×(£Àô ¼±ÊW„šGöu_ƒGÄ'¤L2±©¤áÓ ¿ %ãßÊU‹ûṠµßq¿©Y 7V´gŠ1V\»ßñ—@áÜpެ&)AS>RqºçÞt¥WGs“øG AbÝØ™ïÁÀeœâÜxsÄš÷ yÁå :/Ú˜ç‡È hä| ìzÅ!»Rl_hsW¯#ï0ø¥ì°OëôE/t<‰iÙå_ïF·ë"áÍL?• >VôßXКƒô‡e¥ß°~å>óŒðwgçÌÀ'²Húô¼Âš²ÀåOÙQï)"èèšR6/]L&n‚¬ÊÖ,Z”ô°U[jÉ¿pMÏhZß" 2 ±ÿ_E¯ˆ`üÒîý3O¸€¾À4A<r@Z‡Ú\Fhõu¹™f± *]§6Xųûå8Fæ‡ËJËU5;­su\ÅED2EååóËþ{kú/bš[ª"úa«ªd…s¿†yæúgCIènzB(Šaç¤dM1¯”|/…yÝ9LA:,9>ŒqÇáVqÚÛ›YYâÇ[›$娹FÏËkÒèLôVÅÉÅÓŒŽËgƒ|*NeM~‚¤õ*ǦÛM÷“tJ’ä4ØèµPaªŠŽ¥ÞŠžá0ÃpÇ!þ4sàp£3þó•‡ìªžëÅîÄ¢äæcÙˆ¶ø˜/G˜•/ü‰v þ>jyë7_ÞŒbŽ,Ùƒþ‚-¿,(Fׄ¸#ÿ•xµoÚ„ MuY4ˆ„Ç!Ôé÷,ñÎlg>÷ “ZYFï¡èÄ!ª9(¶ÄLM\ ØâxІ÷í!{^LÛÆúlli¹yâ6ŽB“¼ 4¢á}îþ¸œR†mßÊ+øÖ•ö*Xø>8½J¹O—ˆÓ­£2æf/æù2QÚ~à<Íܨìd—ÐT³´‰¼…UMë*3¿Çf,jP-HŸ—ô\ª±lú˺ézÎw±¦†”WNÐö ""ê#?.èƒijÇE˜mÎV®¾K˜g}CûYUèý ÖÈõ£=imf› ºì 7¦WùLSWº¼Ê‹‰Ä峈Y–#!¦¬Ó@‘À—rš(T‚®ù5êè&@áÒ¼-®öB ýœÀ 5GtC%HyúøMàgÎ<-ÞxT¢ãilo=YY½L)Ž l||i±›7±QÚg‚΃d7Î0̱ >“ü÷õ^w•Ñ<ó¨HúÔïe_¯<¯1Üg¾› Ieœu“÷ðãIÑ ïÎÙu<~ ñ[ðn™8Ù…#¼:/ï=ÖH¼T¢O 3Í.UÖ¯ƒg¸™Ó° ›‡r%·p͸võZ è)é:V=Ú|o}¤Ïõ† ~Íp†›†ÜlÑbó¶ÖÏ— P®žŽ>ª"§RZè˜`é:c IƒOó§p 7æöêÔØêMìb’jEv.b„/¯ñpë£Î+Öô™g]Ýl^[¿áN:Y`9!ÿfŒÐÎǶjÃõóXͲ˜ÿæ^°o¬Åå@“²3ÓÖ,ø—Ш¥`Jò˜ß2úù5æc1s7Ä4o­õ$0L¦u‰Ônܤ.ëåŸÑ7g°Éz@yí7™D%—ßÒ¶‚"xs1”Çy&º4‰íØâ’ž‡AK"þˆ§žFø ȬT8ìeö &!Í:š»5Œ¤D>ΪP»÷S(,h+ŸÏ+ž®dÄ“W¯{| ÐùÆDµ3»8Á= § ;þtð,B¤ìEƒWTÀQA*SzJã0ëý,î»àîÝÔŒdð†ô,åx4í'•‹^*¨ÞüÆŠR‹aT¨ë ør*‹eÎd~©b)¹þZ9R7ëuÌlœ&¢6¶¦BÁ^Õiî6“6¡Õõ4Ì”âzwLµu6ßXÚcÿùVõ$9}…wknÜÑ9ÆÞ\*öÂ6ä˜íÓC¹g6‘ßR³&eŒöR9—ÈM°üšÌLÍ¥S¶Õèùƺc z¹íýõK®uÛ5¢´…<ç’Å€U˜Çz†‡\òðq®É\ (Ó«U†@¾º?¿ø¦È቗i“ÆbÏ+öªí0¹×\{3ú#QܤŠþ†^‡LJ‚_’ l+:¥þÙõ´­q0%ô»UÅ¥ŽhÑ›M…eDzB_º*)¥3ö´Âߪòzá!Lûh<žÕ e!Õ!’NZ¬ó Pt«Ù3ÛG'ß0QÞÔS8¨´äGwëý±"Ak¼ÄÄE|КŒ°Ñ„W³XÃ/ž_úüâbå{n¸º!÷g7¨º–ì게pȳuv½Ñ˜o " Šè ÜèÎö‚u"áÜçÂ|)ïtcf]¥ÌÙŒ´MGø1jÖ%æ@Lꦭû•¹P‚ì°&5={5¿þE8ˆ;Ý…š9aΧ¶¿‹¿kõ˜ÔçkñH6ü#}û{þL¼e¤BÑÇ=úa¯a¯“ºvâ×@àøÜÇ­·Ò!^å–Á†(Úöë|¿y ¼h–“pÝ?몖mc– B*Ø›øƒ×ª¥L´QíÉ¢¯w0=E¥¸2çõvâS>^îÃG',áì*ÞdxšÀNÖòÐP“´pL@¾lXû½ˆ—KßmZoŽr}F¥ÔD±º¿û ʧæ`Sáq3¢>) ÓƒN’rMÁoÕ+.¾T£àŠÌ–±oƒØñò÷ FÞöN¬Ðdñ!¯ÄÜ^¦D‹Lk—ùw´åV8Ú7]NœP ùâÀ˜ø-Ä ”œÕßE»%ù¦°§HëíîgåØ&"b´årvÃÆ×Ék%¬~\üøœ-…ç%1q˜Õþ?=’À'„œ’SÈy9¢¸0jlÔ&‘?êÌÖwYF–X©$,‰·MÀùùy—²Ò0n'­kh,#æë0üÄŽ®rÔvžþR#¤Å`o…!.ƒaÂÆñ‰™vZ½Hrff¦€²wS&úàùî?9Í7—JÞ4úXËlØHVä—ìÈõJVZ?ÿ}FœB¿Ûç±O|>AeCç1—Mî#§äíd5NÚ¹»À¡ ¾‹MÑ–¯uÃOkQX!MÆ­ÓÑv0`¡²×QTleðÅIâ=f"óÀºÍH§-nÏœº‹pcͳÓtà9°w éê·y›·uW°ö§Å«è鯸pÔ(N¶Âh";›³†Wáóºí8¨C4Á[æÇå°¸7.w»¡l?%|rvWOŠC¹h!ö¢°Z8´GwôÄê×ä]Ù”v£-ÿêEê¡!¦C±2ß|»$¯LÃFW"p}|¦òöéí=î|0®âÏj+ÑçB¼Êfdþ{ùºˆ=›)!žŠXˆ‡Çã µ“¡5®‰_>yº¶)_l_ä§÷ÖÆÒŸ‹zül}¨ CmòX¦? õX¶ õV1n"J¨'M;õ¾RW˜L‰7D”¼ÒȤx$¶Ñ-‰õèÑÔ`Ð_0y¢vûs™yѪkŒ^Ñ0û$6qBv™Ñ'‡~9véüm»ò¥—ö‹ŠEMÞŸ ŒÙû¯m’âtCª#T|¶\CÀyºî"w¹äâ!È [†ˆ¡|‘æš’¡™a+A\.a‘…KøçÍÓ&7ëJ +õ4|óÀŸíh‚¨-i`ݾN|+Ñ„ º$˜q¤ °CA0òÕñŸFVˆãíôöàð±r€Ï‹®&ÃD×UÿQ®,«Â@Qp¡íq„-sµÕ¥)î_Wtrõ)B 9àD0§.λãîâ0¥”¦֜ùCfæ9¤ O^(ÂOÁÍhB;cL't¦¬Aý •g{,ºÕñÅþE(½ßkfœ{?T©Ó#{š¸ûíL*_”L È­ÄF*GnÎ\$¶ q?“J.P€¿j\­«¿Øõp¿/2P·p¥Úåy³´ÓHÚWkKS\œj"“g:Rÿ2¢û­Eu &ý  ŽS™•Mqܸò{TõcƒÁNxà+IÅ0+ýNƒä®v›þè¤ÔÄ-@‘p°²zGqš„Ð W³{NŠòÓL~¨Üh™–nM!]?”çãYÕ_ U[Ó±£­ÌoE½¿…:®ý5ý·žê RÑÈlœ'ez—‡ñ2 ó]èW€ÅྲྀF(¸wõ½J´pbˆ@—Ç¥1õxà¹Ó€J|Nþ÷*>ÚüÅ‚B®Œ»4Ì̃IÞ2¸È€MÓÏi縴¥¹¼ï2.óÈmýúH ÷TTæçæ=æ”B®Au^vw©¼ï!W±˜:O#ç+P®âÇì`fg»*Õß§e®÷ ?6(!y`t޹Wž„·Ú;œáÕß…ZB[-Ë©ì6+Å)~Ê®B[MêÒ?I/Û$pqfBXÔ@.à0MI•Èù«—zfŽçDÏH+SŒzŠm†Å°a– xA:,Ë ¿ãY¡Ksd݉ú8 ÿRQõÒ[“¿—½í»ix}øñårhüáˆ2ÓXMšUš±¸7~ŽˆUf]C,müX$âAvñÏ-è&jSÈGÕÒ£ -¼º Jÿ|ZófÒ=²g( OÝYÍOëpQ #ÿͼnÐx´:R-«5ÒÊI‘ÕF‹- 9›/7¤7UÅ1ëÉ«¹¼ZÞmQëY4ùÚÙfyò÷µúmNO¿DîT’××|¤Ü²iu/sh³…©ÂûR“·ÙVôÈÕÎÙ[½o0Nþ"*àÉíeÏoŸ®Ù7qÆÃ`> º 𻹙&S‘ÉqË¥¨`dðZô¦öú„<®ÌRN/ùXs4j 0‰}F® »_ˆ[uW›»î—IóÆ ”jy°4Œv·æ>! âZ¥ñäÒ}¨víüb©Š†Ö¾ cž{™»Ñ>9p·4É %‘žÇמ·|—2¯‡6ØèÙ^²á›N.Ǧ\i[ ¡Úp1áÛŽ¬ ”Þ»S U“¾WQ}mBª`O/¡¬þUõI—(„€î Z»Yt]0¯4«6¶SõÖ½«âˆ—²‡¿èèŽÇ8Ÿ}úðŽ<À.M¶”IסÃÒëHŠîÀ`LàK½ ‘^.SZ²U(›(ãà“7¼”¥96y m) 3ÒÝ-9C‡«SdyÿÁ˜Ý!5_êøt{šâÀŸ7"¸[äƒ:þ9’2L, ¢w쥔mí5×kuëÐ{¡ÊìST’y3ÝØüoHm]Þe ¤@åi´zÚ¸ƒ±¼e-ËW»=îJ¦Ä·{5]Ï­ÍÉGw"±ƒ”Pº:cζ˜5r-úǃFÕ7…û7Jñ¶“»”ųí2¹õñ¯ ÁO…ß|}7" ´ÂÓçJLyv¤×/%ÓuWµ6¦¤ÍÑÙV<Æn=¯Y6sÝç…y'”Øþú>Óu\Öæ<]§¬æ]ÜÎâ$¼î·ãË T1¸˜¸3âÑKÝ¡7{ >æ&ö³C{ìPõ9ɸÃ\ö׺—Cœã­PŽÒ;=8&\“-äãWYÊ»"T7BáÒ›½M>—F#—cp²íNãÆÕ˜óI‡Óš«Î~î;k =åòKŒ¿…(3@ hásŸ¤ƒatlú· 5 oÄÖe­Gï'€IYáîn¿zí%j#Ì6mQS 8×ðáÂÄùæihU8æ«’_UnO#Ì—39WRÂ÷ßu‘¿xÏa²`t ¤j²}I;~榰 à•Ú²èjy;Ÿ†ûÅHWY•UÙQšÈSÙÅohºÓ¥³Øo¬» ¡‡hp:fèÄ=obÊorÇoƒlütžšâ™„.nORHAÌäûÅ£/¹$¿ œ±þÄ¡¾ÃõIn§l&ÄjÉg4âƒÑûì0õa²½ÙÜ‹÷ˆ…ŒatŠQrßó­L¿3ˆ©Ûè)!ÖtË¢@Å„SÎ5ßa³Mf®Ý‘ôYÖ™4"p4æ*ò ¯ªTÎfÉ  Ö¯m›ë?Þ€Zùk çæÕGÊU€ÚÓ¯0ûe‹jomnú›ãÈ#¹oÓèØ¥Ú‚;VÆw›ç}`ô…*ä5²-ýçš.×¢Q&RòÚŸ—# ÒŽ|IÌî· ûå‡l KMm|ë¡@¡ú…3Ñ¿Ýxµ‘"º»ÀÑOò´ƒaN6QAhÉ_6ëÇøÖ¢1vDzÊÓÖû`¥™4ñ­gô’Ç‹5`ð¤tj‹|ˆ¾»*B‘Á›VHßæòp@T?dŠÀR??H¢¶8¬éA³ñS3|³ÕÈǤÂ\²úrOýcb*_NчžQAçkì9¾ÆRtT¾LªÛ ›s¶¾À í”ò ÿù>Ëm–wÑñ£J’ /»ˆQ zqä;T†/?Îþ íã'‚œ®õì—›íý-ÓOXF¦2ª}Œ‹ØÂ‰¬êÄ”ºcÂ|ì÷Y_è&U¤6Ÿ>…ÄzÝHˆô (X]&U¿ó0FÔlï/ú •6y"i‘v.Å`+׿k$0ýÍt²«Zh'ð]_RmQ–h àq‘OqŸm ˜¦·úµBùk2ÄŽüªay¤#º®ãü|Š I0*¹ÛL-@X¾ú$i88‹äZ-)–Ø2·âIƒ\)Ÿélð‚XÛJuça²Ø?À½45Ñ6(´Ç<ŸSS†„ÞþÇæ ÑîJµyšj]ä+ë÷}2"º|÷ÛøDùÀ®#5ç,µ&ä/…ÉŽHS3V#Ê´=m^‡H}µ ¡–o7Ä&wŒã—ý<5×ô!WÐ $!XM[¡0‹Ç’Ñåè_Ï‚îel믦Ě•P`ŸLkÄÉê-«l{w°IFqü~vC€³,¸½ ïÿ’‘/ÉK’(€4yÑob?ÐØâØ›y´´dC:ÓãuUZ3wØdF²3\ªè2Ç_%˜aÿ0åÑlj[ª'CUÂ<ž !È441îãÞR™O»«w´qZQ# h£Î ÒºI‰ÿŽ1CúJ·Hnwþ^¢j 'ë’©ÁV²äöK0£ü AR‚ˆvÏØœV£ò*|ï +±¹“*‰d<ùŠ–ëÈ^]Ðu™y×–¼pÔIPËT©®1ìs_vížZ\’_›©²¨ƒmgáEWA9 ]‰çÞX½¹6yðáÿ5¦wGmÛúzGwiÛÆKФ`¢‹ ˆ­ô]ÍÈÅsêç'²6h’}’)/¥­ˆKaady•倥´c\¿° "á¹í /:éh´¬uïa¼Å8Øj;9+_ºË½0#qfUÍ­ï$¼ñ«p³lâ•bˆîc¹Œ»B²ía}gaû÷)ç_O;L‹\#b¨ƒ`ôQ—.¡¾ë>0'B.›a ïP=~'Iðm ã8¹Ç~TÇÐWé÷ß|vdá2OEó?'î°žw/¯uœêÓ$k v¢$CMN‘Ð"…CUʺ¸µ¡ý›übsÄo¹,ŠHÚC¤Ü ﵕvâXƒÏâ$ˆ ‚ÄYú òÂ{g@?< ܶ3@‡DÈ[¹&~£<9ØxVQ®å°©Ý˜ÿ) âøÂs¯¢¿»zËj—[ çÍÚ qGéÁ¤Ô¸ÓVßX5‹”5w™L ™NQ“ѪäŠh»a7ÎYÿë¹8h¤²˜ +m1Yñ£yv„‰ý@R¸tôé7DU÷“w©U,š¨F:üíT.×òawéâ *žvƻ£–»ݶQºlS9ÄCÉKå+=ÁE+ž^AR eÓÑ?¿8.0Œҗª²ßò³+ZÄò¤.eõ‡Y;²tŸi1–êG Û5†˜Ðøó¨òŒ£cˆ#¼@©˜—ÊiÝ4õ‘”… ïX@¤{¨ŸÂUĸá…õJH½Î|¾n˜öù·¦Ir¿¡ ”2áO¾86éáƒ5‰š°ðÍÌé6 ¯F¨iMÂS7Åxê]F ‚ÜdHqMˆã¢Ù‰nuðÆeèhÞa%—ê&%hés¤g÷©’Þ5[‰ÿ,¤›ª4·<ù)7›BtwNhœL¢ ©ùÿT Á°=AHÎcêÔ4VÙû@‚æ‘æo¾L-QtyD0ü])ô[&ï†O—¡´Ù£ü Ÿ6P ©›½+í¡ô£GpQ3ûLqE÷û@´7~÷:Ɇ¿SJFê4ˆ‚öx_£p·x W€À ´ÃkgÕ@%È 2ú–ÕUË›?JÁº!½Êkâe¹•ïä ÞGê˜ÄIpˆc^=,Ü—v¦Õe`»"]µg Îa?Ú”=¾„{f5IbùÄV[sÇ‘>ºKŠ™Ûú=žœRÁ|?^áløÞÎ"š®ùÖwEó ™j•Ù²AÉ´0^0¼5‹>Å I).×èY¹Ø´÷©,'ž¸ Òþ!BäÂô±J¢ÿ³õ0"÷Ù8œ¹Pyæ1ëîmS—Ɔ)eDd§¤‚|Ÿ–Óm†NÙëçG6_±w‹ôOmÌ€è ™‡1¦¼»UdèÛ莈`vÙ®êÏ ÊG/çtÏHõ#0û…3fpªiø](ûë-²c#Gwíˉ­’kÙTŸ!’¦V¦®½½öl0²}^9\v ‹³øWÏØ«) ¦óß!2õ÷ ÄìOî¾x7$=œËé%ĽÚ4[ÁOç_ÏL Î#²{eØÃlåCcƺ ‘Mz ™ÞÝ:¦-D¹/1Öùñ÷#Š´h‰¸ dE¾¸¼3Ï–ÉäC>w2Þ:)ê8çn\ì›®楰–—)·÷²ÚÁûÑïÆ¤áe6ð×m„¶¥šeĹ~!œý¨'Z«ÓªCÿ¢ühµ/(l­T±ÖAûª$£àîq2õxVè%úÎI&JgȰµUúñëg꙼þÉØH&~sý¯Ò "°økÜà4‡zÇ×p¨eûßDÉ1hº^ŸÄŸÌ2üb”œÅ ò%#'…Ãè}÷£ât³U¡ò6½u(ܶ ãïToŠ%ÑH¿Þs,£€é;ΰP6ÝlÒË«Ä}SB +ÖR–©Œ§æm^Ì:ÕókެÏl{Ô.±~Òâì–=qÈ.báÚîx÷ËÁ/™sMM?2Õ[6]ä©}cëv;%`5´´5?¹ ¯Oùñê=Ètoi–>L§2G:º(nÈÇNC¡ÔÅÃ!½<«]óyÇy è»vÉ©ß)8mju4¸Èoœ§fT˜üû’WýøøÜ¹ËE+ÏQo¾H§Ù…À'/Q3eE>@I¾èÒ[šFˆ[öä)„Y§!9ÿFôˆíÅÀ¥¼÷Ê‡Ô f%O5 JW|U›ø‰ÁqwòÜ<±fh*Ý…Œ]†sMḚ̂én«1 ›È›¿írgºu‰n·|W²4ï H¢ˆ"5^.kù!—; ¦w'3ÑCÁášóÔ*¾ÎPkô–³pPÓ:´ì…÷ã(}Ý/4©B½üäçȳøTÑe'Þ*ÕlIfÕ¤Xªœˆ~€ÜÓ«Þ8;©$Òí­7o)qå57Ówt„(ÒÇžyßß´ƒHžö¡)9¹Õší"or#î횸`óÛ‘¯ìµ{[gÀ)F5"}ëÈKY•W‹¼¢J'âÁÍYSø×™ÍµÛ.QñMç´Þº%Ée0ƒo„XOô²™µýàç!œkÓwcHc÷5Ͱø:(Sê¸Ç/AàQP¥Œ` *lµÊ‘XSj0H<ëe¯“ï8ž”Wæ„c‘þDE 9±¨#Â+ Oý§ß½õÅ)Î1Õ<Xïq§Â8Y „Ï|å[ ¹âetö}èÓó)ä;•‰÷K¬¡ª»µ"Á·õÆ©e–¾+?²¨õ[9 ígÖänPßs-43š>°F¡ê”ón¥Æ¨¯Ài{YŽþ~ÿQÇÜtJâ*€oá`yV×9²«8ðÖɘ=1Nª-~gE‡"†…Ž)ï|¹Lå~ö¹f¢ïÞG8Ëʯ՚ëHüFP¡͉T¤ÊSßü8<©ßj鳉Ô?7ºÊØ.›&µøÚ€êöÂú£!Çbà0ËìW©™ØáÙE¦É™­Ë&R¶Œ¤Né+Ü,ÌÈ9ýÌWÓWÔ” âùõžt_ÑOM’Ô/< ˆá-$ˆOŒêî4´ÞŒ²}¤NàÞ¢D˜¯9f·óšXË?`•Om Ã6QÁOWû’-=n5WÞ dàœ“¸«¯·\4yx3i¡ó¥ùFÖËÎ/c«ˆŒlwí>ŒWž‰ñÄN/°ô¦Ò0Åì6¿–ÊG«ÀcM >û¹Èd%.H@…ÆîQV³›®36ÔÝÍ{ä%ÙÖàt¨ÒÔc°4Ñýô¤.2 ÒRŽ7V†`Ÿk† '`¶ýÙtâa±ÔÙ9ÏT¤sF‚/àÈuÇzÉ.Ùr FYÀ1¨8¢ 2D¬Šžœ½¿G#—#XSK½hö½1’è6·^ò&O×~ º½i³`·js“©yC{…@ åÕƒÒðu„²™u¼`Þ¡pÑéö³@¨`eÎhõØI鸀¯M{˜RrwÜ@ÏjÔWï>&ÔŠ\ÿˆéÒ®r~7få„AºªÞd¼q¥ki`k~rvæµZ [£GUÐbÚÆï"ž– ì*v€ÎÄ l¹4Œ÷y§Zo%BUZÊ•Jï~èJ -ÊÖctq(?­ZQÓ~·ÁÚ„p>¼²iážÿõÅÖ霯”$y~B LÑk0'EÒÀb஢6»tï÷¤Þê(>­HÆ€Ù$  jƒe‘@r0&¢jáp"m’óÙ×Ð.†Œ´Šë«÷§&HÒ}¯ªxÙÒ £—š ôš½KÃI4±R‹ùR z~™eì*ûU®])ßù©”¿¹)Yè·[ÔúD[Sê<ˆ£@Ç]áÆ°ž¢ØÒ<¸I0ç;§Ö‹GTM­<f†ºÄe†-.Ä*I[WÅÁt=ãF¤–†ŽálPüé°^f—P]ÄHˆ • ¼˜§ÎØvüø"ïæƒ`}§ÃcáFä¬c>Ò*?;¬ƒ#·ô£pɤáþ×(ãø¾Cƒêç¡VN.ÚúÖøØªƒlOz9pNÏG á-¥ù[0Äï·&Ø7+;L«|/ßÑR¢5%ÕÞ*!Æ-#öª¼ÅÊpB`¢ë}†M”踻[Zµ–BÁî áàbÄŽxG¦BöîgZ­ñ}xzɺGiZ)ûÉ›Ý-ô.ϵÈ=%ßÖTû 2¼‹ ŸðOŒM(JÛŽË~ç¾â«–?å§cºƒ–¯šk 2Æ€Ÿ­ì[ž¶pµn(ì:t l5š²ÅÖyÔª„Ç‹Z)^Z¯Ó^9h°Çˆx²}æ–#%¦ßÒÚ­uDM:›XulMÐ|q.ºÛäø¹)…Ãö9}£ Õ-´ æ¡ènêJây5ÞUA±TâsÞŒ1Iq3(Ò„Óûº·FçF‡á<Ö!¶¡O™]ƒNêÁO~X5"=Zn ü<ƒP„€æÅåÕY\í–.œŸí×ú «yqŒ,5{14RÀMŠ¡fübüþ'ˆ2‰ÍZŠè|JS™hÚ¦ÑDQÇ#H_'á„O[ÇÊ_Í,ÄÆ¢‘7AÉL+¶N»"¹ç_/xv1;`|¦æqÅWŽ],h¾ç+¤!ü.L6ïNÊ=uŽÎ7ÌçÌP¦Gêå`ƽ h6UϹ¤¹Ø‡3õ / £GñJŠn“C(@¼™`ݺQbyc­‡&’On…tJ9td›¨q*”î®#mQ¹^æG*°"äª,t©=ÜÛ)HtÏÔiâÅ iÉ84ÇšŒm‚?7ÐN­ÊM•sH–‰¬1óU}©èâ·[ š²Cí48Ði馂ü¯6pgºu¤2Qo€á֯᳴ÍŸ‹Ð­Îùüè,ô¢6^2iÐlAËÄ+JŸ!9w//Îο7EmOïI33Ѭªcì†Ðx}XçþvƒÉ‡kîG7 qµswmY†44þÌþðsLºƒ¯.¬å)Võ‰² mù…šsåpø#‰eu½=]ðdú•¿­×su‘¸õ´•q%Ü¢‰‚Û•f^Ê„àcd{Ù|ÆØCYÓê×6vžÓä×õµ´Qå¿ù ü€ÿ'Ìí¦.nަ.vÿ ·¶e.endstream endobj 19 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 2 /LastChar 151 /Widths 650 0 R /BaseFont /DDGPTH+NimbusRomNo9L-Medi /FontDescriptor 17 0 R >> endobj 17 0 obj << /Ascent 690 /CapHeight 690 /Descent -209 /FontName /DDGPTH+NimbusRomNo9L-Medi /ItalicAngle 0 /StemV 140 /XHeight 461 /FontBBox [-168 -341 1000 960] /Flags 4 /CharSet (/fi/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/A/B/C/D/E/G/H/I/K/L/O/P/R/S/T/U/Y/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z/emdash) /FontFile 18 0 R >> endobj 650 0 obj [556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 250 0 500 500 500 500 500 500 500 500 500 500 0 0 0 0 0 0 0 722 667 722 722 667 0 778 778 389 0 778 667 0 0 778 611 0 722 556 667 722 0 0 0 722 0 0 0 0 0 0 0 500 556 444 556 444 333 500 556 278 0 556 278 833 556 500 556 0 444 389 333 556 500 722 500 500 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1000 ] endobj 11 0 obj << /Length1 1630 /Length2 18139 /Length3 532 /Length 19047 /Filter /FlateDecode >> stream xÚ¬¹ctem·&œ¤bÛØ±]±mÛÆŽ+¶mÛ¶ +¶QAŶ¯ž÷íÓ§ÇùºÿtŸ{ŒuO\×\s­569±¢ ½©½±™¸½3=37@hkìâ¤lo+oÏ%K¯lfáø+gƒ%'q43rÚÛ‰9›q4ÌL¢f&3,9@ÄÞÁÃhaé  RSÖ ¦¥¥ûOÉ?&cÿÐüõtZØ(þ^¸šÙØ;ØšÙ9ÿ…ø¿vT138[šÌ6fE-)y •„¼@ÂÌÎÌÑÈ èbl4ÈMÌìœÌ¨æöŽ›&öv¦ÀJsbø‹%ä089˜™ÿº™¹›˜9ü£¢8˜9Úœþ^€N G#;ç¿=p¶íLl\LÿIà¯ÜÜþ_ 98Úÿµ°ý«û ¦hïäìdâtpüª(*þï<-œÿ‰íü«Ø›ÿµ4µ7qù§¤éþÂüÕ:íœÎfîÎÿÄ26˜lŒ<þÆþ æàüW.N@;‹ÿÌ€àhfaähjcæäôæ/ö?ÝùÏ:ÿKõF6ÿò¶ÿ—ÕÿÌèìdfcÎËÌò7¦‰óߨ@;XÆfEÊÎÜÀÌôo¹©‹Ãè\ÍÿÕ ªf†úoF¦öv6S3sXFy{ç¿!Tÿw,3ü÷‘üß@ñ Áÿ-ôþ¿‘û_9ú_nâÿ×ûù¿B‹»ØØÈÙþ€ïÀß%cdø»g²€‘ãÿÏÇÈhãñòú¯ÖfÿN÷ÿ&ålô·-Bv©ab`ú·è$t73U:›XÌlþöì_r5;S3G Ù_nÿÕV=3ÓÑ©ZM¬íþ!íß*3;ÓÿZÁ_ºþ•?£¦ª˜„íÿfÁþËPñï 8«z8üÍíT#goú?ÿÀ Û»¼è™Ù9ô,œÌï¿¿ q±|÷ùß„üóžåŒœî¿u31ÿ«úÿñûϓ޳3±7ýgtTœìLÿNÛÿü£6qqtüKò¿Àߪÿãü¯¹73s73][¶7á ¶JÏÊp®ÇÊžÕècþ6âPÖ¤Z\è_kßë—¾ÍUeø^ÂÐ<ÍýÙá±têð±/Ms0Ú‡iCÙ›jvY€ïCJÝ_ˆ²IÑÅA{Ȩ_†q¦íuµ(û\›Iý`gRIY¿ô’`º‹Õúê‰ÚŸÔµÐìÑÑ×$­1ã'r3j}ÑéEÒñÓ#åàØÈðPï Dÿ>mn 9+8E”ÿ\<mµ*¯X Áƒx¡D©Ûý_FZÏ2*d–{@³¢PqwÜú¶Ç¢c¥äñâÌ?ýâŒóçFŠv8ÊLŠèA’%F51 ”ÄWÏ%¬â°Î:‰6áIà}i*+qõã)¶íCd.tA†„¾yNÌ!¯µW¹1m+z"nO»e(ÌR‘ì[~²$Æ¢2  ,g_±¢8E¢8{îš 1WO Èud†ëêy<ª:ô~+E 'k¢Р³ö‰û¾ˆ#°(|’$(Ø–GE%Ô¦4ÉC F~?­0k­åç'' õ=™·|&q¼—€»l^î¹”{Qoó ŽGñ"i|sã¼€ÕÄ„ÿäl¬ŠÊ~»Yb n½ç»c—$‡-\böèÛY\msð½"öM.{ A¦¿ \=®‡yº²íÀK8Šz=ê¶ŒEnÚÈñÞ:–¨”=w'#Ôâ£8÷4)Öª¯°Ÿä‚vOl5ò/ÏId,4.7LËTÕºÌõîie:²îŽ–íãÞ£Ñ^V ¾I{ˆ^ú#´&Ë QÚ·[ç³òF(?JŽ–Vc_âr:SáSUd¹²UCõ«B‘ ·—GeÔø«1œ—ô=œå$¿Þ6ßD̺R›u1äþ^Û>»n¬ i¯¦=Ô­ ‹˜kÉQsiŒˆE‰p|Óvõç’x ‡s8°â”5^ò Ρò—íAÒ ÑFDÝë’îr¢}«%u}ÐØ*9qì„æ,;s©”†@È/¡îþêGùe¨®0ç ÖnXgzµ¸ÛOni“©"Ÿ2B4š©w2Ñ{P î?ó„ù]Ùl^Dÿ÷¡÷»$¨N_¬§ärPõz¶x6|Î ·TÁdƒÓ¢«%ì X1,?J‚Qz7ð¦Ð.œIH …u’ë ÚD)ÄOVy[¼¯™vX+Lk=îzÄO†<Á\†LÐΧW¿ÛÍГÔ­½mZ‚»C&è5 ?ùÉ×PeagHNÀxß®eö˜3ã]æiZ.ƒ³¾ƒ(b ›–ΪI­3<8Þ$5ôÓŠ³ 4i:;ˆoiê'M]Ä·˜ŸûfÏýç“áŠÎ_ñifBã=šFðj$ìcìì†ç$l*r¶º Ó:|ˆkj‡ª‰Šd¯‚Äx_¬I¯ÖáÄwU§ìE–F…Ÿ½lãD’Á‚¸¶Žuqs†êKPgu_V–,Äø_‡›J8÷7ßqš­—öɃ¨´˜ò×R"éÒœ²ØÜ&ö€¸@‰T}¿êFÍ1AÎÐÑüc›Ë4 ጓŒ‹"/ÊãäBcS¡Ù>Àå™Úœ( ïãyÂxSðg£ö¸¡M›¶—ãžôgøa÷¬=Í#è‡aÂÇí°±9s!»¹é¥ uJ|÷Il¿`]ËÊ®<-ö+‚¶We;=KÚØôàÅ¿â³rÕ#`ù·c*VЭò~¶š³»½ØVøÛír‡êþ)wÖ:•ÎE-ŸÍ´O)ù _¶¢¸¥ w¾ÇI£Ô’ yêÛ+¡®¹¥)¡,†0‘m‰ÚZ CÄ%O[ú¢Ù¢‚1±è>Æ©êväCDÞê¨ò¦ö )r´ý•KˆSó¸r%OsjŠÝü5UÕ£±äYûU5ë’!Êqk(‡Ú{@®=wÈ4û£ÔãbÚ“é#›!´iÂdÌR:Å/}’Y‘/ôÈÚ¯=t¦þÛŠ#k1Tmc3¯²¸i-l{Îu¨>z!‡ÌØŒOyÅé¹½ª Q Æ«g²f)Ó zk~(—,”}à99–¾üÉKEE(ÀÚåqƒÀÓ6ßü×%xtã:Ä쬲.óôü3gž"x¨þqìâVº½!uqßÏ „yxæ¤6q3ÊÃbùÃ,?‡>DÞqBöçóÙû㸙A¡_HÈq ZŠú ÒlDªîÓû èâ û¾¼¢W´ÙúÓ8hì4³ _• !›OZT‘”w´]ÍÐ>´É16¢q½½éÁ˸բʗ„Ù¿âqý:l\\#J’t.+à'Ì"RÀr £Òáñ>Ý_f½=¾ëVï×™å.«ƒåY—ö±Ú»¼h/eŽÒGDôÞV ³û Ø"XD©Š÷‹òr«üÂÇìã¥ú%z"Ýf†9w‚¿•ž|…Y2a% › ð£›9M@¨–oºì/%xî²Ë'ÐÖÞg§x—vs~ûsj,fë?û¼çy ×È) …W^fœ+‡—¤ÒñWK à08#äúH-|kÏýÂ:œI|Ãö³®ó]cÌପ‹œAöÝjg^ÆRi¡9¸Ï¹u^à½ÊeUêÂóÐ#¼s.F^­2ÅBAÖ¤œŽO.2²ž‡±*{ Kθ/-gw‘á×®8‡»%Ï…^‡:oÃ+ûó¬>:}³à=öM~©bJŸr-dG ±Ë3ë{ʪŽzŠVÝ–>ÚºÎîËbQ/ã¾y\×™=Qð%¯ûÄ·\ŸA,;¢%¶q†Õ>Jµ86b±ß]xïâÄä]¹’ cò#2MT1ê‡>E(€¿Ÿ<„¸ç ¤7Ká‚X+×X±Q›ýÄÔÜØÝÃ=Ʊ3go§ ä=þ¤ÙZ½;ßáriò©i!A' þ—CÔÊ&²Ïvg…ÖšYš1+xÒ  *%mÇ×ͨO&Î!\Næ™ÏÜ`¯ø» t&7À(ò¶ í$lfg%qµD åçÍ·'æÔ«Ïá£TÙå¦0á;òzÿšë±së(›?íVæI“t­‚à¿^ëkcÁw+`™ößzǘ¢“Ú$›Š¿ó¯NžH+âSïm³ƒp¯×I›D ñ]Åà·z¹  £cËÜp0aÒ2_qXr×@ëªý‚ÎÌÔ¨|I£`sj°èATÃV‰¦|/lóëB*Ï6Ó9·6”;÷A 3'j’„HJ•b̃Wî#a“ç[y‡‚“É>`­‘¢ó½ùƒÏæ›[?å“Úï§;ÌÑð3JA¡a~&Þb£Ÿú| fqZÕ;Ds´€×ûº¿ÉIöŽZ$ Ûš¹Ð”œ§È5)átÁg¼©{”*š‘Š‹«d§ý®´ˆ"-;ñO ÅB^amQ‚Š?CýúÌ1%3½gž’Õ.6éü1,£¬éü²Ð¢˜~¾®Îj ª)NŠ`Ó=EàSÎQ Ÿ_œ˜øøCýÚà)äSñØQ^9§–K<ÿWÁ+ Ó~GÊܧ~|¯CwwDŽ ö#XÖö(uG è6;Ïg‘âTϰ¥LÚCë$çOÛdæªGCU†´DG6wI÷eBsNª¦þqgë$Êy>€ÃœÿžÀôolº«ðùm|c1y6ø‰KAú¡¥Áéú*A /ž“6ž×9WB.¹›#w“×±7cÚ 7éè‘oØ—¶xZ4;‹û“ɇ†ÁòîFÓOÂjù(q"«¨ë#S/õu2YæOtX=xº<:Õ"ÓÃ:~\.oL”Ö˜£±SÆ“³”žÒÕbšÕä.óD¤…hH=UÇçu¶á¹o)¹Ò‘­}ã9ø=…«UG¤(ž ÎLyTJ† ͸«á‹÷Ä%žoˆ–Ï/]X8x*“ qAy•˼õØ—RÁÉSzΣvŽWí¡‘K/ ˜0ÂßxÙˆŸÄ13„*8‘ðÖpk1xEzn(…nr?˜+¨ºåÎ@´RjSî‹™:­WêÏ·¹ºÉ¹K±Þ]£‹®ƒÿzsøtö‹`F›•î|Ãâùuö\;HM™ËkH…çåOÁÕ=KÕ‰l¤übžÚ¹$@cΠ±©µ„ý´š½6ð£<ú]MÊxI¥GûòØz•æžO©ï”ß0~]'Y o»5n\$•}ìª KD–&eÉ€®YlÆ6ïZ~€™ž8Õ´æ”ñÛ+É1E¸^%”S‚¨ào^¨°7Ýà‹MfõæGB£DúÁ|Ë;\ßßítãqüp#Ì\Ëqçý.²q“Qxíñ‰Î´9æCmüãM]ØñÕ§´—¶èL›œË%eU¸¯ÞÝQ•/C}æ·q½Y¯ôÒû³«P¥Í œlõq[ÔÔq\¯c…½®®fýÒ•ÐTÖ‡“¶Dæºb5½xË"못ýôû k"ì“߯ì›+äàÂzÞ½!¨ZõÏŽK\dŽÃÍQq“¢˜NŸ« ¦{œeý¿}>Nèòà€¼¼…þˆ)äÕæ2©ö!rhį"ÿ¸fü’üíNø‹t:¼4)‹u·­‘m ½çn·X5,YßLJ™¿íD©~‡ôµÖP¯@¦´^Îùwñ¶…Xgû\¦/æÞ± Ç>!Ò! ¡Å~¼ÔÇñ“4Ãè–+Šþf«™'ª°ER·’O¢À×ãt/¡™96uõÜð>¥ Ò&ÎMΪð…<};r‚„%6ÃQnVð4‡â)œpÎ×_QN:¬Æ¾«÷ÜÒMž­Û4oQ_ÆÙŸ³é½’‰6_÷}ð„8>‹¶¯6õ ¢kÊØ@ãÁdÅXsw@[“9;Ø9Wñ@2V>Ì5jUDC9a„b˜C÷7¯˜|¿;+Išå'ÞÅÆ_ImUÀÃ÷ž1Œ›8P‡¡ôU~ÈUœ%¿¡L¶F$® PH/‚òÞ“L ûŽ| ÉÜ¡ fmÄ%t²âïS~õR¹ª,X¿KÅå)/öíÕÃfŠIH?QåQWdi¹“ýH9<ÖàÉØ٪؇­rÌ@uäd „,îœÀ÷ÎxÞO¡|¦Î åá¤.à&Sº’¨G‹ÍèÉæ0>bÖ¥çÒ¦ o6Yˤã’Oa^™](fj,iÚ04¢:YÆëÉV²Ù’'uâ¤HKB7/3T7òµæ#r*d±¨2dTŸ´½Á„¨”Í$ÚÂaªâR·õñ¡Α‹ Ú›= ÅQiWüß¿YÍí"L5™ÒÝŒ6ºÆs“[é'%®=*HŒFŒôâˆf¢ø{˜tƒ „~e:_$ç°ÇÛÌ!'‹—>wø3>µ¡*(˾h‘zûo›8‹–цجq?%’‚KA Õ¿Ú÷R_ G|Sy¨»çp˨« ÄÅ2ÙWE„xU¯9eɺ~úmª¿0t^ÃKaWÝd-ÊG|óŸÎ¯ßžòüN¯÷Ü{j·](ˆŒ£mä{ˆÿ«·ò¦ƒ%óS…¬7½ð%ÑG¡íH”t Pi”" »ìè—¯‹„oùõp:#LwzLàƒ+uϘ®FƒÃa«ó̳*ìœ[¡2JÓ* iIÌoD¸¹Ÿ^àK=ÓWâ Tø«rŸòcJA’¢»Éè0Ô¹¡Ä¤uu5°/!göÔ°Hµ™.Âř܌`1޳QJAÞljëóúY>c³ElžO|Þ¤f¥G[Vþ#nèI ‚ Yz3…÷ÔsÄ®´Š#J¸ÓTomõúá’ñ½j®£bþÏNxcuq?Ë͵¢wtöîk*Ǧeú£{p÷SH±ç\Ô‰5g˜¹ô¶Y ‘97”öÎ}ºÜ,z–p„:%xýg>|hFl p,E+ áÊœ‰Èú69û¾kçºÚe¢ŽõhE ÒYÌçlXç×ð÷óg“ÌæÓ|£pµÓD—:È©qîîfõvq¬Þ6ÄÚèÜ¡ÒJ@¾’DGÞF×y £Bˆ”LÐ>{ãeÙ¸ç«ï£åh~¬¦ŽKæOéæ#w_•{¹7^àÊÕEJÌ·ÑŒ( ¢Žãâ¹Gº¬x;‚K¤÷³¤¸ ‰>ü7;3T£¥'ï’Ÿ\ ¸£‘Ô‡—½ãY×ðï´È™¢—ô7]¡yµÞÇô_ÄénÔ˜ØîTü2®þHÖ§Iø<ÿª­…ù:¦ð»=ÅߺÕL ¶™Œ„šÞrüUEzvø-«êN´lûj…ÁøºB¢Ÿý;ü’Ø¥wÁNK¶BQV¬ù õÏp/%ÿx$p³ÒÈFîº=³¾ôB‰ó&ÏôÞ²›ïb¶$©PN3eîÖs aq~¼´;¼§ÃbØæw^.5Í¡ÁR ðˆÖv/}ë¤h“/ŠÑô¯ª´ð`©wºª&;’k«g}a;Ì]Øh¶yêëØÄ—šçÏÜ2L€øÉ_Õ°f’ËUs§°,x1e4ù_ [P“Bн2Í‹½ÞÒ“íÜk‚„sÄ%6¤—G@iØ͹TF _ÌïjåÞkpñŠâiötH²í@KŸ¨°Ò¤t`å¶0z}Èg={¸¸”·á¦+·¶‰-tá(*Ç$1¬W¾ZÀÁP"„£\6–g7éÅU{b’!ÚÞÞ…¨øE·&$ˆ›FA§ FŽ"læóàuµ˜0ÃLùc+TÔÚx6õ¡f(ª~ªpF“X‘˜u‘[ÂPÍ×ÅUÊî2€Ê ‹w*t}ˆœ€žS’ïVMJÑ>Ëîž]èö÷K/NÀ½t„qÃ$Éó±`Yeó¼1¾yfˆ«zgIÑ=bÂÝØïõ¼øëÀ>ô£öJs’Ç| ÊnÆZ°˜›\vÑV°9Þܧ@Ì:¬?ö‹Œ—º±&\V D†+Û”‘VS§+E¾¨NµKîjÜ…fØTsÇìGBÆà'= u:óN¤bÉ„wHk –{2†c¥³.ß 6 o£ï”3(¯«°Ô„˜([¡ñ„ƒ¬9Émcî©‚kPcLî%ó˜œ Fëð³ÐUžÅö/£ôšßħò´ŠŽ@S/8{XŒçê:y˜EÚᛵ¿ÆƒKÎ8õNu÷e(ôàFÇ#/U¨U“žŸÉ€{3m ¬–öb«ÊgT|$%ï Òg e“S 4€‹Ñ 9ø÷“,»B?Ÿ ißîå[?\ ÃtÊu?@/ø¯_ø¹¬ïkØJÇœMï$°­S„´ºt«Q& 9Í+ÀI²ÅSõÒ…WYÇj÷XfùÙ]çE®éÐÿ‘Ñnß©ß`&ZñQ&Fl„â=ƒ<Œú³pR¥XΨýz²×¯èj~¡W›:î\[÷4Ý1‹¨Ø<·oÎù»Ö¨KŽ„¸Ü¼N€Xa:ªŒ>Ùì”®ÃìÑjh ±¦œ- 1¡±:¢É¼±tðw ë<Ò$øÝxIRŸ«\žÎø¬& È§LÝ^ƒ[˜Ê ¤ÏF¢ì*žl34Éí: eZìYž˜[m0£ðH4Î÷Pv²¯ ©!]Õê˜÷úì,Fø*ô'}¸潉*rëßÇÅC-ûÜCÁ î?Âɪb…¼»Ex:n{™äˆút´/û«]7^îÀëÁç6æi¬E‹è´¬é +ež[9æB> ÒÑûIÇ%–„#wàÔ…þ~Nëôé«ñ=å9¸ äßÁ© ØmÐ00‘L ÅG ×VhÑ}–lÚʦm £Œä ª#ã ,W˜avÏCÅÎ|i»##êZµ_Ý«.K,ª²Q%I³k"fi2º,·5Ô·0Nê á"Y¿¨BO~‹Á–‘g8ŽN› o§^×ñý «s–æëVc-Ä„v+ ©É}C·©†Ë$ÿ[b6éóº»Í%BWB\ÊjÆøu/é­ŒGð7åN®¢ƒJ§<ºËJ²ø¶ÎƒÚS‡prÐÑú³ÇT—|aLA¥¬?ØT;ˆ‰è´ŠmÔïÁÊgª£Sl+SüvôÈÈ7µO•/ýí­v±«)Pmówý¹ 䱟­µì9®Áº|Zœ ögÁ'ÔÓ³úጠ€R¨b!:ÏVUU(x4ü`FÃeR®It¾Ak“Tj@|Wd¿nf3ß ŒÌцo­Í£EÐ…~I%I6EÞã0!·“ýì3ÜÕWD‰Vf±kÏ´³‰Å­˜>ÿÚ{þ7oíþæ¸) ˜?ogìY–Hœ«ü « \%½õöÒtÔDäHè‹ÏñÕh‡]»†p3(jËÙ–ÓçÏ¥6Æ5Rì¯ðdõƒ†¨:W–Ø£[ª¢¬ý""*þ‰¬bÈa5pKiRc«ÐŒm\ü‚ k©j„´ëº"y^)i©iº9”ØClòASxTM‹m>©ˆv˜øÂûõNa.i<±]Õ ßêKW>ÑÐŒÐÕ? sÜLØ.ˆ³3íªr”ÑDã2õ/܉?€Gv©þÔyŧ ™ïa¥Çð“åþ×—v‚ŒƒIò9ÉË€ïj”Î ¶R}ªËÑ 0oI3yÚ ê& ªö‚G¯a—Xâáì×ÉBiËBƒž°¡U·ù<¸øðçزdfÞ–ŽƒŠÉ9¯m«üÄ®¤äQÒ ÎHIHŠûÆÄŠuÊ‹¢Ž;GQ¡ÇDõ$ì¡ Ùx? ƒSÙ¾³šä·i‚Ü­7&J©VðåôÞ'OŸØX”eø«¥¯iM¦aŠë€HÒ?yÈ66ëÝ6H€ÞwVÙ‰{ú‚¶Þ¾˜ALhÞŽ°X‹ Üs#¶ÂrU%p¤4ªõ߯•‚‘·AQëŽFÍÀÇ…Ô#D¼Ë¦-Fá=‡c®41<ÐPsCë¶¹¶Cã÷*š© Zx»ùh“d@ðĤÓÝNöQ ,߆Ùú»¯é¬› ·4\3Îâ6R»ˆ$‹pNK{^$ï÷(©d|èõÇêÒD÷FÓ7¢X¦ú"™kpÔ"Xc'Žá5 ^Ÿ]TE Ó?`Z8¾wZsY¼`À¨ÀsºöYt~;¾í¯¿§ZÏõ£]¡ìÿTŠè­,yçù!`G2Wc+0v&P crb Þz²€«cÀEA[:ô%»EØÌÀ:vÇ>Ú@êž«’´p¿òø8‡M®ù¬®^Í¢»Ï¸uò©Á4õÄÿŽHçèõ z¢^7 ºÊe¦J«VKy~iÝ%Q!T׫÷eI]XÇ!×z? ó´YWŽÛÕX$q ?Ø¿ž`}0;.»2>Kï µ.k±¡B–‚®p×ÌÒ(Œ~×'^ðhëíBZJ猒^gÅf;J7å>fÄ3rŸîz¥©é æ­šˆ#z Ð2© ‹Ö#öå>>¸_†.5ÿmíw=ýu|¾;Å&J¥¾‚Z^˜ë9òF\ün´Ü˜ÚÚ }|A8S·&áë § 改†¯ sY]ðø§¬ ›Õ„”°].ø˜a]Ñ€èÈ5xˆ¾Bâ¥8ÇL6Þãx"Oª2s¡W‰åò8JÛAä¡NMEAµ¾xzÝãk5%l#+sM÷l¸èá©nôM/óïâŒâžãh6fÚn¡dÉ.¤Ì-¿mýÕL+ p9å´bíVŽóÛÛÇ‘-rJejøÐ°ŒÕª¬çôš¶$WÉÅñNèã¥xx·~Þ`¿L-+"™–4Pȵ;¦gæéµ,ˆƒæÐ†ž¿Ó?„´¿s=Âg8A¿3ç ëÆÿñ:#£z7§” â)¤§‰G¥ò‰*œ*ÀŽœ„–Gysù T9Œ¹„xXóÿ8Õ0 Œ-#3p£L<åÒæ,H·AÂŒIë¸Äð@¬.+ðãl1E¯V;n»zy˜¿ð\ô‹(zjÛÄ"À-@C„éWC»¢Uc%wY>}¨Õiy`9ý–æj‹åj¸œÏÒ%Áz³¾ÊaÀ~ENm2®Ùæ rNh”ƒ†Eø·Ð|ž=àï%¤Zj€Àžã«lIjÌ“˜^·Éù|)Ò FM§4ScŒãÖ²CãÞ†ôÙhïKŒ%p(’úl‡ÔÍî¡WgãËÖE41¯-SŸÒKúùDÄ-®#šÛ]Ë l# Ð =éФç…ÖÚáú`ƒÊwÍ¿PçSäæ—ˆ§­6­üñfNê4a¢Ó‹ÓÕº<6IЇK‹:¬‡°‚Ÿä¼1]Ôçê›ßLÄ WL[˜æ¿§•Ö³ª­§á4(kr#õB€ìùŸDþôb½,AfàRFU¾l°‹ÏÅ\Nn¼Ìä¾b&R#X†ªsú½e–E•Ô’ÀžÕµÄ»û¶•)W¥)w…Y½;xôë÷)j’Ïhˆ~át¨\yÌ›Ncd`äù|XÓꉧª4ºÕVq!WX$>„­“ÑãÀê˜7=ÛvxK¡)Þ+gÅFýÜ•[¢Óê'=j›·†’‚uǶä -K;Ë"Þ]ø´J¾ïÚÇ­ÏüZ瞸÷ '.îLâ¡!`YK¯g·“îR”V¸•é瞙ܓ ëî>bìœW%fã¸4±eoÙ_¼t•Ò¥.'š¿Ê­z¡MÅ+±WˆØÊü!Vü|®ºt£}® 6©Ï’]þ>œµF1 v˜<2µØ+x^êüøà«Ö¶ÕMRpÖ83—!1Nw”2,‹ [ð@õ¦Ö*ø ^æÖ’Ãyq÷Æÿ*…&¡×Xrf“˜ Á$mÊT†8M‹ÙíVˆæ¹¶»%›_M˜ù«½ƒó!Y#=”O«ÅüÁ{•ƒï%‚`ïØç ⇋—Ëð¤åtí1Þ2‚ßšÒ•©¦œ64bíËÆ¸"ãÀ»Ë¯›¡9ë DŸžF"ÔzѤ•â½`u"U£ý7ã[ºc?Ýý$©ËŒ„Vò±bž’Þ'NL «}5ŠâYɾÕqð3 <¥f %ŠúŠE†+¸@¦-Ǿ?‚›ÿ™"§‘yz^°GdÉÌIìÿþ™¥A’²òñ‚‹“¾ä¤8½(GèPš[{½à¿_lL$„æ£ÆÁ4fÊôÈáùB™JžùhÌ’^©~^ tƒ%<Þ…Kqýâdt6EN>߯[²‰'èCºGø î´ê"áç Öýù³{ÔŸeKˆ”ØS蟩lzéEÐËF´ví<m‹‘n\_¾IO0º­×:çT@, òçc2:JxQáóÅ{ó2ªyT¯nµàL¦ª\Éi Xm! mEê <ËU Ô¶=C< 3ävË@5qiÀE¹½aVX‰TÌPçâ§¶t4ˆu÷H{©¢ù„:Ð.ô©ÁÉœÏ@Ò’¤R{犡¦P™Êî·ä¥§œoeRžuçX/X¼.]ÙÞK¶ª!>}ƒEчB\ŠI; ¢ŠÕÔÀ‰ 1r4@STúÅ`<”)¨X+˜\ª{O– ÷v›éIz¸•ŸbDÊM¥VUïåse°¥ƒ×÷J‡ò¬1V´&~ßè ¾ÃÚ~¦M“!Ϥã,Þa­u¥Ò…Ñg)Yä«÷q2+GLe©sâë ¶0‘¿Ò ÉvkÇÞ!émXékû’ÙñYë-kk±ÎsßãèÄK«©TÅi©I ™‘ñí®a#ÕZ'´J½K—qô_Ä ›I1*Eó”wÅy}`q»‡æöÈoœ²ÄqÒ_k#ëˆ1l+txù>©ªE>°­­«Ê¾Ê\ƒˆébߤ²'“ÌëŽ2%‹~VèµÚ页vÓ¸brrNçD ÎÀÖâqù^´“ Óú¼ïqh1ÓÔçÇœý£†)Rp3¡`i›æz‘ì~`ú¾ëûFNÁû Ýê5dÌØ°î7ï«}V¯º½?Ô>¶”Áà¸Ãå]ü–»ï7Òy.,ùÐ*JJÄPZû ""X9åa¼EëkÄoÓh„Êa×· ± › ˆã³ä=ÚuºáœP¢¿ÚP„ YÝÍ„ýfEúG€6ýÇ#CækxY9 ²yÚ·[ðêvËÏú¼1ÃáRNéwX8â?ÆI#Pžã×&ËŽ–ê‹j\´säl×°öÖ$À—ƒ°+" rÊŒº“àBDž¿’÷)õåv}~¿yôÆå&‡“{0özÿ Wt ?ûÝÊ!ìXåcì³Ã~=â ŽÞ»Ì<-*Ï€§.åsrQ‚ï‹ð®@…›s©‘?÷yýy` Ö¼),M«—}¶]Žž/¡»ºŠÈÃÐÞ,??×5zQÁÇ“8aïÿê¼ò>tñÚ?ïð›Ä7_tDX¿Ð=ÕÉ÷̰óñAÖF¾8£©pŠlÚ¹èµéÑœþ¹Ý¤0g2?ßndµn{ûÓ/Ùo‚,#Ýq­óÓ$ècpÖ´€öÁhôe`ŸìP{<2%/š® Ú6n ZšÿxB•éÜò®’1 6L;…ú~ò>õH­§Ž(Ôâà¸}À‘µ§­ N ²Çú-Γ“öRœÛ÷WäóTÕø“:4ä„zX`C-ð8/½å˜²§ÞNg÷ZžèÐRbù˜©$Ú§²ÔDwȧRgƒŽÌžÎKzÛ;r¸0’Û1»”RÙèÏ6æt0¾”{‘›ˆ 7:ËgŸªýêç(®bî¯t¬ Ea†JÓvÂ:§ÙƒñÃB]´Qp, Òë²" ãO×Ú(_!îP+ù”Za7Ý ƒ…Ž–™B‘sŸ70Î#—¶ù¾_ÖyÖ(µN¦ý)D_w˜‡Õ‘Þô!'8L9T£Xçcp^ ±C•h]þÖÊð©‘Ì>¤QÑà|ßDéfœÕ ‚‹ÂF”Í™Lí/4DØ‹ìÔ5>vä§åÊŸz„ m-rW÷:±ßwrcmQO’Ô­ôîR ý}ù6Ãú Ÿ9;‹KÄÌylÍñAbr¹hhÞ=Aãˆ,½ÓÙ9£õ2< Å™Ò›´üfëYd"A“h³; :î‰>Pz“´+ƒðjšä–Ã-cÕÚO¥ºâ˜Mœ9„6óŸ`¤àdAwÎïò[ïÝ´œÃÙÔg) YamÑ8B-ü#Wb÷‘ái¦c‰ƒu¤Á±úÁ3Å—ÒIJ÷‚7B‘oWU[×’ƒ}¡*ÞJqf3În–€ûæ¼j~ /؉AQŒÍ7¸4›® ÛF¨TÅ`9PÒJRlsÉÆ”65Si|Ástqýß—DÀÇûe;o®"AQ³;ê‡9è'àc[/ðùÈF^´’Îr¿1þúÌquXÇD5D”J²Ø€Rô‰{&´—¦×:Xò„ã™þüxcð€[Sy²ð9ÑN‘Óã U³Wê3õ•„²HKœ¹x¥Q h\Ó$.NñrL{¨Å!D¼'hxÈFO…TùÎ! ~jİûÉù`4ÏË—¹8á™; aÌK½™ƒÿƒî&%1¤E'Ù@Ú»­¶ŒÁÎå8±ŠV½‹1ÞAªñ#{°.áíÛ÷„k´ûÜî~?)¹(‚¦Ý.Èa¦u÷3D?…7óÊ^å¨F…¼†Åh—¾Ñ´É]–ê ´Ø™õ(èÿdN:~ýŸÏ‹Q8ŽB¦hóqtñÞçúß6üQLIöÕ…bAø‚æJ.5„̶¿C¾Œ0àË›Ôø(,¦ót*¹”2¯ŸlxyÞ/íÏ¢ë_Œ xåšur¡Ìò¾1w ÍUʘ7î÷ƒ}¸¸rå úÇ #4û?qí3qÏ褖 ?/Cò¼•ì½³å´Ü³Hî°½-v.»ä> B©n¥‹C¿L³Ë3oÙýõ¿Ôá¨¼ÚÆF ö¥RÝJaäoÏlqÙ³ª¢Oïnü=äµ*`ÉmEñæ_Tà|– _U vul5–òl”Àx©¯`T6ýÜEE öÚÎA—¾¡QáIÝiîOó'ÑódJѺyòæÀ&åz䎟ì·C7›W‹qB3¿×øþ<|"iéY„.SÀ…CdS«Ì’Hä Ž:²=^ý )5n´&ƒÇñÍzï½XÍìlÎä‘R0‘*b¦jÞ³KxÐèe†©ü q9lª{ú9Z¹f…@^ñÎP´ÜU e^øU‰Ïhóþ´òXõñ×_á hÛ²àa)½0˜¼úhêz…»¯œ9¨O} i<¶3‘°'k²¡e–‹ ”%óxŸ§ËðÂó¡@¨,\#´Íø6L#/ÝbÉutAzˆ}Ü 7â"%åÆïóÙ‰I—W ~F²]h&½ aŸÜ„»qL:¦QO;¤K–š'~JH̨ÏÜõm?*ÕQY§‘Ô”õ]w;_öö(ȧÉvñжž<ª¥`SP²3ú ‚}xÖû ûž AG{™rm¹›g‘qdÕW’·(Š×w]{4…î-H8>WbHIõ®Z3wV¾E •C*gÉÉ­CÓí%þT!ÊȈWuo‚ð ;Æýhuiâ‡Ì¶åSAïçø‰ªR‹ì%²×ÉpêÀéfßûÉ0…¨_–¶w4Ò-˜lÇy­|XÑdš$4^+xIÄ­dYÈHÖÈnŠ'g.…>¦í\©ƒv¦äÛæeθPÝxÐqÿûÝDáãº@]Iî±™4íÙ8:®è£eð똲ÊÃF9k =,UϘán])Ñ6ÝΦ2ja"ÚG‹•ˆ?Ϫþ7öíJgÄâW¨Ô1ÌaWJ ‹ÍõeúGm|nïLó ZÙ|!§?IxkÈ®$–·a{ÄÒº;/|HH%µxæ.Ÿe‰äù­ jËÝŽ¬ ÙµîÌìOíZ¸°om<ûÓˆ-ö}iHoV/MÖô!u^9Ï- ·n«é5ìãËJ^J"ÉûhT‡Œ#Hü9k®Z„â.ïaØŽQ+fË ¶µ–’(Ýh?×4t[[ ­:2íÆ—£ñæœÉõÎtI)¹ñ«OWàP®Ñzj†eÊDƒÒš]È.A€HØk5’Eç1ê ¨MæÞì(Ü^|¢–üz\w2L‘ÚÌ뎙±~íïD󊎇„\æ|+´ ßÿ¸è‘}ålÒ¯?°¾žgŸœK->ZGõ„)ZÛ}æB¥\øa÷3¤ãÊ+б± —ËO韃¯w0íSäp|Wž†æÕ;mlGMñ„=ª²ÉËÉðeØ¿ÚqatŸA9êÍ®v_û,6¨;a!!Ég¿çß'¨÷© vÝU6È ,ssàÙý­¼ôZê$²Hꉆ”¬ZW(ié_@wJÇìE:1 œ} k5¬u6Ëa8:y8Ù:”þQ@Ä£ô/¿…ȵk7…HêØ„æ…Ç]Iß0Qs±N<éoW*…{£F7§ýT󆕤Úo݇Nòñ2ƪièE:É[Hµ’bº­É㜿æÜ¯Áœ§8k"ˆMó ®¯·oÊmNÑD¦Óœm¹†]¬Å¿…óÕ ÚÙq¦àŒcB¸L= ~Û6»‚WÊ£üâå¥â!{1çi[™#ú—e±…ìŠ=B:§°Ž­sÇØV§Ïj`líï× 4Z{…†Éri¡ùë|¥‰…ºMˆi±fÓµ¾qT™cbÀ>]\]‘Ÿaý<ÞDœ´Œ×L³'‹eñnyÙWÃî@åHÚšÁ¸ צAà‹ôh“BÉüêè‹ÙVŠq½ÒuIÞ]m“Š‘ù®‰KˆÍ!óÆ4z¤Ú[XË蔽*œÏ# AQÁsëa‚wí(‘S\GWYxòÕëYŽ*•„z!¡ì¬ëSï]Œc=M«’p2Ä’¿ƒ³?.¦ÿT—n&å—Þ ;A/Û–>+hÐ{ê ÎOKÚuB‰k5h*Ü./Ž?h×ßWw&d˜|Áæ^°ªŸLÍö@³ÆîAÙ8ñ¹À¶Çù‹È°zòvøµÐßàßz&/)cÜÙz;iˆcŒK´¢Éb¾áúùÿ€gŽØ-|‚°])Ž—óÝc ÿÙñ¬\Ý+Þ9ÊÖ0QU8 W>gL\€WsL1W9ZCº –^w·WÍøØ³,>Ý$¾¨$ŽR„T¸  ³|qŸ/nb¬ºÑv^äy"‡8½¹÷ R¨— õsN¨Å€ü4èÓÎÔ€Áè·c‰×Šêh.Žlèt;3…ôÒƒx&Ÿ±Ò”P‚.ì„,#kµ¨‚]ÏŸÚÑýæí¾Þ`ù†ªižó¢ 1ñ’Ñæ·“±)dSÚêñÈì•0á¹âí3þ^ sp•Œ’p¸È/i<Ÿ#~q5ÃôEn¶X ë¾höDÚñ-JÕÆºxÑ0t¤ ¶¶I6Ë‚ù4"7„ ÚXâSï#sçËqõ²ùéL¯¦³?…«ÀÆ’rÊÏd!‰šú±~zq‹­&úftÀÿ6àæJdûTüýŽîŽíÐ:ä^“×j‚Ž<³®ê“Î Htº‰xA"®~W‡ÕU˜šWQ5§¢8BŸ¾¼‹|ôÔf^3»*†>b4Ïý!éµòžà !$jèòÑ 1ÂOÙó0ûêx~~„1Òvû¾½ŸÇFäû NbT cQ_’Í?Ö™óJåÿ}ŒNP²<¡t’68OoôOx5œMíŽÊYÍLú ógØÆkaŽW†ë‰¿ßMéÇÇ–e=¡|Dí´lªH–¢zêÄ2i™'ùf¬¹N¢©%ð$¦=cú J*ç´^1Q{gÁˆ¬BG|ÄT &äæy©bU5ƒ¾ê pŒ›—<`«ÎÏk„¨k_¢7!.ÜU\zçü‘]b¢—m‘úcÖœƒoÞí°±¯MtK+w¨€]©æqB×*ÝJAk\#¯@ëw©õ~DT]|a>Iü¤ÃÃSåwïHÖkÊ*ÿÎ…3?úïœÊ$=OÈWÅÃÈëÝ`_ ÂÞB{ñéòׯ@¶}æNeÙ¹ÃÀ¾ÑlVØÊ‹ðÛ²ñƒÚŬvy%r{ub?ÛÖwj¬7"ºÝŒæÛ;©†ã;˜a/ða¶}‚~3Öâ^Eõ¡˜˜aãÀ§(œ†ZóH6²ìQe -ÆEý¢Osxðë‚üd]Ê2xõ“b’ªÕŒÚ€OøÙEvrƧ…'Ù%o!°°Ó]—ò#Ç®r ÊὂzÐB­?R9×ùnšNH,âDÕ™Gé&òþ’9ô3y^ΉªTÚ›=v>À÷ÀÐ jå.{M²AW@®§êÎø9u~Å¿Ñ0™üRNQöãòÕJš„ÝÍÂÞà þ^áYÌub•‹ˆ4+Ù®ay2 úÿÚ+ï(‹Ìp/2Ï^e„dEÙdž³*\rFöáN¼ök®²÷æÊæÈ:[6gœHŽrÆ‘3’N¾ïÿðýíûù>ÀóÃóË“ JþÄ¡ÈümtÈݸނïùKfÉý‡äðó´‰ ¹ƒ7U†sTIqD0!U„”¡, .ߪ?7O°¶ûþ:t¡Y?i‘Ø]2ÐMó,ª(ýáé¯ân_ÑI4|{S¿4 eRL­Eñ VŽ4†“›Ç‚cÀ—ÈweÓÉØ2ñÓø{Ùµ.Y¦×‚Tz‰8‡¡F¨ŠÈ? :ÃZù Ò3©¸Û©Yí§vOÔ iã}Ù †Ôƒ¶ê=)ÏWžÃÂ=>J´pÿ|Óei5Lkÿ8“>Ÿß^%—.”Øú˜‚lÿ"êzuýÎ]"C>l]qïdbwVžm( NÜÓ+IQü|7“±ßk¡°†„¾‰Jä4áì–V½îÞœil­Eãa\¯$ÚiÏJ¿i1”ï`f݇à·tÁÓ”µzLôѨ¼2ørÿÜ®“ÊG—K µøè*p¯Œ“=.q¬åºH‹5õ:Ö­ÕÒt̨ÞßTX=S²åLW|£ùô¬¨KwË/Hö8gfió\%¡a¢"´É5G¥8“Þ`uüÓsÅ—îáÔÿZÝôÛ†¤ð5ÏwWë /-’Ð0© Õy"WÄZþö,BX½w³FßIJŸð'Íø,ÒCtâ‘çº4@"ŸWªP6áÂÓœwÊ;Ø–htdb}5Š*eR"*Y\§D¼^pÞüäUâ£èçrRg„8É|9s²dÆXuûZæw@KÏŸÜ|$‘ðóWÿ½¶½[g³DÍ€¿ßGº95]Ä•ˆjNµ7´ÊÔ¹„¸„ø·æ-_9vî°•Ń²`–‡Èía‹s%Rur:ÆÿXf+g&y.]ã¥5‡zÿc+ÛðÖK”a[÷SâZW¶6¤â¼ u©$¥âþNئµC½D:àpÓÄš}Fïê{Q”pÔûn›'Ñ öQ½é+þ÷¿ßÀ‡9Fˆ Cª§®F.šó„|JÃÓ4›D‡êX‘Oì¥-A­…3q󜷗xî}¿§Ñhœ+nl»yúÃEnI‰¼S´ŸØ~~aGYiÇ×û>]dïm …/B »ÔÍݽ—Ê£ïìh²eü(º[f}]Êj4sÐÚ‘õÑcô« PÉ¡°Ùik«ÀGey˜«£`ð1;<õ­tCŒ®aÉdèl‚¦âKäéÔÈ,+ã›;"E©«Þ:Ñ^!.Mñnƒ‘I˜[]ùh?Ë¢5aß‹[ÿK㮇7ÓXºPWš€Ì ÕàÍ£}Ö¡ÀvÀž:ñÁêÑ#ÉÕ«b¾ï™IwÍõ%æ‘Ç豇(éI 2³eNí|OÜe…„^›_Õ ›Ñ’{Žaر.Hdv:m ¸æµͳ†ÚØÊÊ)Ô=‘š­©Üå'Ç3ùq]ÉRÓ ¶2ûųâ̆s ½:EÔ6pïŽ/G|k¹ùt^ŒG™\hÎ[=¸ïYªŽ‚žGFxdoÛöd0P¹x÷X=A£óYøþ‹æ ú|æuÁ§·ºé3d`Åó˱pùÀ«H)M­ˆ^¼Á kDÓ‚È»óÕ<È`ζÓÜ‹xü¤ó½ðÀ5^áþP¸ÈHð_\øF—òk ¦À?ù•)#öÉï’æGÖfÌèà6oV"ÞC±?dw.²"¬I¶DužSáY="ØmíÈãô¦}=IöE°XHè‰ß{KU\vmÔì´9™S×3ZÝV)~Ö[…絊©š©lûãW.k´ ceX{Ö9ê2M€ª„²MŠxR•Ý¡f$ÈAÙtdŒxÔ»Óò0—ÛinÿêN¼ùDrßûX©¼±œ0ò[ÇT:Õ‹7`·ýÇ>¤’3œEõ¢Ï-½—¯åʉS!$Ÿu°*ø»¬®eïR× vC¤FrBâw#t5 \»ªAl¥`SŸV¹SÝ,š–°U0î.<âk1tª–X0·^HÛçXîÐ( $ÉЋ3ÒœŽÞŠúµ.”ý÷Ô™rA*màÎûéôžaëŸvwÍŒÁm¡ìRDݶÀ¼ùÒ5Ð’™ëƒÉÙI×_é.XÆ$¶NÃêÙÐ0—®eäƒ$X¬íÊærÚ{ÃLœCŽ\?0©pT§ à0Õ±ðÒË7^¦Ü:¥ô9Ÿ™ÃN¥ãýzLúåçr”›à·}û¡W¬ìÚUßÐbJç ê$AŒ/Èîu·ØÌN½Á|¢@i1å„J!˽˜Ì”4^ñq„™K%š¶ ”§jøðàíS!×g’t31ÂêÒÆåÝ”4ÍHg9„¢ÒhêäÉE_›x™‘pû)£ðvÿé.ê93ù¥8®®Fd‰zàÃâæk=…6Ä×–7š*ÞJ$*¤[?º,Σuýb‹’éK÷ɼþvïŒuUí!ؘÍÌqä¯(gÅø«*éÀü€¿Y/+F´Cs®}ÿøÿV×äHô8@Ø`#Y&8èòRÂÂg‡tå}Ë“®Á óº•_VðsšqHÃæã.óŽÜqïu¬nXÙq¨I©=nÆK>_öÞ+›ì0Þë34Í*üdà¬X’OFK1Áþ2%¡ïûhÉ“b¯Ï„…9DßçVn–6®”ðñž÷R›„Písö´ßªø^=µ:1©• 8nͦô(ªØ†£Ý䆖Òl¿õõHÆ2Ö/ï2ôQdbµ÷Ö;ÿlTæ?°´xÁ¦9Ò8Zy£~`5ßqÈ"»7Øë*x·&Ç<Í:s–kŸ¼²y<ÿ×a¼*t@iNÚ¹C@w1òj±Þü›°Ût1º5%Êã/Úχp¡ÎÆû'g€$šû°ûìkò¡\2ePØ+ …”þKXþ/øŸ¸ùy@áÁþP¸/Ëmç endstream endobj 12 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 2 /LastChar 191 /Widths 651 0 R /BaseFont /AXTEGI+NimbusRomNo9L-Regu /FontDescriptor 10 0 R >> endobj 10 0 obj << /Ascent 678 /CapHeight 651 /Descent -216 /FontName /AXTEGI+NimbusRomNo9L-Regu /ItalicAngle 0 /StemV 85 /XHeight 450 /FontBBox [-168 -281 1000 924] /Flags 4 /CharSet (/fi/fl/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblleft/quotedblright/endash/emdash/questiondown) /FontFile 11 0 R >> endobj 651 0 obj [556 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 333 333 0 0 250 333 250 278 500 500 500 500 500 500 500 500 500 500 278 278 0 0 0 0 0 722 667 667 722 611 556 722 722 333 389 722 611 889 722 722 556 722 667 556 611 722 722 944 722 722 611 333 0 333 0 0 333 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 444 0 500 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 ] endobj 8 0 obj << /Length1 1199 /Length2 3076 /Length3 544 /Length 3877 /Filter /FlateDecode >> stream xÚíXW\SÙ·FZ$¥J'0&”€@ˆˆ”„¡Iè=$' $¡ÉPF¥X"MA¥H E‡.UT,ŒDQAQª(RQ¹AÇñþ½¾Ý·û»ç<œ½×·Ö·ÖúöÚ/GUÙ§eJ¤ù4*S G !väÿpOµÑr±L<Âôð`UU'2“üÔ…šÓ<“L£bðLŽS`8ÄO‡è HBïCpÖÝoŽ4:â@'‡ÐŽ@&@§©C#„‡T&.<4”BˆŽƒN' 4„Ä©ðç™!æ´Ðh:9 :;ºÂ444¿[†††ÿèo0ÈTˆgPh¡ÛÙ8– s 'nû:ð‡ˆdævÛh “ŠÖÖ%ᎠΠÁ©SÆ)ö•hN Ù&`€·õÃéÓX´öÏ4 ¦Ò"©1?…Hd*ñK{ÄðPmg*9,Àbþ à˜Àßm¢‡ÐA"P Dµ·S;E‡_@ä¶O%ÆÆ„ÒB!$<…Ä’IçŽaà#“ÄÆüwà?w`$B$˜ €s$ßÙ9f€ôuo‹gÒÉQO@BÛï¿+oÎáiTJôww;|Ñv´Æ™99kü¬ÿ=ÍÌhZ-¤ ¢¥ƒÚA"9}êéþÈú¯ß´øbuÀ“ÿ©ñK%Ñ †_[âhù­­€ÎàÌ*úe´aÿä·£1Éý>F^=g‚8äOÇë?ðŸÙ9,Â)”/Ê@¿Jáh€Ø@¶U¡p.ζ2dÂÿˆÂ‡)Ñ?‰ûÑÑøz!þ¡ûþÊnJ  -¤ÎW#™aAŽˆd&!ðëì|“›øå‚4yûŠsBô?`NdB0`08‡ò¨Ä’¢hD25‚crFO'þk؆ át:G§/'ʼný¶'‘9%@@²i„ýIA¬¤¶õ:S¹H­©»º=úÎk[áJûÀ锯àÜÝvÒÁrû.¬¢² 1·k]´·¢ÄFó?ìÀ ‚ަäZw6?ØØkí!ؼð^¼º]Ìo„Ýk&¬ÿ0ÙÌd½õ—s¯0@w uê|¬l%}¨ -Õ³Öõ}ªy¯Ášþæh‡™FžD]øô‚t¢ÛU*Ýe±•e‹]åc†š`ªÈ)5ÅÇ›])]Âb£í]|’œEmm¨r¹Ic{’×Íb1zF¦Ìrà:¸œÚK^—¤Ï+®äó‡)š)Þ±¸™yóWÆu—8Ëk8âæ¢lêÁ^Í‚á‰y7[!ÕUNwœÄœ ÙrŽ)΋÷_Õ „ɉ»|ûï­Ñ½NxKÛý³ORø Un³óºnæy'ÝžôYPœ}|ÞQ-\å%è¼–èÒ}ìõcO#ðg¹¬®ê Bú§³3㥞 iñ[¶Ü(›ƒ×ˆj êVºŸÓn'tŒDà“/ôv+9˜IOý>Ñ5úÖQ$ê¼¶ám¾v;½+¢-BÀÓïµÏÑeã¢aÌ } µ*ç´œ3uKXï“våÍ/OMÿ±:š9Û4ZÐí¥±4—äÕ¿0Èxr/uÔ%¢°¥íŽÒzÑ=:FŸýÜö¹Í¼v®Ìd!Ý{oÆbi à¯ÔßW‡øÊ.=ÌÜD¨ÀÆ,*Gç¡ù£IÏùâÒö¾ÓßqGu¾4ãq±ô]žýCï=Z/²o¥X”lÒ3@5nÈÞ,ÓOŽÿ…gðÁ½=—5ï:’RžÚ޳%¢åu–e%³Û´Œ¥"5EîmÞ]P‘Û<9¸vý^y-r°òÓDJž©Þ0SîÙZ#mGÉØöòW¬§£ÏNºíõX‰ »n ßCõ±:]HíJ!ù—®›ï³Y¢â‘àÙi´E UlåRšW™˜<ûÊeÛ'–(€ÿ—–™Gm4“}ýÍV˰¹'O°þïÿb1>Ë>ŒÁƒÈP(éó.ƒÝq…•™WcŽzˆp‰¸^U“‹Q‹·'j¬ºw$ßçi9RjpTüœÌ$¨V·@Ö2 ˜£=º”fAñGÜöÈ<–˜íf…áürÌRž<¸½ÐÝÝ=œ¦øtSÙ-Õ9é$A\Ì'©—ô4åˆéYÍe'LÙ-Õ&P±˜w¸žZ}ß!lR7~ßÞµñ®%4ãj&™üV ½ë;~‹,0N0X½ZÏÕ.z0ÀU#,øg³vìqçš'®IŒü¼Nò¤ß «üî« ÷:F"yÒgv¥ÜM—8«Ã‹åŠ«Pi:mkù•;é@‹!¾ý±Gí#ç…&*2we¸%U¾MÜî“Α¾%ê ­ ­Ù­Áw=¿Cà]¬ìN¨°Ù„ åεÈäìo:·Ø(_Ù„°’ä\Qk_,J%õ¹¤?_•ìÇûÇÝ6i‰Ïð,>÷Õ­sr$ß)æÇàÖ%‹GÍ7ðÄÔ‘âyŽNîÍ( HæY÷Ú…¯©gUޱtc[n°Yõ’ ˜ûÄ¥ âÌsãßu»¬ƒü#KµC¼w¯?œÿÃéã9²9“~‰5TVÞ$Ÿpp!vºícmD·M‡±Édq¡iÔ¹œ¸Iñˆz†ºÞÄ9çΜ)½Zé¤Gem„ àë§Œ‚›=26RkDž'Àj¥¢±Sw_ "üîòÙÌüëÈ}œ¾™£2¶æ æýÀ—kóÞ0»ÒÆ =Ýc0ZoܚѳÊVÕ=ï'Y‰}“un8öuIòÀXCrMÁ ±ßÒïãL.†åR+ã}ö‰ô•Úµ ­«}ÀÉSgÜõM´Ñ˜úù1§Ã3¾—¢UÛ$#Ç?™w S´"¥º•veÃùIµ…#ˆ¿ÊͶ‚w1¢³«Ïcï½z;KÕSª<Ö+ã”ÈÕÔ™þÛ$Ø!¤Rî&è‚Þ£ƒ'ãëìÒJìžwÀò/ Šå$иébf!Ÿ•ZÉËç‹’Ý4%—à­Žd«Ê®²ù÷ZÒŸeì˜tÎ/8ðxm9ÚwgÕ>ÃD’KeEM|ob®} ÛoWs÷Aq™@„­'ßYÞ•Üþt4”§Ù˜f®Jq>ýñÔÙ—I¤ð‹ú§Û9©m¦¼«>5œ9ôÇña«™Šy™ÔΞYJh/ûY˜¿ôHÿpØx÷tMÑe^îÔÅרüÞâSñã˜É^¼}Ž«ÍhyQÎN]ŸtÍŸ`D÷P k¾£w¹ž®8ÏËUýqǦ—NJrDZR« jÌleš–Б—s˶»„Æ7XÉ¢l…C øO‹ ø›²›7{î«9:‡g˜‡¹&á{[ß\Yˆüd\ÃÛŸšý·Üµºaß—µazÿ²A·¨¹¸±Öfõj~ʤ пxœzfÀäÙç†; ‘¼ª<©ËˆÈ+Ÿìôj»îˆÜ *ÔÊãÊgy%ŒŠ*Ý©r­ò\rxÕ­Ä3Zov–›•W<˜hn“ˆpl69¿ç—)ûˆ—ŸT<ÐÙ&Èì1ÓúzŽç‡¤&ŠôÖ¨ë*uz®Ü£ã}3çWaõõ‹­ '|FÎ:c­47`þ4*³°2åp¡àUŸÊ«‹.º‘båžÒ1S¢%@Âç²W&%Y¢ïÛn¼kƒ¡å]ØvGѱ+ôˇ·öƒ/Ì{œz¾ãÆÛ „²þý„+Õ·¼þt÷èûk)\ëÍS`cÐ3¢©þI„¤ön¯ÑŠ®S'è€úªÀµéʹ£NEgcÃ}ªÃÔ'—W+bš]øƒ÷ T]}/D› žôg±„žZOwÎJɰýÆãËt"Š¥/<Ëæ¯ ½Ã+^ånL²^ñ Ó¤H«Ï¸§±­'¥A2.øò<{ê1–S¬Ÿ¢ggu>7ºü( üN”¢ÜÊI»RXþОV/$.DÊÏVX ^´sЋÇ×Fi¥ÀZ¼WÝø§óä.Ô®]ŠYñBbŠr ^ØbþN,é·žßû¨{=‚M_\å²B-ÀÙKÝ,]³Pîf<ÊŠê×få‘çzR†wxÈï±Vðroç¸|æÓ¸:ûg¶ëtŒë¡ú‰tQ¢*]bÕo.>ò{óˤe Ô$vñ¿|ÀÿOð‚€@ðt&-OÇГFßþ…þ/â-Ùìendstream endobj 9 0 obj << /Type /Font /Subtype /Type1 /Encoding 642 0 R /FirstChar 46 /LastChar 115 /Widths 652 0 R /BaseFont /RJSBTU+NimbusSanL-ReguItal /FontDescriptor 7 0 R >> endobj 7 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 /FontName /RJSBTU+NimbusSanL-ReguItal /ItalicAngle -12 /StemV 88 /XHeight 523 /FontBBox [-178 -284 1108 953] /Flags 4 /CharSet (/period/zero/one/two/R/a/e/l/s) /FontFile 8 0 R >> endobj 652 0 obj [278 0 556 556 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 722 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 0 0 556 0 0 0 0 0 0 222 0 0 0 0 0 0 500 ] endobj 5 0 obj << /Length1 1166 /Length2 8495 /Length3 544 /Length 9311 /Filter /FlateDecode >> stream xÚízUX\[Ö-Ü‚[€‚»[pww— §ªp‡àî,xp w×àN€ Á‚4p9§ÿÓ}ûtß§ûv¿»÷Ã^kŒ¹Ç\s¬¹v½ ¥š&‹¸•³PÆÙ ÊÂÁÊ.P9Z¸A4Í”X4€6n€Ç•†F uþýBH‚æP³“”9ô…ײu(›ƒœìvAv~AŽ—1;×_Î`A€äèì PB`Ó %åléæt‚jº¹¸8€€V@ˆ³ØX¿¬ì?³$]¼À [(€^[C—‰‰ù_‡€€ÀÂë/ „€lœ´/w ƒ³Ë™^$dN@ðË¢­þˆU³6—¶Aÿ(@o …º²±¹X›_0Vˆ5«ÊÆð²Pi'+IgÇ? ¨x&-_Šòbû»oöNÎN>ÿ[ƒœ¬þ,ÉÊÍ…MÛ äê”—úŸàõ_˜  àaçd`ç]@OK[¶?Rjy¹ÿ$9þ€Í¬ü|\œ]Öæ Èøò@õ˜»P°ÐÏç'þ}†ÊÁ°YB@›—mø—ú ´þÇ\Ù y ÙYÙÙ9ìÜÿ¿l¨•³“ƒ×¿ÂUÌ6Y-u %¦¿×þÏ( çI>n '?ÏK§¼( ðpý]ñŸ^üåߨš9èÖÉþ/Iy'kg€À?Êyññ¯’Ü`ÈKoèÿlcÀ¿ë«8CA–@ý¿ZLj‡ý¥k^ÿµ¥þÿ¯õ÷2nºBÿ;/~@J€?q0ÿG¸¹#ÈÁ뿼ð÷@]à?ºÿÿ #5wYŠ;Ù8üÓ&Dä ´RA-mÿÑ.¹lõç9ª9C@œd Çß8-[¥½yÙ‹?) “ÕßRJ;Y:[œlšÐ—®4[ýøƒ¶tƒ_ìùsƒ^Þýkn zY è ´D]^p¶zoWÿ¾ý¶VœÔƒew’«Wû׳7j¬ì6+\¯ ‘})wþ5jŽ”Ú˜­Hµ!¼2ºÂVrk(]ÓuÈÇŒÕ;ˆDŒŸ_£Òí‡ì_±$,dÃÅŠS˲Q¾‰oƒ*û Òþ„_R÷mUÎØïÜŠVsàP¥ÙðûáÆ©*UQ;hmâp WaBÚ¶:‰K«K7‡® ÍŠ…>kØŽ'à¹I/Ïç©ÓU¥)”8ž~ „°Õd3wcZ­@iè<‚7aÖN=âzà8´‚õ(ËlúÍÒÃè.³øÅ ¯¡ÆõC„á¾…GB?’ܲ*gôm’Fž¶›#.h «=ý¨pß5˜ôÀíÇ0]ƒd +>7-ÊC²~¨ë à–ó˜ïWüæ$ þß_.¤àÚ¬+äÓç=„¨MÌ~˼EÓ­<>*ÌÒs„)E‘]¼]ÙÅF'ê‘dxŸÖ­hïœZ¾‘Û®—$½Ó/qtEØGíD4%e®Ž–‰N q“WX0º™^›…Zà /|Ì•a\ÝóØ»V» dÈʬmbÍD%{‚Ãûà”ƒJ0kŸ:2ö ïÞÿn¿;&JÕ•Ê.•YÝj/JŠ[±/«*ë7gY1~¥±½i´\oÿ,é+vëŸp50ì?1@Ïù‰8#.î]wj’±}>„lU%Æ]è0Ge…zu‘·è‚ÚÜä Ÿo†ºEeåÌ|jÚž8:M(:jý '·1ûž4ž3íôëïófÇv-êó˽Y›Àž½&b·J³¢Uáój3RàQÖÝ¥ú2¹Íã_YJ,ªy¢´•>çÅT$È)ã¥kê–·G6¥æ`vLÝéÖ¿ H9Ö•lû¨Šsq7W…)**(…|2?^ˆcmÏÁ¤‡¸!aìæN©c©I"•ÃÇY‰X Œ øE¤t™n‚¾ßIt!OU ìÉJ~hÚuXé÷ùÛ}¯ÂÐ'wª¥ûÀ_‡¼j5&,öIàü¢(¤õàÆÕdkß<`íÂ5JnÖ‘óÒ?Š’¯y?»¤;Ô«S~Ò·´:ƹß{ï[å‡h=ë¯ Th@J‹›—5óÙzV¹ ³)ŽJ÷ä´º¡ÍM1,Ë€Á£Á³"³n6³­yÀ QêÌö=oõ¡¾Ã¾lÆà0“ŠYÐí ¿IE ?À¤(bÚ:úñÛ ^>9à½ÉM¾ž&CKõ¨t7™§Å£ë®ê¡æÍA°¶ÙÕ$hx¯c-šr™á÷vDŒÎ5õ4ïø~#k¤ØÒœ«Øú¾žè¤ Эáü¿§ƒö6³9:ôÉónÊ׋oÈh\?G@åG¡ÒçОÔJrŠ=½ã ©êžAœÏo¼’È[-¿ïua|úM­GÄXqÇPvx± ñÖ ²r+Œ,–bZ“Y²ø5ù¦dpiôÊHŒ"ŸÇK|@-´âéÛ‘`^®ÿÍGì2##°ÎÑïÓÕñ—YCœÚ³6{4¦ÓQ‘Zgs¥—CëX4ÔJ0ï«&ÞÑâSøÆ³ÙêˆT¯NŠÉOøI¤R†ïAY÷cWæØÂ¢Â"ðk†¯O Ý{;éØP`+q W ˆ ‰úe\?kža…#„y»À*Fs)”[˜aÞÖÛøLr ‘y¸øºð4ƒpI$¾‚Ä Í>„J;¨ŽŒ!°|:OÅöÒùÎ.Ž¥ÿ ‘ ¡È((£¯ÇAn¶b^PL ¿=C©¤ l¹²¬R¸“ò5\„“;xñù*Ä|âñÉœ$µdƒ‚ª¸rÅ?jÑD´ÝfÇa¥)ÚðMâ]S‡Ñã6Nu±qåoºïÏÆÄDB»y,iÙÇÛÚzˆ-3ÅXBQ¡“§8Ì~|‚Tó ?ŸŠ„£ap]NRŒµñfáaUÝ´ ]§¬æÁûîÚ~fctÎúå¡rcKo[oIf§ô´œ9ç¯v&JÃ6š’·¾õz³/YR.ƒ|®ØÍ—Hå«Û –0 V©5‹"ÁäaPØ›eëxBÑfûÒU&^ÖT°3?À–²[¬÷,g|¨üŒ£á ׊Ø3¦}²Ð¢ð)gý^THùÆŒMkÅ¢¡Äª„PMÀŒ*æú¥kæų3ÑùLf>sfŒA‘|·`‚è\F>i&Y[ÊSèÊÊ4ñ >¸¶ø£îé°[ðMÉ©jìd›†ñ7½,á>–Ïß#´Y·=­<»}Äà<—$0ðäY½ÜÇ Ft\\¡‘†UÍ®Jô5ƒ\ƒ€µqZ¶5c0ÆsOU €?ÁÿÝ9ß±ÙG]ôñ¡Ÿ»:‹˜¼^v2‘û–óΠÈèq¨ÃàEÔ¼"zu–ÛÁ¬‘lulMQ“9ÕJÙd®‡OÕÕOзíáƒ.‚EÂûkI߃pDkÚ:”¡éÙkµ÷ZâGš–}Öš\ånTD£ÚÕ†ýk»éwrM$!”ƒYí–åû«iÖ++ÃîkIW„õ8Ýdßç'*At4œá¿õŽ*U߄ٴˆðFq0¹Æ.iñŨúäcÞÿÀœœÝqF“p+aÏ!÷î~ôC‰ji1žSúÜP¼ö7})‘**¸ZIßáœ(6ËÇ÷Že…$]Ñ­@m6Ýx³ð*°òꞈìÛkÙ¿ÖG`kZÊñ°Œq©L¤f‹ºã<ú*nû5odt•é=DS 7Ãi¬ú¨×ªÖC¨êüîb#d1“–‘Œ³·,Ép‰R޾ßÞÅ×9 ùö«°Ÿ‘9HmqÖ rª¦E¿Êû²¼¶|ÉæõšÕºŸ7È­9“I R‚ËÙ^H5bÁWØC ‹8ñù†ÕVÜy AZó[ "Ž0¦>mÑWß§›«<Û Iur™®3K­‡ï¡Ò€26®z LOq¶Ê@d—û­Ñrôi1ê®B‰ó¿J}Çwú·§Zé'O½Ü¤µfhom)ݲ™Oª…Ú>&‚ïѾšB\Ö¿EÐ^”t›ÊÁ¹GI.b¶C¼¨œÈžå¥:Ý—ø¢4+™°Ø¥„³³”*åÂQ.6›‡IûªI+ÁAþl£ˆ¬yM8}êŠGT¬ßÓ(^K®ÙHæ7#÷Möœ*²ÔÑL#†ÜÌöXëÙääh…}“±°†wɸˆÃÜ,‡ý6–Ò'c˳ÛWü‹ŠŸ®-X[4£í@bÏ"-îÀ¼à|?^Æ%MëÎ^ª6=ëØ#p^és ÁRHyapì(íºåÈ4Ÿ^ã‹Zõ¾Ú]½h1JWªS‚òþ÷ÞÔþ€r7zª¾4"‚óiºel»òrV¾|*§Y»È¯›ITI™îoÒyfZf^½f3¯´ì ¥'誃cža3˜<ÂsgØu6åúøëçmrÖ«Ǩ>E¶û©Ã:ÙîéSþ}3”Ũ€¹Õ&çYöòoꢾÚ¢j@Öù~ÅN9É£ÒÕ·Ïß§û\ʸ÷š™n}àÝñrõ‹Ñv »ƒí\ì •ÝÐÞ‘z{YàE´]|õ°ðîÊhXÏü-¢¶>ÑÆWv·B”l?,QŽT¢4SkÁ£6Åü`ÓG0m¡^¤ªë3ä7D'/¶ð›MÎí¡-ð*^qORYAÒ¯Z•GR•yë²Í‡uÔχŠ_§¿w«ô÷¦Á ‘Dl“H§ôáì­|\¡HTøœ˜7‘KT¡ÄÀ\¾0$èµ#…ï÷b†ñMJÝÕŸ,^B›t|ïŒd.®k8 ŒÜ’X:3í„ïWÈçªåfxz„^ 'äL}” KRÿq›Í9 ÙöÀÃ˼ºj«ç+TÈW(r¥¿â´¹* ÀÞ$±ýþª_ËûÈã@\I:ï餆'ž(3Ùò‘é¸'žàó#°´‡+N:ÆQF2;‹ÑˆgRúãm”ô§W2ì]ri=iãQÃNx¹)J~çMUí½ƒÝÝ>c+µŠ'ÝL^ /ã×–núR$õNN‘Š)ã· é«©8V…èÕq³äçÎ"wˆ4.€ë›.ôÝ飪òm;S …9Büߘéà¿£.{nÃÖP!À;ðèRÍ{LS·ýBGçQÙÁ:frïËCËuòçšk›žªœ'mb·Œx^|½³ò¹L )£çÒº0îCàчzÉcr>Ø —­Œp?«u=g»–×ÞEäââɰÌÓ¶4£ÆYåÞžL¬¤ñ¼O+É8vío1ÒŽ"W~€l /¸ùä*NÜÑÑ ¡E OÖN,¦¹¶¸=梮ù~4x­œfŠ6NòBn ¿†*2±¬>%LM Þàý†Ì“ÜÕÑ#¢ä[ ‚F ¥P]ƒFˆ[Ù×ûw»u|ô‘6åÖhàñh ûRD(w†­_)SAí¤JUƒ¦­Zµ÷†Æ…ŽÇáNµ7òÑ ÂÕsõ3òõˆ£ªDS(‚)Çf:R¨6S[IîøIÍþ)½çÛ˜I²*ÜR”2·¯_´Ç§ Ê$J9; Ï^QCn„·¾Ã[‘å°„é™<ž–™Áà:TrBWÝWuØÇ$DHWE_€jo,„Šp¥ºÒ"’¤V¶d##Ù¦5ïrÓ¬ž=¯uƒÑqNZ…O¥~C»q†fÛ´½(¢W†»¼,‰È¥ìg¡ÑÒä©-)KqO2¤G‰§#FqPÅW.£o¯Ôz‘a ,¯Â–”ôò”Ô9Œå•Pñ®Ê¬+/!¿_«ßyŒúú&%Y/"’\,kÛœ&ž#Nrp²WÔ'‹&dœÃY¾BX·Èü¥yC!¨–66)|,”d²†}öÞ!—G( F"*ó™%€˜âa‘¥ž8R¾\yßÄæ2ÊŸ9̼ g GR¸—¾¼P„›Ê˜›—N31i\Ó_‰–áV+’ø É:â# àÞd^6¯÷Éîg2¶® Cb[ \Õõ×õw(är ”ήoe&Ü1Ôã#.TUEÓ*ªKª"ø¾S®àI**ZU?mðÇu ß Ó,Þ‘p)Áfë$½}‹ú†ë”7{j~É»‰8Ã[Ü¥?Š¡¼è'³oÒ[äæ+ßæ*Ÿh6åhšUzìg†òµ†©¨¾Éœô6RÌæ§*€gC ƒ*‡g•×¹®I&q.ìé& ¶é;ñÉO¾ »{|j!âÅ”éäÆG¡Ñ$}{á÷ŽÙtº?83ÖiÔ‘+ LÎôl[tòë;-ÃCüWhó¾Ï…‘y& -¹WÓ1X¾F§`ÿœÎPÒñcM›³)óÕ‰Œf?J0ÿA,{-#¹uªÊ¡2 Ù>3s – 'hlB²†^9kœ=u¦Us÷(ƒÁ³õŽ¡Fuù±]ªEа5 šïK’l<[´ñV*.Çõþ™Ùi¦AÁ'sÂksž±$äLCÂâÎÄ$‚s,OU†L ¾ÍÅ0&ÖÓâØR Fp|À×dïü1^AÍY÷§«MKw‹vHì¬àØÆ¦h$§[ï®YœëÐÒùS `0^ë¢~ó¨p~¹˜bÂXG6r9Ÿ+çTöº®LÓ)4¡éœë°±ÿJék±ü÷Cì¸V,Õ÷þe©T!­i!qñb›ögÓRF¤¾#7:yŽÐ÷ Œ\˜ 0¬ÌGÍDaö¬SÓ)­Nòœø1t蜂Ô92'œúb»ýA±Zò~ÔŒ–Ò’gþ»*‘—j2U$Þ7yÐL Ž$Íštc¿Ý÷éóÐ $4¡|œ|×cªºGX>õ\jÈ\i.eüWÁ¤£5šAPŒgU+èãeRÉ`ÐqTÚìœß ð?”*e¾G¦Yz¿šE:îu„»¬¯yÒŸaj¶&bdÊúÒn:ý‹Ë鳿ØåÃc-D§(àØÛº.±ëq– k|ܓ㫖÷ý«êGÞB{BÎå'Q.ŒDUAŠ5­­ÑP>»BlÚØ ÍN7n¢²ŽRN'.W½¦3òxl:é˜&–$ÄÈ‹ñ )—:óéYÉk’Ü#Z'í¸t2^ŸåÞY»#Ý×Å7°ï³~0ü/Ö1T2ö!¥™[2¼QeÏbU«gÕ´Ãi.ÀG3N º¨éÑš´’ä!ØÜÜ[Mç©ÙÔÊÝêUNdJÔmN«Æ'ˆãn¯gþX 4Ñv²%J{¼-òÝHþèôÿ©MzòíFÚ#R® P\×ø¥ú ›Ì“ûœtœ<ÅÂïzÖdÙ"ðyP.“ LXBm²$:/è…uÒOü«)mô‰ÚxÏÌN‚rú3ª3B«Kd‰”aÊ•ÖÏó~ü0Û¹8t wî·Îù©xE‡|‰3(P¬øÙ™1øíùIKÊSOhJ.âƒ.ñ–Ž9°ôRkjÖÚø²YÆ¥§¢;¤š÷ÖÙ}em÷/NØñàÐøõå@¦êöÚÄò\C­™ÂuF6<{§vè)¼•d˜œ@Žézìð¦ÅHÁá„ óZë=2tq}‘rUÞz!‚O¬õ¾Hüû¡°1Âzäò}Lô'â„&2æÆ8!7ÉÕ¢Ê(«ÏÃÇ$Bn· ‘rÒ¶úŠG‚àOòí~ê,íðPánpÌ$±ˆv]=i#yÅÂ|zsbdŽÄ@t@ú T·¨á$`ÞÃôƒ~òéPTz©y17“/I©ðžÆÄx©©R[î©mh¯T q´€²¯Ø¥;÷Ñ8jHøU‘\ùtå½™ÝKIÖ#ëý2!±>Í·p¡¬ñ‰ªmIUú]†ÉaBxâÌhå÷_jß`Õ#J…æ#öH÷Xú×Î(âãâ­ï%"¬§æ='’“8P9ް÷ÐÒªææžDjRiô$$…œ,Š„TË-5~qdV'óå㛥ªXW• Žxˆ:õºû‘~s3ò¶tx›àÊ&šD£B¿%BÄeÜ-iI…íìm#ÙÕ½¢m‚.…%7¦ŠàÈ2‡æudVM„êDT_¬ï`+µ)v¶ôŽóåWÖ­›½p†}ïíFj[U­=©e ¨ò‹Ò5 óÜÛi¢]î9ÏM+¬Çí@Zÿ`bÝ;˜‰Ê$`1óãïÀ±±NTB^ûä}Í™ÝÔ6Þ­ŽÆ:V™¦ nó–sâz#Ãgxš{×y ¬™F‰ûÃ3Mkζåm E« êÖ ž_2"éÃõnÃëjÚ–Ð Äz¾ÏtY—+p=Î+S[ fÒŽOWÊ&†Ø*Þcï ܨEìe‡jñ·´c:píS=íª\†ýpMçÄÕZ ̳ÚY-–ºÏjÔI„Ù ó-ÌlŸ- J‡Ô»$º¿tV#z÷‰¯—¥ØuùÛ#<\+N»ñëãÆ{wÝc„gUµMºªj3øsR.׌=.^}¢ãî™uj@(«z»%ËÁŸxõ+q%4%ÒÛ!ËœqMÒŒ¥ÙôŠŒ­hcIui^`ã¹S9_’QODF9w¸OC}Eïþ„)_æò%ò$¯—Gå*à´Á8æáÓÿµZ‚L*ì’Òð.â\º@¸âÇ©W6œÌpûth$WK€§`›aqê‘ZlÔ‹TiäÆ{Ý’¡6m5=N­)o;ÕGѪôýÚ™Db?:M§½o±Q ðtíÜTZ¦ò` ÕY8VScËêâ¼§€‘y¬qe¹–Û‘if(;n»ê·uÔÖ7t͑؜¦«Á^qÜÍÃK ŠÎy${b竾iTDl¹´cŸK:ÓK*)§–ûÜKJ_R4 m?cDÅP•“pÓ4 ´™án- *Ø Î'EÜ8¸zû7HíÎòÖ„T±<“ î”L¼ÉÞb{>µ×"êþ0s9&ðúcnM’ì†nº¿‘úžã,8¥~‰Ù¥Nþ!ŽIs=Y¸@K㇩év¡ŒB«»ÝÕ§\ Õ¾Wâ¥ùm(=ÿÃG%¨bZ°µö ZÊgž†×ζ^z-ߟ$¶*GGyUÖó½ zàî‘ï3ù YÒÖ›¼D|ß[ƒh\rSž>Ç1Å î‹¢%¾RÄÜB~èˆüë]üšç–­¨®W”ßÀGt€'}Ó§èsm¡µt]~šf?Ѽ`ùýRæ„¥ g!qÐ;œŽëa ÿb¿?i!ù¥… „Q.ðäY?Ãù¨c!A¼¥\k¡Êb¦1±éAuG¢ôüWõ±dܾTÚ¸ÖJ4Þ½h0BiÏ×]p:XÃîh"è36Ó¨ŒìbLAf‘4q”ÇH?îw_£ã§Dsù×úUÚoÎ/̤&Õ—9j¿!3™Œ°óÖ=®ƒÕ€öM#Ý©)¸6‹êór-Ra=9¨egŸ1!Æ:zÒãM£}tAAÈÚ”wih½É7 çñYÉn…h„Yv }Õ=¬îÁ©Ø²¢¸Âñ(Ho(¼Ïï–º8ؾ¢dö¾'Ì-Yz?–ûM‹äþô+Íèû —× ÕBæõ fâŠ?§—6ç¶T ôÁ·zD(‰ÜOÈr6<ÅlÃÆQ¾'4V7·­¬g­?\/b]¨^Ã.ÿ›çI8阨ïœÒ· UP…2dÍ>X”È +‹?7¯ ¶)ÿ9E¢…Õ~3ÛÓÌ„¦„HÎi\4pÒ~}$G™Ò|²õ°QÑ…*ä¿Ú^0Ý™Âò6l\kÃ@ìÖåÛ;ùI.›,­_ó™Ë 'L´Ž'‚?Db¸ œÉï‡èf¾®ä ¤;"CxUâÈà~ÿᓪSZÒ£îw3CŠ×“Ž’«vÒR»æK(âñŠuS|·žŽ!1ˆßO {F½“`FãSê,@aeÃîÔ™½ßábÆ-%Š®…Ûësoäì¼ðñ ]âÞŠËg˜1£„8oܲÞ{N]jÀÁNéLÊ“Éës~Ñn*ȳA˜±Šš¡%,Qüy X¤CÏ >ûz¾Nº ¤èUäüd8‚E`oâô•`ÖF4¹–í7%* ¼,ª dwø28!Úþ,\ï_ f±;#Íwš=L޽Q]*"½¨,žE2wðAõ!*æßÎ|Rv‹6B퉵RdsÚ_9*#¯ÜcN¬[DCƒ9%> endobj 4 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 /FontName /GTQBBL+NimbusSanL-Regu /ItalicAngle 0 /StemV 85 /XHeight 523 /FontBBox [-174 -285 1001 953] /Flags 4 /CharSet (/quoteright/comma/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/colon/at/A/B/C/D/E/F/G/H/I/L/M/N/O/P/R/S/T/U/X/Y/Z/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z/emdash) /FontFile 5 0 R >> endobj 653 0 obj [222 0 0 0 0 278 333 278 0 556 556 556 556 556 556 556 556 556 556 278 0 0 0 0 0 1015 667 667 722 722 667 611 778 722 278 0 0 556 833 722 778 667 0 722 667 611 722 0 0 667 667 611 0 0 0 0 0 0 556 556 500 556 556 278 556 556 222 0 500 222 833 556 556 556 0 333 500 278 556 500 722 500 500 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1000 ] endobj 13 0 obj << /Type /Pages /Count 6 /Parent 654 0 R /Kids [2 0 R 15 0 R 27 0 R 36 0 R 39 0 R 97 0 R] >> endobj 130 0 obj << /Type /Pages /Count 6 /Parent 654 0 R /Kids [124 0 R 132 0 R 138 0 R 141 0 R 145 0 R 149 0 R] >> endobj 155 0 obj << /Type /Pages /Count 6 /Parent 654 0 R /Kids [153 0 R 157 0 R 161 0 R 165 0 R 169 0 R 172 0 R] >> endobj 178 0 obj << /Type /Pages /Count 6 /Parent 654 0 R /Kids [176 0 R 180 0 R 184 0 R 187 0 R 191 0 R 195 0 R] >> endobj 201 0 obj << /Type /Pages /Count 6 /Parent 654 0 R /Kids [199 0 R 203 0 R 207 0 R 210 0 R 217 0 R 220 0 R] >> endobj 225 0 obj << /Type /Pages /Count 6 /Parent 654 0 R /Kids [223 0 R 227 0 R 230 0 R 233 0 R 236 0 R 239 0 R] >> endobj 245 0 obj << /Type /Pages /Count 6 /Parent 655 0 R /Kids [243 0 R 247 0 R 251 0 R 254 0 R 258 0 R 261 0 R] >> endobj 267 0 obj << /Type /Pages /Count 6 /Parent 655 0 R /Kids [265 0 R 269 0 R 273 0 R 277 0 R 280 0 R 284 0 R] >> endobj 290 0 obj << /Type /Pages /Count 6 /Parent 655 0 R /Kids [288 0 R 292 0 R 296 0 R 300 0 R 304 0 R 307 0 R] >> endobj 313 0 obj << /Type /Pages /Count 6 /Parent 655 0 R /Kids [310 0 R 315 0 R 319 0 R 323 0 R 327 0 R 330 0 R] >> endobj 335 0 obj << /Type /Pages /Count 6 /Parent 655 0 R /Kids [333 0 R 337 0 R 341 0 R 345 0 R 349 0 R 352 0 R] >> endobj 358 0 obj << /Type /Pages /Count 5 /Parent 655 0 R /Kids [356 0 R 360 0 R 364 0 R 636 0 R 639 0 R] >> endobj 654 0 obj << /Type /Pages /Count 36 /Parent 656 0 R /Kids [13 0 R 130 0 R 155 0 R 178 0 R 201 0 R 225 0 R] >> endobj 655 0 obj << /Type /Pages /Count 35 /Parent 656 0 R /Kids [245 0 R 267 0 R 290 0 R 313 0 R 335 0 R 358 0 R] >> endobj 656 0 obj << /Type /Pages /Count 71 /Kids [654 0 R 655 0 R] >> endobj 657 0 obj << /Type /Outlines /First 368 0 R /Last 602 0 R /Count 15 >> endobj 633 0 obj << /Title 634 0 R /A 632 0 R /Parent 627 0 R /Prev 630 0 R >> endobj 630 0 obj << /Title 631 0 R /A 629 0 R /Parent 627 0 R /Next 633 0 R >> endobj 627 0 obj << /Title 628 0 R /A 625 0 R /Parent 608 0 R /Prev 617 0 R /First 630 0 R /Last 633 0 R /Count -2 >> endobj 623 0 obj << /Title 624 0 R /A 622 0 R /Parent 617 0 R /Prev 620 0 R >> endobj 620 0 obj << /Title 621 0 R /A 619 0 R /Parent 617 0 R /Next 623 0 R >> endobj 617 0 obj << /Title 618 0 R /A 616 0 R /Parent 608 0 R /Prev 614 0 R /Next 627 0 R /First 620 0 R /Last 623 0 R /Count -2 >> endobj 614 0 obj << /Title 615 0 R /A 613 0 R /Parent 608 0 R /Prev 611 0 R /Next 617 0 R >> endobj 611 0 obj << /Title 612 0 R /A 610 0 R /Parent 608 0 R /Next 614 0 R >> endobj 608 0 obj << /Title 609 0 R /A 607 0 R /Parent 602 0 R /Prev 605 0 R /First 611 0 R /Last 627 0 R /Count -4 >> endobj 605 0 obj << /Title 606 0 R /A 604 0 R /Parent 602 0 R /Next 608 0 R >> endobj 602 0 obj << /Title 603 0 R /A 601 0 R /Parent 657 0 R /Prev 572 0 R /First 605 0 R /Last 608 0 R /Count -2 >> endobj 599 0 obj << /Title 600 0 R /A 598 0 R /Parent 593 0 R /Prev 596 0 R >> endobj 596 0 obj << /Title 597 0 R /A 595 0 R /Parent 593 0 R /Next 599 0 R >> endobj 593 0 obj << /Title 594 0 R /A 592 0 R /Parent 572 0 R /Prev 578 0 R /First 596 0 R /Last 599 0 R /Count -2 >> endobj 590 0 obj << /Title 591 0 R /A 589 0 R /Parent 578 0 R /Prev 587 0 R >> endobj 587 0 obj << /Title 588 0 R /A 586 0 R /Parent 578 0 R /Prev 584 0 R /Next 590 0 R >> endobj 584 0 obj << /Title 585 0 R /A 583 0 R /Parent 578 0 R /Prev 581 0 R /Next 587 0 R >> endobj 581 0 obj << /Title 582 0 R /A 580 0 R /Parent 578 0 R /Next 584 0 R >> endobj 578 0 obj << /Title 579 0 R /A 577 0 R /Parent 572 0 R /Prev 575 0 R /Next 593 0 R /First 581 0 R /Last 590 0 R /Count -4 >> endobj 575 0 obj << /Title 576 0 R /A 574 0 R /Parent 572 0 R /Next 578 0 R >> endobj 572 0 obj << /Title 573 0 R /A 571 0 R /Parent 657 0 R /Prev 551 0 R /Next 602 0 R /First 575 0 R /Last 593 0 R /Count -3 >> endobj 569 0 obj << /Title 570 0 R /A 568 0 R /Parent 566 0 R >> endobj 566 0 obj << /Title 567 0 R /A 565 0 R /Parent 551 0 R /Prev 563 0 R /First 569 0 R /Last 569 0 R /Count -1 >> endobj 563 0 obj << /Title 564 0 R /A 562 0 R /Parent 551 0 R /Prev 560 0 R /Next 566 0 R >> endobj 560 0 obj << /Title 561 0 R /A 559 0 R /Parent 551 0 R /Prev 554 0 R /Next 563 0 R >> endobj 557 0 obj << /Title 558 0 R /A 556 0 R /Parent 554 0 R >> endobj 554 0 obj << /Title 555 0 R /A 553 0 R /Parent 551 0 R /Next 560 0 R /First 557 0 R /Last 557 0 R /Count -1 >> endobj 551 0 obj << /Title 552 0 R /A 550 0 R /Parent 657 0 R /Prev 518 0 R /Next 572 0 R /First 554 0 R /Last 566 0 R /Count -4 >> endobj 548 0 obj << /Title 549 0 R /A 547 0 R /Parent 533 0 R /Prev 545 0 R >> endobj 545 0 obj << /Title 546 0 R /A 544 0 R /Parent 533 0 R /Prev 542 0 R /Next 548 0 R >> endobj 542 0 obj << /Title 543 0 R /A 541 0 R /Parent 533 0 R /Prev 539 0 R /Next 545 0 R >> endobj 539 0 obj << /Title 540 0 R /A 538 0 R /Parent 533 0 R /Prev 536 0 R /Next 542 0 R >> endobj 536 0 obj << /Title 537 0 R /A 535 0 R /Parent 533 0 R /Next 539 0 R >> endobj 533 0 obj << /Title 534 0 R /A 532 0 R /Parent 518 0 R /Prev 530 0 R /First 536 0 R /Last 548 0 R /Count -5 >> endobj 530 0 obj << /Title 531 0 R /A 529 0 R /Parent 518 0 R /Prev 527 0 R /Next 533 0 R >> endobj 527 0 obj << /Title 528 0 R /A 526 0 R /Parent 518 0 R /Prev 521 0 R /Next 530 0 R >> endobj 524 0 obj << /Title 525 0 R /A 523 0 R /Parent 521 0 R >> endobj 521 0 obj << /Title 522 0 R /A 520 0 R /Parent 518 0 R /Next 527 0 R /First 524 0 R /Last 524 0 R /Count -1 >> endobj 518 0 obj << /Title 519 0 R /A 517 0 R /Parent 657 0 R /Prev 515 0 R /Next 551 0 R /First 521 0 R /Last 533 0 R /Count -4 >> endobj 515 0 obj << /Title 516 0 R /A 514 0 R /Parent 657 0 R /Prev 473 0 R /Next 518 0 R >> endobj 512 0 obj << /Title 513 0 R /A 511 0 R /Parent 503 0 R /Prev 509 0 R >> endobj 509 0 obj << /Title 510 0 R /A 508 0 R /Parent 503 0 R /Prev 506 0 R /Next 512 0 R >> endobj 506 0 obj << /Title 507 0 R /A 505 0 R /Parent 503 0 R /Next 509 0 R >> endobj 503 0 obj << /Title 504 0 R /A 502 0 R /Parent 473 0 R /Prev 476 0 R /First 506 0 R /Last 512 0 R /Count -3 >> endobj 500 0 obj << /Title 501 0 R /A 499 0 R /Parent 476 0 R /Prev 497 0 R >> endobj 497 0 obj << /Title 498 0 R /A 496 0 R /Parent 476 0 R /Prev 488 0 R /Next 500 0 R >> endobj 494 0 obj << /Title 495 0 R /A 493 0 R /Parent 488 0 R /Prev 491 0 R >> endobj 491 0 obj << /Title 492 0 R /A 490 0 R /Parent 488 0 R /Next 494 0 R >> endobj 488 0 obj << /Title 489 0 R /A 487 0 R /Parent 476 0 R /Prev 479 0 R /Next 497 0 R /First 491 0 R /Last 494 0 R /Count -2 >> endobj 485 0 obj << /Title 486 0 R /A 484 0 R /Parent 479 0 R /Prev 482 0 R >> endobj 482 0 obj << /Title 483 0 R /A 481 0 R /Parent 479 0 R /Next 485 0 R >> endobj 479 0 obj << /Title 480 0 R /A 478 0 R /Parent 476 0 R /Next 488 0 R /First 482 0 R /Last 485 0 R /Count -2 >> endobj 476 0 obj << /Title 477 0 R /A 475 0 R /Parent 473 0 R /Next 503 0 R /First 479 0 R /Last 500 0 R /Count -4 >> endobj 473 0 obj << /Title 474 0 R /A 472 0 R /Parent 657 0 R /Prev 470 0 R /Next 515 0 R /First 476 0 R /Last 503 0 R /Count -2 >> endobj 470 0 obj << /Title 471 0 R /A 469 0 R /Parent 657 0 R /Prev 467 0 R /Next 473 0 R >> endobj 467 0 obj << /Title 468 0 R /A 466 0 R /Parent 657 0 R /Prev 464 0 R /Next 470 0 R >> endobj 464 0 obj << /Title 465 0 R /A 463 0 R /Parent 657 0 R /Prev 410 0 R /Next 467 0 R >> endobj 461 0 obj << /Title 462 0 R /A 460 0 R /Parent 410 0 R /Prev 458 0 R >> endobj 458 0 obj << /Title 459 0 R /A 457 0 R /Parent 410 0 R /Prev 455 0 R /Next 461 0 R >> endobj 455 0 obj << /Title 456 0 R /A 454 0 R /Parent 410 0 R /Prev 452 0 R /Next 458 0 R >> endobj 452 0 obj << /Title 453 0 R /A 451 0 R /Parent 410 0 R /Prev 449 0 R /Next 455 0 R >> endobj 449 0 obj << /Title 450 0 R /A 448 0 R /Parent 410 0 R /Prev 446 0 R /Next 452 0 R >> endobj 446 0 obj << /Title 447 0 R /A 445 0 R /Parent 410 0 R /Prev 443 0 R /Next 449 0 R >> endobj 443 0 obj << /Title 444 0 R /A 442 0 R /Parent 410 0 R /Prev 440 0 R /Next 446 0 R >> endobj 440 0 obj << /Title 441 0 R /A 439 0 R /Parent 410 0 R /Prev 437 0 R /Next 443 0 R >> endobj 437 0 obj << /Title 438 0 R /A 436 0 R /Parent 410 0 R /Prev 434 0 R /Next 440 0 R >> endobj 434 0 obj << /Title 435 0 R /A 433 0 R /Parent 410 0 R /Prev 431 0 R /Next 437 0 R >> endobj 431 0 obj << /Title 432 0 R /A 430 0 R /Parent 410 0 R /Prev 416 0 R /Next 434 0 R >> endobj 428 0 obj << /Title 429 0 R /A 427 0 R /Parent 416 0 R /Prev 425 0 R >> endobj 425 0 obj << /Title 426 0 R /A 424 0 R /Parent 416 0 R /Prev 422 0 R /Next 428 0 R >> endobj 422 0 obj << /Title 423 0 R /A 421 0 R /Parent 416 0 R /Prev 419 0 R /Next 425 0 R >> endobj 419 0 obj << /Title 420 0 R /A 418 0 R /Parent 416 0 R /Next 422 0 R >> endobj 416 0 obj << /Title 417 0 R /A 415 0 R /Parent 410 0 R /Prev 413 0 R /Next 431 0 R /First 419 0 R /Last 428 0 R /Count -4 >> endobj 413 0 obj << /Title 414 0 R /A 412 0 R /Parent 410 0 R /Next 416 0 R >> endobj 410 0 obj << /Title 411 0 R /A 409 0 R /Parent 657 0 R /Prev 407 0 R /Next 464 0 R /First 413 0 R /Last 461 0 R /Count -13 >> endobj 407 0 obj << /Title 408 0 R /A 406 0 R /Parent 657 0 R /Prev 401 0 R /Next 410 0 R >> endobj 404 0 obj << /Title 405 0 R /A 403 0 R /Parent 401 0 R >> endobj 401 0 obj << /Title 402 0 R /A 400 0 R /Parent 657 0 R /Prev 398 0 R /Next 407 0 R /First 404 0 R /Last 404 0 R /Count -1 >> endobj 398 0 obj << /Title 399 0 R /A 397 0 R /Parent 657 0 R /Prev 374 0 R /Next 401 0 R >> endobj 395 0 obj << /Title 396 0 R /A 394 0 R /Parent 389 0 R /Prev 392 0 R >> endobj 392 0 obj << /Title 393 0 R /A 391 0 R /Parent 389 0 R /Next 395 0 R >> endobj 389 0 obj << /Title 390 0 R /A 388 0 R /Parent 374 0 R /Prev 377 0 R /First 392 0 R /Last 395 0 R /Count -2 >> endobj 386 0 obj << /Title 387 0 R /A 385 0 R /Parent 377 0 R /Prev 383 0 R >> endobj 383 0 obj << /Title 384 0 R /A 382 0 R /Parent 377 0 R /Prev 380 0 R /Next 386 0 R >> endobj 380 0 obj << /Title 381 0 R /A 379 0 R /Parent 377 0 R /Next 383 0 R >> endobj 377 0 obj << /Title 378 0 R /A 376 0 R /Parent 374 0 R /Next 389 0 R /First 380 0 R /Last 386 0 R /Count -3 >> endobj 374 0 obj << /Title 375 0 R /A 373 0 R /Parent 657 0 R /Prev 368 0 R /Next 398 0 R /First 377 0 R /Last 389 0 R /Count -2 >> endobj 371 0 obj << /Title 372 0 R /A 370 0 R /Parent 368 0 R >> endobj 368 0 obj << /Title 369 0 R /A 367 0 R /Parent 657 0 R /Next 374 0 R /First 371 0 R /Last 371 0 R /Count -1 >> endobj 658 0 obj << /Names [(page001) 74 0 R (page002) 75 0 R (page003) 76 0 R (page004) 143 0 R (page005) 147 0 R (page006) 151 0 R (page007) 77 0 R (page008) 159 0 R (page009) 163 0 R (page010) 167 0 R (page011) 78 0 R (page012) 174 0 R (page013) 79 0 R (page014) 182 0 R (page015) 80 0 R (page016) 189 0 R (page017) 193 0 R (page018) 197 0 R (page019) 81 0 R (page020) 205 0 R (page021) 82 0 R (page022) 212 0 R (page023) 83 0 R (page024) 84 0 R (page025) 85 0 R (page026) 86 0 R (page027) 87 0 R (page028) 88 0 R (page029) 89 0 R (page030) 241 0 R (page031) 90 0 R (page032) 249 0 R (page033) 91 0 R (page034) 256 0 R (page035) 92 0 R (page036) 263 0 R (page037) 93 0 R (page038) 271 0 R (page039) 275 0 R (page040) 94 0 R (page041) 282 0 R (page042) 286 0 R (page043) 95 0 R (page044) 294 0 R (page045) 298 0 R (page046) 302 0 R (page047) 116 0 R (page048) 117 0 R (page049) 312 0 R (page050) 317 0 R (page051) 321 0 R (page052) 325 0 R (page053) 118 0 R (page054) 119 0 R (page055) 120 0 R (page056) 339 0 R (page057) 343 0 R (page058) 347 0 R (page059) 121 0 R (page060) 354 0 R (page061) 122 0 R (page062) 362 0 R (page063) 366 0 R (page064) 626 0 R (page065) 641 0 R] /Limits [(page001) (page065)] >> endobj 659 0 obj << /Kids [658 0 R] >> endobj 660 0 obj << /Dests 659 0 R >> endobj 661 0 obj << /Type /Catalog /Pages 656 0 R /Outlines 657 0 R /Names 660 0 R /PageMode /UseOutlines >> endobj 662 0 obj << /Producer (pdfeTeX-1.21a) /Author (Rich Salz,, Christopher Blunck) /Title (ZSI: The Zolera Soap Infrastructure , Developer's Guide) /Creator (TeX) /CreationDate (D:20071101225915Z) /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref 0 663 0000000000 65535 f 0000000610 00000 n 0000000505 00000 n 0000000009 00000 n 0000268071 00000 n 0000258474 00000 n 0000267904 00000 n 0000258058 00000 n 0000253891 00000 n 0000257887 00000 n 0000252798 00000 n 0000233459 00000 n 0000252627 00000 n 0000268832 00000 n 0000002947 00000 n 0000002839 00000 n 0000000701 00000 n 0000232664 00000 n 0000217685 00000 n 0000232493 00000 n 0000217060 00000 n 0000215068 00000 n 0000216900 00000 n 0000214093 00000 n 0000193864 00000 n 0000213924 00000 n 0000004753 00000 n 0000004102 00000 n 0000003053 00000 n 0000004243 00000 n 0000193148 00000 n 0000178454 00000 n 0000192973 00000 n 0000004409 00000 n 0000004582 00000 n 0000005054 00000 n 0000004946 00000 n 0000004859 00000 n 0000011692 00000 n 0000007250 00000 n 0000005094 00000 n 0000007580 00000 n 0000007715 00000 n 0000007854 00000 n 0000007988 00000 n 0000008127 00000 n 0000008266 00000 n 0000008400 00000 n 0000008535 00000 n 0000008674 00000 n 0000177805 00000 n 0000161570 00000 n 0000177636 00000 n 0000008809 00000 n 0000008943 00000 n 0000009082 00000 n 0000009221 00000 n 0000009359 00000 n 0000009498 00000 n 0000009637 00000 n 0000009775 00000 n 0000009913 00000 n 0000010052 00000 n 0000010191 00000 n 0000010330 00000 n 0000010469 00000 n 0000010605 00000 n 0000010743 00000 n 0000010878 00000 n 0000011012 00000 n 0000011147 00000 n 0000011282 00000 n 0000011421 00000 n 0000011559 00000 n 0000019035 00000 n 0000021352 00000 n 0000023476 00000 n 0000031109 00000 n 0000035723 00000 n 0000038360 00000 n 0000043240 00000 n 0000051654 00000 n 0000057689 00000 n 0000065023 00000 n 0000067717 00000 n 0000069617 00000 n 0000072034 00000 n 0000075339 00000 n 0000078496 00000 n 0000081065 00000 n 0000084821 00000 n 0000089326 00000 n 0000095146 00000 n 0000099814 00000 n 0000109053 00000 n 0000115664 00000 n 0000015493 00000 n 0000012880 00000 n 0000011809 00000 n 0000013135 00000 n 0000013268 00000 n 0000013408 00000 n 0000013548 00000 n 0000013686 00000 n 0000013826 00000 n 0000013962 00000 n 0000014102 00000 n 0000014242 00000 n 0000014381 00000 n 0000014521 00000 n 0000014657 00000 n 0000014797 00000 n 0000014937 00000 n 0000015077 00000 n 0000015213 00000 n 0000015353 00000 n 0000118639 00000 n 0000119968 00000 n 0000125461 00000 n 0000126391 00000 n 0000127812 00000 n 0000132056 00000 n 0000134591 00000 n 0000019092 00000 n 0000018737 00000 n 0000015586 00000 n 0000161219 00000 n 0000154230 00000 n 0000161049 00000 n 0000018869 00000 n 0000268941 00000 n 0000021409 00000 n 0000020711 00000 n 0000019223 00000 n 0000020859 00000 n 0000021021 00000 n 0000021182 00000 n 0000023533 00000 n 0000023364 00000 n 0000021515 00000 n 0000025173 00000 n 0000025003 00000 n 0000023652 00000 n 0000025115 00000 n 0000026715 00000 n 0000026545 00000 n 0000025279 00000 n 0000026657 00000 n 0000028980 00000 n 0000028810 00000 n 0000026809 00000 n 0000028922 00000 n 0000031166 00000 n 0000030997 00000 n 0000029074 00000 n 0000269058 00000 n 0000032800 00000 n 0000032630 00000 n 0000031272 00000 n 0000032742 00000 n 0000033796 00000 n 0000033626 00000 n 0000032906 00000 n 0000033738 00000 n 0000034243 00000 n 0000034073 00000 n 0000033878 00000 n 0000034185 00000 n 0000035780 00000 n 0000035611 00000 n 0000034313 00000 n 0000036276 00000 n 0000036106 00000 n 0000035911 00000 n 0000036218 00000 n 0000038417 00000 n 0000038248 00000 n 0000036346 00000 n 0000269175 00000 n 0000040474 00000 n 0000040304 00000 n 0000038548 00000 n 0000040416 00000 n 0000043297 00000 n 0000043128 00000 n 0000040592 00000 n 0000047159 00000 n 0000046989 00000 n 0000043440 00000 n 0000047101 00000 n 0000048744 00000 n 0000048574 00000 n 0000047277 00000 n 0000048686 00000 n 0000049227 00000 n 0000049057 00000 n 0000048862 00000 n 0000049169 00000 n 0000051711 00000 n 0000051542 00000 n 0000049297 00000 n 0000269292 00000 n 0000055483 00000 n 0000055313 00000 n 0000051854 00000 n 0000055425 00000 n 0000057746 00000 n 0000057577 00000 n 0000055613 00000 n 0000061651 00000 n 0000061481 00000 n 0000057876 00000 n 0000061593 00000 n 0000153917 00000 n 0000149038 00000 n 0000153743 00000 n 0000065080 00000 n 0000064911 00000 n 0000061794 00000 n 0000067774 00000 n 0000067605 00000 n 0000065210 00000 n 0000069674 00000 n 0000069505 00000 n 0000067904 00000 n 0000269409 00000 n 0000072091 00000 n 0000071922 00000 n 0000069804 00000 n 0000075396 00000 n 0000075227 00000 n 0000072221 00000 n 0000078553 00000 n 0000078384 00000 n 0000075526 00000 n 0000081122 00000 n 0000080953 00000 n 0000078671 00000 n 0000081617 00000 n 0000081447 00000 n 0000081252 00000 n 0000081559 00000 n 0000084878 00000 n 0000084709 00000 n 0000081687 00000 n 0000269526 00000 n 0000086481 00000 n 0000086311 00000 n 0000085021 00000 n 0000086423 00000 n 0000089383 00000 n 0000089214 00000 n 0000086599 00000 n 0000092289 00000 n 0000092119 00000 n 0000089526 00000 n 0000092231 00000 n 0000095203 00000 n 0000095034 00000 n 0000092407 00000 n 0000097262 00000 n 0000097092 00000 n 0000095346 00000 n 0000097204 00000 n 0000099871 00000 n 0000099702 00000 n 0000097380 00000 n 0000269643 00000 n 0000102907 00000 n 0000102737 00000 n 0000100002 00000 n 0000102849 00000 n 0000105593 00000 n 0000105423 00000 n 0000103037 00000 n 0000105535 00000 n 0000109110 00000 n 0000108941 00000 n 0000105723 00000 n 0000112635 00000 n 0000112465 00000 n 0000109252 00000 n 0000112577 00000 n 0000115084 00000 n 0000114914 00000 n 0000112765 00000 n 0000115026 00000 n 0000115721 00000 n 0000115552 00000 n 0000115214 00000 n 0000269760 00000 n 0000116168 00000 n 0000115998 00000 n 0000115804 00000 n 0000116110 00000 n 0000116745 00000 n 0000116575 00000 n 0000116238 00000 n 0000116687 00000 n 0000117191 00000 n 0000117021 00000 n 0000116827 00000 n 0000117133 00000 n 0000118697 00000 n 0000118527 00000 n 0000117261 00000 n 0000120026 00000 n 0000119856 00000 n 0000118816 00000 n 0000121136 00000 n 0000120966 00000 n 0000120108 00000 n 0000121078 00000 n 0000269877 00000 n 0000122103 00000 n 0000121933 00000 n 0000121218 00000 n 0000122045 00000 n 0000123028 00000 n 0000122858 00000 n 0000122185 00000 n 0000122970 00000 n 0000123972 00000 n 0000123802 00000 n 0000123110 00000 n 0000123914 00000 n 0000125519 00000 n 0000125349 00000 n 0000124054 00000 n 0000126449 00000 n 0000126279 00000 n 0000125638 00000 n 0000127870 00000 n 0000127700 00000 n 0000126531 00000 n 0000269994 00000 n 0000128832 00000 n 0000128662 00000 n 0000127977 00000 n 0000128774 00000 n 0000130048 00000 n 0000129878 00000 n 0000128914 00000 n 0000129990 00000 n 0000130938 00000 n 0000130768 00000 n 0000130130 00000 n 0000130880 00000 n 0000132114 00000 n 0000131944 00000 n 0000131020 00000 n 0000133444 00000 n 0000133274 00000 n 0000132220 00000 n 0000133386 00000 n 0000134649 00000 n 0000134479 00000 n 0000133526 00000 n 0000270111 00000 n 0000135967 00000 n 0000135797 00000 n 0000134756 00000 n 0000135909 00000 n 0000136982 00000 n 0000136812 00000 n 0000136049 00000 n 0000136924 00000 n 0000137064 00000 n 0000279010 00000 n 0000137109 00000 n 0000137143 00000 n 0000278945 00000 n 0000137188 00000 n 0000137237 00000 n 0000278813 00000 n 0000137282 00000 n 0000137312 00000 n 0000278695 00000 n 0000137357 00000 n 0000137401 00000 n 0000278616 00000 n 0000137446 00000 n 0000137486 00000 n 0000278523 00000 n 0000137531 00000 n 0000137590 00000 n 0000278444 00000 n 0000137635 00000 n 0000137827 00000 n 0000278326 00000 n 0000137872 00000 n 0000137916 00000 n 0000278247 00000 n 0000137961 00000 n 0000138001 00000 n 0000278168 00000 n 0000138046 00000 n 0000138099 00000 n 0000278075 00000 n 0000138144 00000 n 0000138176 00000 n 0000277943 00000 n 0000138221 00000 n 0000138252 00000 n 0000277878 00000 n 0000138297 00000 n 0000138340 00000 n 0000277785 00000 n 0000138385 00000 n 0000138455 00000 n 0000277652 00000 n 0000138500 00000 n 0000138563 00000 n 0000277573 00000 n 0000138608 00000 n 0000138643 00000 n 0000277441 00000 n 0000138688 00000 n 0000138750 00000 n 0000277362 00000 n 0000138795 00000 n 0000138832 00000 n 0000277269 00000 n 0000138877 00000 n 0000138916 00000 n 0000277176 00000 n 0000138961 00000 n 0000139004 00000 n 0000277097 00000 n 0000139049 00000 n 0000139091 00000 n 0000277004 00000 n 0000139136 00000 n 0000139173 00000 n 0000276911 00000 n 0000139218 00000 n 0000139249 00000 n 0000276818 00000 n 0000139294 00000 n 0000139326 00000 n 0000276725 00000 n 0000139371 00000 n 0000139417 00000 n 0000276632 00000 n 0000139462 00000 n 0000139501 00000 n 0000276539 00000 n 0000139546 00000 n 0000139577 00000 n 0000276446 00000 n 0000139622 00000 n 0000139649 00000 n 0000276353 00000 n 0000139694 00000 n 0000139730 00000 n 0000276260 00000 n 0000139775 00000 n 0000139806 00000 n 0000276167 00000 n 0000139851 00000 n 0000139882 00000 n 0000276088 00000 n 0000139927 00000 n 0000139967 00000 n 0000275995 00000 n 0000140012 00000 n 0000140076 00000 n 0000275902 00000 n 0000140121 00000 n 0000140180 00000 n 0000275809 00000 n 0000140225 00000 n 0000140292 00000 n 0000275677 00000 n 0000140337 00000 n 0000140384 00000 n 0000275559 00000 n 0000140429 00000 n 0000140465 00000 n 0000275441 00000 n 0000140510 00000 n 0000140555 00000 n 0000275362 00000 n 0000140600 00000 n 0000140623 00000 n 0000275283 00000 n 0000140668 00000 n 0000140696 00000 n 0000275151 00000 n 0000140741 00000 n 0000140783 00000 n 0000275072 00000 n 0000140828 00000 n 0000140855 00000 n 0000274993 00000 n 0000140900 00000 n 0000140931 00000 n 0000274900 00000 n 0000140976 00000 n 0000141022 00000 n 0000274821 00000 n 0000141067 00000 n 0000141114 00000 n 0000274703 00000 n 0000141159 00000 n 0000141227 00000 n 0000274624 00000 n 0000141272 00000 n 0000141453 00000 n 0000274531 00000 n 0000141498 00000 n 0000141532 00000 n 0000274452 00000 n 0000141577 00000 n 0000141621 00000 n 0000274359 00000 n 0000141666 00000 n 0000141701 00000 n 0000274227 00000 n 0000141746 00000 n 0000141784 00000 n 0000274109 00000 n 0000141829 00000 n 0000141858 00000 n 0000274044 00000 n 0000141903 00000 n 0000141940 00000 n 0000273951 00000 n 0000141985 00000 n 0000142019 00000 n 0000273858 00000 n 0000142064 00000 n 0000142106 00000 n 0000273740 00000 n 0000142151 00000 n 0000142185 00000 n 0000273661 00000 n 0000142230 00000 n 0000142261 00000 n 0000273568 00000 n 0000142306 00000 n 0000142343 00000 n 0000273475 00000 n 0000142388 00000 n 0000142418 00000 n 0000273382 00000 n 0000142463 00000 n 0000142492 00000 n 0000273303 00000 n 0000142537 00000 n 0000142570 00000 n 0000273171 00000 n 0000142615 00000 n 0000142654 00000 n 0000273053 00000 n 0000142699 00000 n 0000142728 00000 n 0000272988 00000 n 0000142773 00000 n 0000142810 00000 n 0000272895 00000 n 0000142855 00000 n 0000142889 00000 n 0000272802 00000 n 0000142934 00000 n 0000142976 00000 n 0000272684 00000 n 0000143021 00000 n 0000143055 00000 n 0000272619 00000 n 0000143100 00000 n 0000143131 00000 n 0000272487 00000 n 0000143176 00000 n 0000143224 00000 n 0000272408 00000 n 0000143269 00000 n 0000143298 00000 n 0000272276 00000 n 0000143343 00000 n 0000143371 00000 n 0000272197 00000 n 0000143416 00000 n 0000143459 00000 n 0000272104 00000 n 0000143504 00000 n 0000143545 00000 n 0000272011 00000 n 0000143590 00000 n 0000143629 00000 n 0000271932 00000 n 0000143674 00000 n 0000143718 00000 n 0000271814 00000 n 0000143763 00000 n 0000143797 00000 n 0000271735 00000 n 0000143842 00000 n 0000143878 00000 n 0000271656 00000 n 0000143923 00000 n 0000143954 00000 n 0000271538 00000 n 0000143999 00000 n 0000144036 00000 n 0000271459 00000 n 0000144081 00000 n 0000144110 00000 n 0000271341 00000 n 0000144155 00000 n 0000144183 00000 n 0000271262 00000 n 0000144228 00000 n 0000144269 00000 n 0000271169 00000 n 0000144314 00000 n 0000144354 00000 n 0000271037 00000 n 0000144399 00000 n 0000144450 00000 n 0000270958 00000 n 0000144495 00000 n 0000144521 00000 n 0000270879 00000 n 0000144566 00000 n 0000144596 00000 n 0000145928 00000 n 0000270761 00000 n 0000144641 00000 n 0000144708 00000 n 0000270682 00000 n 0000144753 00000 n 0000144779 00000 n 0000270603 00000 n 0000144824 00000 n 0000145986 00000 n 0000145816 00000 n 0000144854 00000 n 0000147068 00000 n 0000146898 00000 n 0000146080 00000 n 0000147010 00000 n 0000147150 00000 n 0000154146 00000 n 0000161464 00000 n 0000178156 00000 n 0000193498 00000 n 0000214684 00000 n 0000217529 00000 n 0000217304 00000 n 0000233028 00000 n 0000253328 00000 n 0000258296 00000 n 0000268460 00000 n 0000270220 00000 n 0000270337 00000 n 0000270455 00000 n 0000270525 00000 n 0000279128 00000 n 0000280338 00000 n 0000280377 00000 n 0000280415 00000 n 0000280524 00000 n trailer << /Size 663 /Root 661 0 R /Info 662 0 R /ID [<767010DC65D8837513F3AAD3A5A16484> <767010DC65D8837513F3AAD3A5A16484>] >> startxref 280832 %%EOF ZSI-2.1-a1/doc/zsi.xsd0000644000175100017510000000763707427543543012642 0ustar zsizsi ZSI-2.1-a1/doc/zsi.ps0000644000175100017510000062320310712455101012436 0ustar zsizsi%!PS-Adobe-2.0 %%Creator: dvips(k) 5.95a Copyright 2005 Radical Eye Software %%Title: zsi.dvi %%Pages: 71 %%PageOrder: Ascend %%BoundingBox: 0 0 612 792 %%DocumentFonts: Helvetica Helvetica-Oblique Times-Roman Times-Bold %%+ CMSY10 Courier Times-Italic Courier-Bold Helvetica-Bold %%+ Courier-BoldOblique %%DocumentPaperSizes: Letter %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -N0 -t letter -o zsi.ps zsi.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2007.11.01:2259 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: 8r.enc 0 0 % File 8r.enc TeX Base 1 Encoding Revision 2.0 2002-10-30 % % @@psencodingfile@{ % author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry, % W. Schmidt, P. Lehman", % version = "2.0", % date = "30 October 2002", % filename = "8r.enc", % email = "tex-fonts@@tug.org", % docstring = "This is the encoding vector for Type1 and TrueType % fonts to be used with TeX. This file is part of the % PSNFSS bundle, version 9" % @} % % The idea is to have all the characters normally included in Type 1 fonts % available for typesetting. This is effectively the characters in Adobe % Standard encoding, ISO Latin 1, Windows ANSI including the euro symbol, % MacRoman, and some extra characters from Lucida. % % Character code assignments were made as follows: % % (1) the Windows ANSI characters are almost all in their Windows ANSI % positions, because some Windows users cannot easily reencode the % fonts, and it makes no difference on other systems. The only Windows % ANSI characters not available are those that make no sense for % typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen % (173). quotesingle and grave are moved just because it's such an % irritation not having them in TeX positions. % % (2) Remaining characters are assigned arbitrarily to the lower part % of the range, avoiding 0, 10 and 13 in case we meet dumb software. % % (3) Y&Y Lucida Bright includes some extra text characters; in the % hopes that other PostScript fonts, perhaps created for public % consumption, will include them, they are included starting at 0x12. % These are /dotlessj /ff /ffi /ffl. % % (4) hyphen appears twice for compatibility with both ASCII and Windows. % % (5) /Euro was assigned to 128, as in Windows ANSI % % (6) Missing characters from MacRoman encoding incorporated as follows: % % PostScript MacRoman TeXBase1 % -------------- -------------- -------------- % /notequal 173 0x16 % /infinity 176 0x17 % /lessequal 178 0x18 % /greaterequal 179 0x19 % /partialdiff 182 0x1A % /summation 183 0x1B % /product 184 0x1C % /pi 185 0x1D % /integral 186 0x81 % /Omega 189 0x8D % /radical 195 0x8E % /approxequal 197 0x8F % /Delta 198 0x9D % /lozenge 215 0x9E % /TeXBase1Encoding [ % 0x00 /.notdef /dotaccent /fi /fl /fraction /hungarumlaut /Lslash /lslash /ogonek /ring /.notdef /breve /minus /.notdef /Zcaron /zcaron % 0x10 /caron /dotlessi /dotlessj /ff /ffi /ffl /notequal /infinity /lessequal /greaterequal /partialdiff /summation /product /pi /grave /quotesingle % 0x20 /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash % 0x30 /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question % 0x40 /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O % 0x50 /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore % 0x60 /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o % 0x70 /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef % 0x80 /Euro /integral /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl /circumflex /perthousand /Scaron /guilsinglleft /OE /Omega /radical /approxequal % 0x90 /.notdef /.notdef /.notdef /quotedblleft /quotedblright /bullet /endash /emdash /tilde /trademark /scaron /guilsinglright /oe /Delta /lozenge /Ydieresis % 0xA0 /.notdef /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron % 0xD0 /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown % 0xC0 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis % 0xD0 /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls % 0xE0 /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis % 0xF0 /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] def %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMSY10 %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 13 /circlecopyrt put dup 102 /braceleft put dup 103 /braceright put dup 110 /backslash put readonly def /FontBBox{-29 -960 1116 775}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A 27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF 5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A 71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C 515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 253AB320C099669BFED2878A6C4038A5BCEB5B4C28040BB8B4AC2C167BB2C999 ED93E2F4AE3E4B44B7B6B469C36A24080D4BEDB5523D202E920D8898DEBD5EB0 CAC3C5D5F01A87F7B15BD1C197B344F7D94E965CBFE73E8A65A2AA6A6F93B878 03E30E60F1390C2FB671C8D36E7D6E516A20079B48CA9BE632F5A8D1250F01EE 6809D6C5B51AE3D1B4C5F2F0273F59A8B6996BAC5E80E1D3465231006F548460 8FAF92EC9040848022ACFB9FDCF92DB3C3BFCC5ECB83DF8FDF612FFA0143E790 8BF3F08C9CFB528D9F148285297C422C3453AC567C162F9AF67A8C04A9C6EF24 F22EAA0E1E3C019E87D4EE91AD20B46B9D0AA009258729F27189AC5CE11652D3 D333BB22D9FA5C9493F0A0BD7535C830DC8B0DA576488CC641C193FE7CC27697 A90351F201AA029742EC530597B0CC5F862A5DBB24A7C6D75B4A116E0B6A285C 04A42215D39D5109AE37295051AF25C4A8317D461D4E67DF4E855356479B6F84 DC5A56370F1B73CE160EF1D35C0C95598363456BAB251BB783EC8D0517B7D82E F6B8E6ECA69FC7DBD1A64E08A9AF313E04C3B00B4FE18D75E1229C7A482494F8 A78672EFF2E156CC8052A5C44FE7A7DBC97E493C6519CEDE5B0B22461390B8B0 363289D7F2AC693256A3943D6A0854C3CA39F7E7FAE5E36B0B9CA0A8C47BF5FC 2CF48FD8F139786D179CF88ED2F083C1513BAB7963DCF8947184D707A37FE528 61EB53D581AF2B61470F29AEE070A2E97F1425A4C8BBAE7B5AA8D9C59130F6BB AEF0C4B2B0AF4E9C145EBBA4EC69144632C9E3CF7F7DBB2E9D554CFCB784D942 3081E604D1ACE9F686BA4F27240E4F1DBEFBF506685E4AEB0FF4B5D89A6EFE8F 6043C819750B5720EAE0FE0227A34DA5D92B1BADF2AE24F673B1B2B02580F8D5 AE65D4CFFBC195EFF321DF9D72F98B0516B5D141AA315F2362450C7F398DA68E 170D12D7423F8E43DCBD5DCF8EF74BDE161BB620F43FAD0D106C6C3404C92611 0CEAD737CDA74A1A328CBCEB4B47A9F01AB1EB00BF135902A187EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont TeXDict begin 40258431 52099146 1000 600 600 (zsi.dvi) @start /Fa 166[50 1[50 2[50 3[50 50 50 8[50 50 50 67[{ TeXBase1Encoding ReEncodeFont}9 83.022 /Courier-BoldOblique rf /Fb 134[72 4[72 3[72 72 72 72 72 2[72 3[72 72 72 14[72 72 15[72 1[72 18[72 46[{TeXBase1Encoding ReEncodeFont}16 119.552 /Courier rf /Fc 162[40 1[40 91[{TeXBase1Encoding ReEncodeFont}2 119.552 /Times-Roman rf /Fd 134[124 2[124 124 124 124 124 1[124 124 2[124 2[124 3[124 124 2[124 9[124 2[124 124 2[124 9[124 2[124 67[{TeXBase1Encoding ReEncodeFont}19 206.559 /Courier rf /Fe 130[45 1[45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 1[45 1[45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 1[45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 33[{TeXBase1Encoding ReEncodeFont}89 74.7198 /Courier rf /Ff 134[50 50 72 50 55 28 50 33 1[55 55 55 83 22 50 1[22 55 55 28 55 55 50 1[55 13[66 2[66 78 72 83 5[78 1[66 72 72 66 66 6[28 3[55 55 55 55 55 55 55 1[28 46[{TeXBase1Encoding ReEncodeFont}42 99.6264 /Helvetica rf /Fg 104[120 29[60 60 86 60 66 33 60 40 1[66 66 66 100 27 2[27 66 66 33 66 66 60 66 66 8[80 2[86 73 80 86 1[80 93 86 100 66 2[33 86 93 73 80 86 86 80 80 7[66 66 66 66 66 66 66 66 66 66 1[33 40 45[{ TeXBase1Encoding ReEncodeFont}54 119.552 /Helvetica rf /Fh 167[80 113 80 86 73 80 86 2[93 86 1[73 2[33 86 93 73 80 86 86 86 86 65[{TeXBase1Encoding ReEncodeFont}19 119.552 /Helvetica-Bold rf /Fi 104[83 28[42 42 42 60 42 46 23 42 28 1[46 46 46 69 18 42 1[18 46 46 23 46 46 42 46 46 8[55 2[60 51 55 60 1[55 65 60 69 46 2[23 60 65 51 55 60 60 55 55 7[46 46 46 46 46 46 46 46 46 46 1[23 28 45[{TeXBase1Encoding ReEncodeFont}56 83.022 /Helvetica rf /Fj 133[50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 1[50 50 50 50 50 50 50 50 50 1[50 4[50 50 50 50 50 50 50 50 50 1[50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 10[50 1[50 5[50 4[50 50 40[{TeXBase1Encoding ReEncodeFont} 56 83.022 /Courier-Bold rf /Fk 133[32 37 37 55 37 42 23 32 32 42 42 42 42 60 23 37 23 23 42 42 23 37 42 37 42 42 8[51 69 1[60 46 42 51 1[51 60 55 69 46 2[28 1[60 51 1[60 55 51 51 3[56 11[42 42 1[21 28 21 1[42 39[42 2[{TeXBase1Encoding ReEncodeFont}52 83.022 /Times-Italic rf /Fl 130[50 1[50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 1[50 1[50 1[50 50 1[50 50 50 50 50 50 50 1[50 50 50 50 50 2[50 50 50 50 50 50 50 50 50 3[50 2[50 1[50 1[50 1[50 50 50 50 50 50 50 50 50 2[50 50 50 1[50 1[50 50 34[{TeXBase1Encoding ReEncodeFont} 72 83.022 /Courier rf /Fm 145[42 6[42 42 88[83 13[{}4 83.022 /CMSY10 rf /Fn 64[37 39[83 42 1[37 37 24[37 42 42 60 42 42 23 32 28 42 42 42 42 65 23 42 23 23 42 42 28 37 42 37 42 37 28 2[28 1[28 51 60 60 78 60 60 51 46 55 60 46 60 60 74 51 60 32 28 60 60 46 51 60 55 55 60 5[23 23 42 42 42 42 42 42 42 42 42 42 23 21 28 21 2[28 28 28 35[46 46 2[{TeXBase1Encoding ReEncodeFont}81 83.022 /Times-Roman rf /Fo 104[83 28[37 42 42 60 42 46 28 32 37 1[46 42 46 69 23 46 1[23 46 42 28 37 46 37 46 42 7[60 3[60 55 46 60 1[51 65 2[55 65 1[32 65 65 1[55 60 60 55 60 7[42 42 42 42 42 42 42 42 42 42 1[21 28 42[46 2[{ TeXBase1Encoding ReEncodeFont}55 83.022 /Times-Bold rf /Fp 133[37 37 1[54 1[42 21 37 25 1[42 42 42 62 17 37 2[42 42 1[42 42 37 42 42 32[76 17[21 46[{TeXBase1Encoding ReEncodeFont} 22 74.7198 /Helvetica rf /Fq 137[50 3[33 2[50 1[78 7[44 2[50 19[72 22[50 4[50 50 50 3[25 44[{TeXBase1Encoding ReEncodeFont}12 99.6264 /Times-Roman rf /Fr 133[72 4[80 40 72 48 1[80 80 80 1[32 72 1[32 80 2[80 1[72 1[80 13[96 104 14[104 96 21[40 44[{TeXBase1Encoding ReEncodeFont}20 143.462 /Helvetica rf /Fs 140[72 6[32 6[80 3[80 14[104 31[80 80 80 1[40 46[{TeXBase1Encoding ReEncodeFont}9 143.462 /Helvetica-Oblique rf /Ft 104[207 28[103 103 103 149 103 115 57 103 69 1[115 115 115 172 46 103 1[46 115 115 57 115 115 103 115 115 6[126 138 3[149 126 138 149 1[138 161 149 1[115 2[57 149 161 1[138 149 149 138 138 6[57 18[46 39[{TeXBase1Encoding ReEncodeFont}45 206.559 /Helvetica rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: Letter letter %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 0 83 3901 9 v 652 446 a Ft(ZSI:)58 b(The)g(Zoler)n(a)e(Soap)h(Infr)n(astr)s(ucture)2223 695 y(De)-6 b(v)h(eloper')-10 b(s)56 b(Guide)3015 925 y Fs(Release)38 b(2.1.0)3254 2045 y Fr(Rich)h(Salz,)2689 2228 y(Chr)r(istopher)e(Blunc)m(k)3109 4172 y Fq(No)o(v)o(ember)23 b(01,)i(2007)3161 5201 y Fp(rsalz@datapo)o(w)o(er)l(.com)3260 5317 y(b)o(lunc)o(k@p)n(ython.org)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 1694 83 a Fo(COPYRIGHT)0 230 y Fn(Cop)o(yright)380 227 y(c)357 230 y Fm(\015)20 b Fn(2001,)f(Zolera)g (Systems,)i(Inc.)0 330 y(All)g(Rights)f(Reserv)o(ed.)0 476 y(Cop)o(yright)380 473 y(c)357 476 y Fm(\015)g Fn(2002-2003,)d (Rich)j(Salz.)0 576 y(All)h(Rights)f(Reserv)o(ed.)0 723 y(Permission)27 b(is)h(hereby)d(granted,)i(free)g(of)g(char)o(ge,)g(to) g(an)o(y)f(person)g(obtaining)g(a)h(cop)o(y)f(of)h(this)h(softw)o(are)f (and)f(associated)h(docu-)0 823 y(mentation)20 b(\002les)j(\(the)e (\224Softw)o(are\224\),)g(to)g(deal)h(in)f(the)h(Softw)o(are)f(without) g(restriction,)g(including)f(without)g(limitation)i(the)f(rights)g(to)0 922 y(use,)k(cop)o(y)-5 b(,)24 b(modify)-5 b(,)23 b(mer)o(ge,)h (publish,)g(distrib)n(ute,)h(and/or)d(sell)k(copies)e(of)g(the)g(Softw) o(are,)g(and)g(to)h(permit)e(persons)h(to)g(whom)g(the)0 1022 y(Softw)o(are)i(is)i(furnished)c(to)j(do)f(so,)j(pro)o(vided)24 b(that)i(the)h(abo)o(v)o(e)e(cop)o(yright)f(notice\(s\))i(and)g(this)h (permission)f(notice)g(appear)f(in)i(all)0 1121 y(copies)g(of)g(the)g (Softw)o(are)g(and)g(that)g(both)f(the)i(abo)o(v)o(e)d(cop)o(yright)h (notice\(s\))g(and)h(this)g(permission)g(notice)f(appear)g(in)i (supporting)0 1221 y(documentation.)0 1368 y(THE)e(SOFTW)-10 b(ARE)26 b(IS)g(PR)m(O)l(VIDED)g(\224AS)g(IS\224,)h(WITHOUT)e(W)-10 b(ARRANTY)27 b(OF)f(ANY)g(KIND,)g(EXPRESS)g(OR)h(IMPLIED,)0 1468 y(INCLUDING)f(B)o(UT)h(NO)m(T)g(LIMITED)e(T)o(O)h(THE)g(W)-10 b(ARRANTIES)27 b(OF)h(MERCHANT)-8 b(ABILITY)d(,)26 b(FITNESS)g(FOR)i(A) f(P)-8 b(AR-)0 1567 y(TICULAR)29 b(PURPOSE)g(AND)f(NONINFRINGEMENT)g (OF)g(THIRD)h(P)-8 b(AR)j(TY)29 b(RIGHTS.)f(IN)h(NO)f(EVENT)g(SHALL)h (THE)0 1667 y(COPYRIGHT)19 b(HOLDER)g(OR)g(HOLDERS)g(INCLUDED)f(IN)h (THIS)g(NO)m(TICE)f(BE)h(LIABLE)f(FOR)i(ANY)e(CLAIM,)h(OR)g(ANY)0 1766 y(SPECIAL)25 b(INDIRECT)g(OR)h(CONSEQ)o(UENTIAL)f(D)m(AMA)m(GES,)f (OR)i(ANY)f(D)m(AMA)m(GES)f(WHA)-9 b(TSOEVER)25 b(RESUL)-8 b(TING)0 1866 y(FR)m(OM)27 b(LOSS)g(OF)g(USE,)f(D)m(A)-9 b(T)h(A)27 b(OR)g(PR)m(OFITS,)f(WHETHER)h(IN)f(AN)h(A)m(CTION)f(OF)h (CONTRA)m(CT)-6 b(,)27 b(NEGLIGENCE)f(OR)0 1966 y(O)m(THER)20 b(T)o(OR)-5 b(TIOUS)20 b(A)m(CTION,)g(ARISING)h(OUT)f(OF)h(OR)h(IN)e (CONNECTION)h(WITH)f(THE)g(USE)h(OR)g(PERFORMANCE)0 2065 y(OF)g(THIS)f(SOFTW)-10 b(ARE.)0 2212 y(Except)27 b(as)i(contained)d (in)i(this)g(notice,)h(the)f(name)f(of)h(a)g(cop)o(yright)e(holder)g (shall)j(not)e(be)h(used)g(in)g(adv)o(ertising)e(or)h(otherwise)g(to)0 2312 y(promote)18 b(the)j(sale,)f(use)h(or)f(other)f(dealings)g(in)i (this)g(Softw)o(are)e(without)h(prior)f(written)h(authorization)e(of)h (the)i(cop)o(yright)d(holder)-5 b(.)1625 2766 y Fo(Ackno)o(wledgments)0 2913 y Fn(W)e(e)60 b(are)e(grateful)f(to)i(the)f(members)g(of)g(the)g Fl(soapbuilders)f Fn(mailing)h(list)h(\(see)g Fl(http://groups.yahoo.)0 3012 y(com/soapbuilders)p Fn(\),)45 b(Fredrik)d(Lundh)e(for)i(his)h Fl(soaplib)f Fn(package)f(\(see)i Fl(http://www.secretlabs.com/)0 3112 y(downloads/index.htm)p Fm(n)p Fl(#soap)p Fn(\),)20 b(Cayce)25 b(Ullman)f(and)g(Brian)g(Matthe)n(ws)h(for)e(their)i Fl(SOAP.py)e Fn(package)g(\(see)i Fl(http:)0 3211 y (//sourceforge.net/projects/pywebsvc)o(s)p Fn(\).)0 3358 y(W)-7 b(e)31 b(are)f(particularly)e(grateful)g(to)i(Brian)g(Llo)o(yd)f (and)g(the)h(Zope)f(Corporation)e(\()p Fl(http://www.zope.com)p Fn(\))g(for)i(letting)g(us)0 3458 y(incorporate)18 b(his)i(ZOPE)h(W)-7 b(ebServices)20 b(package)f(and)g(documentation)f(into)h Fl(ZSI)p Fn(.)p eop end %%Page: 1 3 TeXDict begin 1 2 bop 1796 2336 a Fo(Abstract)0 2566 y Fl(ZSI)p Fn(,)24 b(the)h(Zolera)e(SO)m(AP)j(Infrastructure,)c(is)k(a) f(Python)e(package)g(that)i(pro)o(vides)d(an)j(implementation)d(of)i (SO)m(AP)h(messaging,)g(as)0 2666 y(described)d(in)i Fk(The)g(SO)-5 b(AP)23 b(1.1)g(Speci\002cation)p Fn(.)33 b(In)23 b(particular)m(,)f Fl(ZSI)i Fn(parses)g(and)f(generates)f(SO)m (AP)j(messages,)f(and)f(con)m(v)o(erts)f(be-)0 2766 y(tween)29 b(nati)n(v)o(e)f(Python)f(datatypes)h(and)h(SO)m(AP)g(syntax.)50 b(It)30 b(can)e(also)h(be)g(used)g(to)g(b)n(uild)f(applications)g (using)g Fk(SO)-5 b(AP)29 b(Messa)o(g)o(es)0 2865 y(with)24 b(Attac)o(hments)p Fn(.)33 b Fl(ZSI)24 b Fn(is)g(\223transport)e (neutral\224,)h(and)g(pro)o(vides)f(only)g(a)i(simple)g(I/O)f(and)g (dispatch)g(frame)n(w)o(ork;)g(a)h(more)e(com-)0 2965 y(plete)h(solution)g(is)h(the)g(responsibility)e(of)h(the)h (application)e(using)h Fl(ZSI)p Fn(.)g(As)h(usage)f(patterns)g(emer)o (ge,)g(and)f(common)g(application)0 3065 y(frame)n(w)o(orks)c(are)i (more)g(understood,)d(this)k(may)f(change.)0 3211 y Fl(ZSI)g Fn(requires)f(Python)g(2.3)h(or)g(later)-5 b(.)0 3358 y(The)20 b Fl(ZSI)g Fn(homepage)e(is)j(at)g Fl (http://pywebsvcs.sf.net/)p Fn(.)p eop end %%Page: 2 4 TeXDict begin 2 3 bop eop end %%Page: 1 5 TeXDict begin 1 4 bop 2764 747 a Ft(CONTENTS)0 1594 y Fo(1)83 b(Intr)o(oduction)3281 b(1)125 1694 y Fn(1.1)110 b(Ho)n(w)20 b(to)h(Read)f(this)h(Document)42 b(.)g(.)f(.)g(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(2)0 1876 y Fo(2)83 b(Examples)3387 b(3)125 1976 y Fn(2.1)110 b(Serv)o(er)20 b(Side)g(Examples)68 b(.)41 b(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(3)125 2076 y(2.2)110 b(Client)21 b(Side)f(Examples)81 b(.)41 b(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)143 b(7)0 2258 y Fo(3)83 b(Exceptions)3304 b(11)0 2441 y(4)83 b(Utilities)3415 b(13)125 2540 y Fn(4.1)110 b(Lo)n(w-Le)n(v)o(el)19 b(Utilities)25 b(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(13)0 2723 y Fo(5)83 b(The)21 b Fj(ParsedSoap)e Fo(module)h(\227)h(basic)g (message)f(handling)1801 b(15)0 2906 y(6)83 b(The)21 b Fj(TypeCode)e Fo(classes)i(\227)g(data)e(con)m(v)o(ersions)2165 b(19)125 3005 y Fn(6.1)110 b Fl(TC.TypeCode)65 b Fn(.)41 b(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(19)125 3105 y(6.2)110 b Fl(TC.Any)20 b Fn(\227)h(the)f(basis)h(of)f(dynamic)e (typing)81 b(.)41 b(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) 102 b(21)125 3205 y(6.3)110 b Fl(TC.SimpleType)27 b Fn(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(23)125 3304 y(6.4)110 b(Strings)67 b(.)42 b(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)102 b(23)125 3404 y(6.5)110 b(Inte)o(gers)35 b(.)42 b(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(24)125 3504 y(6.6)110 b(Floating-point)18 b(Numbers)62 b(.)41 b(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(25)125 3603 y(6.7)110 b(Dates)21 b(and)f(T)m(imes)59 b(.)41 b(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g (.)102 b(26)125 3703 y(6.8)110 b(Boolean)25 b(.)42 b(.)f(.)g(.)g(.)h(.) f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(26)125 3802 y(6.9)110 b(XML)56 b(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g (.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)102 b(27)125 3902 y(6.10)68 b(Comple)o(xT)-7 b(ype)20 b(.)41 b(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(27)125 4002 y(6.11)68 b(Struct)42 b(.)f(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(28)125 4101 y(6.12)68 b(Arrays)76 b(.)42 b(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) g(.)102 b(28)125 4201 y(6.13)68 b(Apache)20 b(Datatype)39 b(.)i(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(29)0 4384 y Fo(7)83 b(The)21 b Fj(SoapWriter)e Fo(module)h(\227)h(serializing)f (data)2084 b(31)0 4566 y(8)83 b(The)21 b Fj(Fault)f Fo(module)g(\227)h (r)o(eporting)e(err)o(ors)2299 b(33)0 4749 y(9)83 b(The)21 b Fj(resolvers)e Fo(module)h(\227)h(fetching)f(r)o(emote)f(data)1944 b(35)0 4932 y(10)41 b(Dispatching)20 b(and)g(In)m(v)o(oking)2778 b(37)125 5031 y Fn(10.1)68 b(Dispatching)25 b(.)41 b(.)g(.)h(.)f(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(37)125 5131 y(10.2)68 b(The)20 b Fl(client)g Fn(module)f(\227)h(sending)g(SO)m(AP)h(messages) 69 b(.)41 b(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(40)0 5313 y Fo(11)41 b(Bibliograph)o(y)3226 b(43)p 0 5549 3901 4 v 3882 5649 a Fi(i)p eop end %%Page: 2 6 TeXDict begin 2 5 bop 0 83 a Fo(A)65 b(CGI)20 b(Script)h(Array)3059 b(47)125 183 y Fn(A.1)92 b(Intro)78 b(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(47)125 282 y(A.2)92 b(CGI)21 b(Script)65 b(.)41 b(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)102 b(47)125 382 y(A.3)92 b(client)21 b(test)g(script)k(.)42 b(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(48)125 482 y(A.4)92 b(SO)m(AP)21 b(T)m(race)73 b(.)41 b(.)h(.)f(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)g(.)102 b(48)0 664 y Fo(B)70 b(CGI)20 b(Script)h(Struct)3055 b(53)125 764 y Fn(B.1)97 b(Intro)78 b(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(53)125 863 y(B.2)97 b(CGI)21 b(Script)65 b(.)41 b(.)g(.)h(.)f(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(53)125 963 y(B.3)97 b(client)21 b(test)g(script)k(.)42 b(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) g(.)102 b(54)125 1063 y(B.4)97 b(SO)m(AP)21 b(T)m(race)73 b(.)41 b(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(54)0 1245 y Fo(C)65 b(Complete)20 b(Lo)o(w)g(Le)o(v)o(el)h(Example) 2627 b(55)125 1345 y Fn(C.1)97 b(Intro)78 b(.)41 b(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(55)125 1445 y(C.2)97 b(code)21 b(.)41 b(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g (.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g (.)h(.)f(.)g(.)g(.)102 b(55)125 1544 y(C.3)97 b(SO)m(AP)21 b(T)m(race)73 b(.)41 b(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h (.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)102 b(59)0 1727 y Fo(D)65 b(pickler)20 b(example)3127 b(61)125 1826 y Fn(D.1)92 b(Intro)78 b(.)41 b(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.) f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g (.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.) g(.)g(.)h(.)f(.)g(.)g(.)102 b(61)125 1926 y(D.2)92 b(code)21 b(.)41 b(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.) g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f (.)g(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)h(.)f(.)g(.)g(.)h(.)f(.)g(.)g(.) 102 b(61)p 0 5549 3901 4 v 0 5649 a Fi(ii)p eop end %%Page: 1 7 TeXDict begin 1 6 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3641 427 y Fh(ONE)p 0 515 V 2821 978 a Ft(Introduction)0 1457 y Fl(ZSI)p Fn(,)18 b(the)g(Zolera)g(SO)m(AP)h(Infrastructure,)d(is)j(a) f(Python)f(package)g(that)i(pro)o(vides)d(an)i(implementation)e(of)i (the)g(SO)m(AP)i(speci\002cation,)0 1556 y(as)26 b(described)f(in)g Fk(The)h(SO)-5 b(AP)25 b(1.1)g(Speci\002cation)p Fn(.)39 b(In)25 b(particular)m(,)g Fl(ZSI)h Fn(parses)f(and)g(generates)g(SO)m (AP)h(messages,)h(and)e(con)m(v)o(erts)0 1656 y(between)19 b(nati)n(v)o(e)h(Python)f(datatypes)g(and)h(SO)m(AP)h(syntax.)0 1803 y Fl(ZSI)f Fn(requires)f(Python)g(2.3)h(or)g(later)-5 b(.)0 1950 y(The)20 b Fl(ZSI)g Fn(project)f(is)i(maintained)e(at)i (SourceF)o(or)o(ge,)c(at)j Fl(http://pywebsvcs.sf.net)p Fn(.)i Fl(ZSI)e Fn(is)h(discussed)f(on)g(the)g(Python)0 2049 y(web)c(services)f(mailing)g(list,)i(visit)g Fl (http://lists.sourceforge.net/lists)o(/list)o(info/)o(pywebs)o(vcs-)t (ta)o(lk)0 2149 y Fn(to)j(subscribe.)0 2296 y(F)o(or)j(those)h (interested)f(in)g(using)h(the)f Fo(wsdl2py)h Fn(tool)f(see)i(the)e Fk(User)o(s)i(Guide)p Fn(,)f(it)g(contains)f(a)h(detailed)f(e)o(xample) g(of)g(ho)n(w)g(to)h(use)g(the)0 2395 y(code)c(generation)e(f)o (acilities)j(in)f Fl(ZSI)p Fn(.)0 2542 y(F)o(or)f(those)g(interested)f (in)i(a)f(high-le)n(v)o(el)e(tutorial)i(co)o(v)o(ering)e Fl(ZSI)i Fn(and)f(why)h(Python)f(w)o(as)i(chosen,)e(see)i(the)f (article)g Fl(http://www.)0 2642 y(xml.com/pub/a/ws/2002/06/12/soap.ht) o(ml)p Fn(,)c(written)20 b(by)f(Rich)i(Salz)g(for)e(xml.com.)0 2789 y(SO)m(AP-based)j(processing)e(typically)h(in)m(v)n(olv)o(es)g(se) n(v)o(eral)g(steps.)31 b(The)22 b(follo)n(wing)e(list)k(details)e(the)g (steps)h(of)e(a)i(common)d(processing)0 2888 y(model)f(naturally)g (supported)f(by)i Fl(ZSI)g Fn(\(other)f(models)h(are)g(certainly)f (possible\):)104 3100 y(1.)41 b Fl(ZSI)27 b Fn(tak)o(es)h(data)f(from)f (an)h(input)g(stream)g(and)g Fk(par)o(ses)h Fn(it,)h(generating)c(a)j (DOM-based)e(parse)h(tree)h(as)g(part)f(of)g(creating)f(a)208 3200 y Fl(ParsedSoap)i Fn(object.)53 b(At)30 b(this)g(point)f(the)h (major)e(syntactic)i(elements)f(of)g(a)i(SO)m(AP)f(message)f(\227)i (the)e Fl(Header)p Fn(,)j(the)208 3299 y Fl(Body)p Fn(,)19 b(etc.)26 b(\227)20 b(are)h(a)n(v)n(ailable.)104 3465 y(2.)41 b(The)23 b(application)f(does)i Fk(header)e(pr)l(ocessing)p Fn(.)35 b(More)23 b(speci\002cally)-5 b(,)24 b(it)g(does)g(local)g (dispatch)f(and)g(processing)f(based)h(on)h(the)208 3564 y(elements)d(in)g(the)g(SO)m(AP)i Fl(Header)p Fn(.)k(The)21 b(SO)m(AP)i Fl(actor)d Fn(and)h Fl(mustUnderstand)f Fn(attrib)n(utes)h (are)g(also)h(handled)d(\(or)i(at)208 3664 y(least)f(recognized\))e (here.)104 3829 y(3.)41 b Fl(ZSI)24 b Fn(ne)o(xt)f Fk(par)o(ses)i Fn(the)f Fl(Body)p Fn(,)g(creating)f(local)h(Python)f(objects)h(from)f (the)h(data)g(in)g(the)g(SO)m(AP)h(message.)37 b(The)24 b(parsing)f(is)208 3929 y(often)e(under)g(the)h(control)f(of)h(a)h (list)g(of)f(data)g(descriptions,)f(kno)n(wn)g(as)i Fk(typecodes)p Fn(,)e(de\002ned)h(by)f(the)i(application)d(because)i(it)208 4029 y(kno)n(ws)15 b(what)h(type)f(of)h(data)f(it)i(is)g(e)o(xpecting.) k(In)16 b(cases)h(where)e(the)h(SO)m(AP)h(data)e(is)i(kno)n(wn)e(to)h (be)f(completely)g(self-describing,)208 4128 y(the)20 b(parsing)f(can)h(be)g Fk(dynamic)f Fn(through)f(the)i(use)h(of)f(the)g Fl(TC.Any)f Fn(class.)104 4294 y(4.)41 b(The)16 b(application)f(no)n(w) i Fk(dispatc)o(hes)e Fn(to)j(the)e(appropriate)f(handler)g(in)i(order)f (to)h(do)f(its)i(\223real)f(w)o(ork.)-6 b(\224)23 b(As)18 b(part)e(of)h(its)h(processing)208 4393 y(it)i(may)g(create)g Fk(output)f(objects)104 4559 y Fn(5.)41 b(The)27 b(application)g (creates)i(a)f Fl(SoapWriter)f Fn(instance)h(and)g(outputs)f(an)h (initial)h(set)g(of)f(namespace)f(entries)h(and)g(header)208 4658 y(elements.)104 4824 y(6.)41 b(An)o(y)20 b(local)h(data)g(to)g(be) g(sent)g(back)f(to)h(the)g(client)g(is)h Fk(serialized)p Fn(.)28 b(As)21 b(with)h Fl(Body)e Fn(parsing,)g(the)h(datatypes)f(can) h(be)g(described)208 4923 y(through)d(typecodes)g(or)i(determined)f (dynamically)f(\(here,)h(through)f(introspection\).)104 5089 y(7.)41 b(In)19 b(the)i(e)n(v)o(ent)e(of)h(an)o(y)f(processing)g (e)o(xceptions,)f(a)j Fl(Fault)f Fn(object)g(can)g(be)g(raised,)f (created,)h(and/or)e(serialized.)0 5300 y(Note)25 b(that)h Fl(ZSI)g Fn(is)g(\223transport)e(neutral\224,)i(and)f(pro)o(vides)f (only)g(a)i(simple)g(I/O)f(and)g(dispatch)g(frame)n(w)o(ork;)h(a)g (more)f(complete)g(so-)0 5400 y(lution)e(is)i(a)n(v)n(ailable)e (through)f(the)i(use)g(of)f(included)f(WSDL)j(tools)f(\()p Fo(wsdl2py)p Fn(\),)g(b)n(ut)g(otherwise)f(this)h(is)h(the)f (responsibility)e(of)i(the)p 0 5549 3901 4 v 3854 5649 a Fi(1)p eop end %%Page: 2 8 TeXDict begin 2 7 bop 0 83 a Fn(application)16 b(using)h Fl(ZSI)p Fn(.)h(As)h(usage)e(patterns)g(emer)o(ge,)f(and)i(common)d (application)i(frame)n(w)o(orks)f(are)h(more)g(understood,)f(this)i (may)0 183 y(change.)0 330 y(W)m(ithin)j(this)g(document,)d Fl(tns)j Fn(is)g(used)g(as)g(the)g(pre\002x)f(for)g(the)g(application') -5 b(s)20 b(tar)o(get)g(namespace,)f(and)h(the)h(term)f Fk(element)g Fn(refers)g(to)0 429 y(a)h(DOM)f(element)g(node.\))0 757 y Fg(1.1)121 b(Ho)n(w)34 b(to)g(Read)h(this)e(Document)0 989 y Fn(Readers)27 b(interested)f(in)i(using)e(WSDL)i(and)e(clients)i (to)f(web)g(services,)h(and)f(those)g(intending)e(on)i(implementing)e (web)i(services)0 1089 y(based)c(on)g(e)o(xisting)f(WSDL)i(should)e (refer)h(to)g(the)g Fk(User)o(s)i(Guide)p Fn(.)33 b(Others)23 b(interested)g(in)g(de)n(v)o(eloping)e(the)i(simplest)g(SO)m(AP)h (appli-)0 1189 y(cations,)d(or)h(spending)e(the)h(least)i(amount)d(of)h (time)h(on)f(b)n(uilding)g(a)h(web)f(services)h(infrastructure)d (should)i(read)g(chapters)g(2,)g(3,)h(and)0 1288 y(10)g(of)g(this)g (document.)29 b(Readers)22 b(who)g(are)g(de)n(v)o(eloping)e(comple)o(x) g(services,)i(and)g(who)g(are)g(f)o(amiliar)g(with)g(XML)g(Schema)g (and/or)0 1388 y(WSDL,)17 b(should)f(read)h(this)g(manual)f(in)h(order) -5 b(.)23 b(This)17 b(will)h(pro)o(vide)c(them)j(with)g(enough)e (information)f(to)j(implement)f(the)h(processing)0 1488 y(model)i(described)g(abo)o(v)o(e.)k(The)o(y)d(can)g(skip)g(probably)e (skip)i(chapters)f(2)h(and)g(10.)0 1634 y Fl(ZSI)27 b Fn(has)f(the)h(capability)e(to)i(process)f(WSDL)h(de\002nitions)f(and)g (XML)h(Schema)e(documents)g(\(described)g(in)i Fk(The)f(W)-8 b(eb)27 b(Services)0 1734 y(Description)i(Langua)o(g)o(e)f Fn(and)h Fk(XMLSc)o(hema)g(1.0)p Fn(\))f(and)i(generate)e(typecodes)h (automatically)-5 b(.)51 b(F)o(or)30 b(more)f(information)e(see)k(the)0 1834 y Fk(User)o(s)22 b(Guide)p Fn(.)p 0 5549 3901 4 v 0 5649 a Fi(2)2981 b(Chapter)23 b(1.)52 b(Introduction)p eop end %%Page: 3 9 TeXDict begin 3 8 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3623 427 y Fh(TW)n(O)p 0 515 V 2993 978 a Ft(Examples)0 1465 y Fn(This)25 b(chapter)f(contains)g(a)i(number)d(of)i(e)o(xamples)f(to) h(sho)n(w)g(of)n(f)f(some)h(of)g Fl(ZSI)p Fn(')-5 b(s)25 b(features.)39 b(It)25 b(is)h(brok)o(en)d(do)n(wn)h(into)h(client-side) 0 1565 y(and)20 b(serv)o(er)n(-side)f(e)o(xamples,)g(and)g(e)o(xplores) g(dif)n(ferent)f(implementation)g(options)i Fl(ZSI)g Fn(pro)o(vides.)0 1892 y Fg(2.1)121 b(Ser)t(v)m(er)33 b(Side)g(Examples)0 2141 y Ff(2.1.1)100 b(Simple)29 b(e)m(xample)0 2344 y Fn(Using)18 b(the)f Fl(ZSI.dispatch)f Fn(module,)h(it)h(is)g (simple)g(to)g(e)o(xpose)e(Python)h(functions)f(as)i(web)g(services.)24 b(Each)17 b(function)f(is)i(in)m(v)n(ok)o(ed)0 2444 y(with)31 b(all)h(the)f(input)g(parameters)e(speci\002ed)i(in)h(the)f(client')-5 b(s)31 b(SO)m(AP)h(request.)57 b(An)o(y)31 b(v)n(alue)f(returned)f(by)i (the)g(function)f(will)i(be)0 2544 y(serialized)20 b(back)f(to)i(the)f (client;)g(multiple)g(v)n(alues)g(can)g(be)g(returned)e(by)i(returning) e(a)j(tuple.)0 2691 y(The)f(follo)n(wing)e(code)i(sho)n(ws)g(some)g (simple)g(services:)236 2929 y Fe(#!/usr/local/bin/python2.4)236 3020 y(#)45 b(SOAP)f(Array)236 3203 y(def)h(hello\(\):)416 3294 y(return)e(["Hello,)h(world"])236 3477 y(def)h(echo\()641 3490 y(*)686 3477 y(args\):)416 3568 y(return)e(args)236 3751 y(def)i(sum\()596 3764 y(*)641 3751 y(args\):)416 3842 y(sum)f(=)h(0)416 3933 y(for)f(i)h(in)f(args:)g(sum)g(+=)h(i)416 4025 y(return)e([sum])236 4207 y(def)i(average\()776 4220 y(*)821 4207 y(args\):)416 4299 y(return)e([sum\()954 4312 y(*)999 4299 y(args\))g(/)i(len\(args\)])236 4481 y(from)f(ZSI)h(import)f(dispatch)236 4573 y(dispatch.AsCGI\(rpc=True\)) 0 4902 y Fn(Each)15 b(function)f(de\002nes)h(a)h(SO)m(AP)g(request,)f (so)h(if)g(this)f(script)h(is)g(installed)g(as)g(a)f(CGI)h(script,)g(a) g(SO)m(AP)h(message)e(can)g(be)g(posted)g(to)g(that)0 5002 y(script')-5 b(s)22 b(URL)g(with)g(an)o(y)e(of)i Fl(hello)p Fn(,)f Fl(echo)p Fn(,)g(or)g Fl(average)g Fn(as)h(the)g(request)f(element,)g(and)g(the)g(v)n(alue)g(returned)f (by)h(the)g(function)0 5101 y(will)32 b(be)g(sent)g(back.)58 b(These)31 b(functions)g(e)o(xpect)f(and)h(return)g(SO)m(AP-ENC:arrayT) -7 b(ype)29 b(instances)j(which)f(are)g(marshalled)g(into)0 5201 y(p)o(ython)17 b Fl(list)i Fn(instances,)g(this)g(script)g (interoperates)e(with)i(the)g Fl(client.Binding)p Fn(.)j(F)o(or)d(more) f(information)e(see)k Fk(Appendix)d(A)p Fn(.)0 5348 y(The)26 b Fl(ZSI)h Fn(CGI)g(dispatcher)e(catches)i(e)o(xceptions)e(and)h(sends) h(back)f(a)h(SO)m(AP)g(f)o(ault.)44 b(F)o(or)27 b(e)o(xample,)f(a)h(f)o (ault)g(will)g(be)g(sent)g(if)g(the)p 0 5549 3901 4 v 3854 5649 a Fi(3)p eop end %%Page: 4 10 TeXDict begin 4 9 bop 0 83 a Fl(hello)20 b Fn(function)e(is)j(gi)n(v)o (en)e(an)o(y)h(ar)o(guments,)e(or)i(if)g(the)g Fl(average)g Fn(function)e(is)j(gi)n(v)o(en)e(a)i(non-inte)o(ger)-5 b(.)0 230 y(Here)17 b(is)i(another)c(e)o(xample)h(b)n(ut)i(using)f(SO)m (AP-ENC:Struct)g(instances)g(which)g(are)g(marshalled)f(into)i(p)o (ython)d Fl(dict)i Fn(instances,)h(this)0 330 y(script)i(interoperates) f(with)h(the)g Fl(client.NamedParamBinding)p Fn(.)h(F)o(or)f(more)g (information)d(see)k Fk(Appendix)d(B)p Fn(.)236 476 y Fe(#!/usr/local/bin/python2.4)236 568 y(#)45 b(SOAP)f(Struct)236 750 y(def)h(hello\(\):)416 842 y(return)e({"value":"Hello,)g(world"}) 236 1024 y(def)i(echo\()641 1037 y(**)731 1024 y(kw\):)416 1116 y(return)e(kw)236 1298 y(def)i(sum\()596 1311 y(**)686 1298 y(kw\):)416 1390 y(sum)f(=)h(0)416 1481 y(for)f(i)h(in)f (kw.values\(\):)f(sum)h(+=)h(i)236 1572 y(return)f({"value":sum})236 1755 y(def)h(average\()776 1768 y(**)866 1755 y(kw\):)236 1846 y(d)g(=)g(sum\()596 1859 y(**)686 1846 y(kw\))416 1938 y(return)e(d["value"])h(=)g(d["value"]/len\(kw\))236 2120 y(from)g(ZSI)h(import)f(dispatch)236 2212 y (dispatch.AsCGI\(rpc=True\))0 2679 y Ff(2.1.2)100 b(lo)o(w)28 b(le)m(v)n(el)g(soap)h(processing)g(e)m(xample)0 2882 y Fn(W)-7 b(e)21 b(will)f(no)n(w)e(sho)n(w)i(a)f(more)g(complete)f(e)o (xample)g(of)h(a)h(rob)n(ust)f(web)g(service)g(implemented)f(at)i(the)f (SO)m(AP)h(layer)-5 b(.)25 b(It)19 b(tak)o(es)h(as)g(input)0 2982 y(a)k(player)f(name)g(and)h(array)f(of)g(inte)o(gers,)h(and)f (returns)g(the)h(a)n(v)o(erage.)35 b(It)24 b(is)h(presented)d(in)i (sections,)h(follo)n(wing)d(the)i(steps)g(detailed)0 3081 y(abo)o(v)o(e.)f(A)e(complete)e(w)o(orking)g(e)o(xample)f(of)i (this)h(service)f(is)h(a)n(v)n(ailable)f(in)g Fk(Appendix)f(C)p Fn(.)0 3228 y(The)h(\002rst)h(section)f(reads)g(in)g(a)h(request,)e (and)h(parses)g(the)g(SO)m(AP)h(header)-5 b(.)p 0 5549 3901 4 v 0 5649 a Fi(4)3050 b(Chapter)24 b(2.)52 b(Examples)p eop end %%Page: 5 11 TeXDict begin 5 10 bop 236 83 a Fe(from)44 b(ZSI)h(import)954 96 y(*)236 174 y(import)f(sys)236 266 y(IN,)h(OUT)f(=)h(sys.stdin,)e (sys.stdout)236 357 y(try:)416 448 y(ps)h(=)h(ParsedSoap\(IN\))236 540 y(except)f(ParseException,)e(e:)416 631 y (OUT.write\(FaultFromZSIException\(e\).A)o(sSOAP\()o(\)\))416 722 y(sys.exit\(1\))236 814 y(except)i(Exception,)f(e:)416 905 y(#)h(Faulted)g(while)g(processing;)f(we)h(assume)g(it's)g(in)h (the)f(header.)416 996 y(OUT.write\(FaultFromException\(e,)39 b(1\).AsSOAP\(\)\))416 1088 y(sys.exit\(1\))236 1270 y(#)45 b(We)f(are)h(not)f(prepared)g(to)g(handle)g(any)g(actors)g(or)g (mustUnderstand)f(elements,)236 1362 y(#)i(so)f(we'll)g(arbitrarily)f (fault)h(back)h(with)f(the)g(first)g(one)g(we)h(found.)236 1453 y(a)g(=)g(ps.WhatActorsArePresent\(\))236 1544 y(if)g(len\(a\):) 416 1636 y(OUT.write\(FaultFromActor\(a[0]\).AsSOA)o(P\(\)\))416 1727 y(sys.exit\(1\))236 1818 y(mu)g(=)f(ps.WhatMustIUnderstand\(\))236 1910 y(if)h(len\(mu\):)416 2001 y(uri,)f(localname)f(=)i(mu[0])416 2092 y(OUT.write\(FaultFromNotUnderstood\(uri)o(,)39 b(localname\).AsSOAP\(\)\))416 2183 y(sys.exit\(1\))0 2470 y Fn(This)18 b(section)f(de\002nes)h(the)f(mappings)g(between)g (Python)f(objects)i(and)f(the)g(SO)m(AP)i(data)e(being)g(transmitted.) 23 b(Recall)c(that)f(according)0 2570 y(to)i(the)h(SO)m(AP)g (speci\002cation,)e(RPC)i(input)f(and)g(output)e(are)j(modeled)d(as)j (a)g(structure.)236 2716 y Fe(class)44 b(Player:)416 2808 y(def)g(__init__\(self,)1267 2821 y(*)1312 2808 y(args\):)595 2899 y(if)g(not)h(len\(args\):)e(return)595 2990 y(self.Name)g(=)i(args[0])595 3082 y(self.Scores)e(=)i(args[1:]) 236 3173 y(Player.typecode)e(=)h(TC.Struct\(Player,)e([)1671 3264 y(TC.String\('Name'\),)1671 3356 y(TC.Array\('Integer',)f (TC.Integer\(\),)i('Scores',)g(undeclared=True\),)1671 3447 y(],)h('GetAverage'\))236 3538 y(class)g(Average:)416 3630 y(def)g(__init__\(self,)e(average=None\):)595 3721 y(self.average)h(=)h(average)236 3812 y(Average.typecode)e(=)j (TC.Struct\(Average,)d([)1671 3904 y(TC.Integer\('average'\),)1671 3995 y(],)i('GetAverageResponse'\))0 4282 y Fn(This)20 b(section)g(parses)h(the)f(input,)f(performs)f(the)j(application-le)n (v)o(el)c(acti)n(vity)-5 b(,)19 b(and)h(serializes)g(the)h(response.)p 0 5549 3901 4 v 0 5649 a Fi(2.1.)52 b(Ser)r(v)n(er)23 b(Side)h(Examples)2843 b(5)p eop end %%Page: 6 12 TeXDict begin 6 11 bop 236 83 a Fe(try:)416 174 y(player)43 b(=)i(ps.Parse\(Player.typecode\))236 266 y(except)f (EvaluateException,)e(e:)416 357 y (OUT.write\(FaultFromZSIException\(e\).A)o(sSOAP\()o(\)\))416 448 y(sys.exit\(1\))236 631 y(try:)416 722 y(total)i(=)g(0)416 814 y(for)g(value)g(in)g(player.Scores:)f(total)h(=)g(total)g(+)h (value)416 905 y(result)e(=)i(Average\(total)e(/)h (len\(player.Scores\)\))416 996 y(sw)g(=)h(SoapWriter\(\))416 1088 y(sw.serialize\(result,)c(Average.typecode\))416 1179 y(sw.close\(\))416 1270 y(OUT.write\(str\(sw\)\))236 1362 y(except)j(Exception,)f(e:)416 1453 y (OUT.write\(FaultFromException\(e,)c(0,)45 b (sys.exc_info\(\)[2]\).AsSOAP\(\)\))416 1544 y(sys.exit\(1\))0 1831 y Fn(In)25 b(the)g Fl(serialize\(\))e Fn(call)j(abo)o(v)o(e,)e (the)h(second)g(parameter)e(is)j(optional,)f(since)g Fl(result)g Fn(is)h(an)f(instance)f(of)h(the)g Fl(Average)0 1930 y Fn(class,)c(and)f(the)g Fl(Average.typecode)e Fn(attrib)n(ute)h(is)i(the)g(typecode)d(for)i(class)h(instances.)0 2215 y Ff(2.1.3)100 b(A)28 b(mod)p 614 2215 30 4 v 37 w(p)m(ython)h(e)m(xample)0 2418 y Fn(The)35 b(Apache)f(module)g Fl(mod_python)g Fn(\(see)h Fl(http://www.modpython.org)p Fn(\))c(embeds)j(Python)g(within)h(the)g(Apache)0 2518 y(serv)o(er)-5 b(.)24 b(In)17 b(order)g(to)h(e)o(xpose)f(operations)f (within)h(a)i(module)d(via)i(mod)p 2046 2518 25 4 v 29 w(p)o(ython,)e(use)i(the)g Fl(dispatch.AsHandler\(\))d Fn(function.)0 2617 y(The)21 b Fl(dispatch.AsHandler\(\))d Fn(function)i(will)i(dispatch)f(requests)g(to)g(an)o(y)g(operation)e (de\002ned)i(in)g(the)h(module)e(you)g(pass)i(it,)0 2717 y(which)h(allo)n(ws)g(for)g(multiple)f(operations)g(to)h(be)g (de\002ned)g(in)g(a)h(module.)32 b(The)23 b(only)g(trick)f(is)j(to)e (use)p 2975 2717 V 3005 2717 V 83 w(import)p 3258 2717 V 3287 2717 V 82 w(to)h(load)e(the)i(XML)0 2817 y(encodings)17 b(your)g(service)i(e)o(xpects.)k(This)c(is)h(a)f(required)e(w)o (orkaround)e(to)k(a)n(v)n(oid)f(the)h(pitf)o(alls)g(of)f(restricted)h (e)o(x)o(ecution)d(with)j(respect)0 2916 y(to)h(XML)h(parsing.)0 3063 y(The)26 b(follo)n(wing)e(is)j(a)g(complete)e(e)o(xample)f(of)i(a) h(simple)f(handler)-5 b(.)42 b(The)25 b(soap)h(operations)f(are)h (implemented)e(in)i(the)g(MyHandler)0 3163 y(module:)236 3401 y Fe(def)45 b(hello\(\):)416 3492 y(return)e({"value":"Hello,)g (world"})236 3675 y(def)i(echo\()641 3688 y(**)731 3675 y(kw\):)416 3766 y(return)e(kw)236 3949 y(def)i(sum\()596 3962 y(**)686 3949 y(kw\):)416 4040 y(sum)f(=)h(0)416 4132 y(for)f(i)h(in)f(kw.values\(\):)f(sum)h(+=)h(i)236 4223 y(return)f({"value":sum})236 4406 y(def)h(average\()776 4419 y(**)866 4406 y(kw\):)236 4497 y(d)g(=)g(sum\()596 4510 y(**)686 4497 y(kw\))416 4588 y(d["value"])e(=)h (d["value"]/len\(kw\))236 4680 y(return)g(d)0 4966 y Fn(Dispatching)62 b(from)g(within)g(mod)p 1119 4966 V 29 w(p)o(ython)f(is)j(achie)n(v)o(ed)d(by)h(passing)h(the)g (aforementined)d(MyHandler)h(module)g(to)0 5066 y Fl (dispatch.AsHandler\(\))p Fn(.)22 b(The)e(follo)n(wing)e(code)i(e)o (xposes)f(the)h(operations)f(de\002ned)g(in)h(MyHandler)f(via)h(SO)m (AP:)p 0 5549 3901 4 v 0 5649 a Fi(6)3050 b(Chapter)24 b(2.)52 b(Examples)p eop end %%Page: 7 13 TeXDict begin 7 12 bop 236 83 a Fe(from)44 b(ZSI)h(import)f(dispatch) 236 174 y(from)g(mod_python)g(import)f(apache)236 357 y(import)h(MyHandler)236 448 y(mod)h(=)f (__import__\('encodings.utf_8',)c(globals\(\),)j(locals\(\),)h(')2837 461 y(*)2882 448 y('\))236 540 y(mod)h(=)f (__import__\('encodings.utf_16_be',)39 b(globals\(\),)44 b(locals\(\),)f(')3016 553 y(*)3061 540 y('\))236 722 y(def)i(handler\(req\):)416 814 y (dispatch.AsHandler\(modules=\(MyHandle)o(r,\),)39 b(request=req,)j (rpc=True\))416 905 y(return)h(apache.OK)0 1354 y Fg(2.2)121 b(Client)34 b(Side)f(Examples)0 1603 y Ff(2.2.1)100 b(Simple)29 b(Example)0 1806 y Fl(ZSI)22 b Fn(pro)o(vides)e(tw)o(o)i(w)o(ays)g(for) f(a)h(client)g(to)g(interacti)n(v)o(e)e(with)i(a)g(serv)o(er:)28 b(the)22 b Fl(Binding)f Fn(or)g Fl(NamedParamBinding)e Fn(class)k(and)0 1906 y(the)h Fl(ServiceProxy)d Fn(class.)36 b(The)24 b(\002rst)g(is)g(useful)f(when)g(the)h(operations)e(to)h(be)h (in)m(v)n(ok)o(ed)e(are)h(not)g(de\002ned)g(in)h(WSDL)g(or)f(when)0 2005 y(only)c(simple)h(Python)f(datatypes)g(are)h(used;)g(the)g Fl(ServiceProxy)e Fn(class)j(can)e(be)h(used)g(to)g(parse)g(WSDL)h (de\002nitions)e(in)h(order)e(to)0 2105 y(determine)h(ho)n(w)g(to)i (serialize)f(and)g(parse)g(the)g(SO)m(AP)h(messages.)0 2252 y(During)k(de)n(v)o(elopment,)f(it)j(is)f(often)g(useful)f(to)h (record)f(\223pack)o(et)g(traces\224)h(of)f(the)h(SO)m(AP)h(messages)f (being)f(e)o(xchanged.)40 b(Both)26 b(the)0 2351 y Fl(Binding)17 b Fn(and)h Fl(ServiceProxy)e Fn(classes)j(pro)o(vide)d(a)j Fl(tracefile)e Fn(parameter)f(to)i(specify)g(an)g(output)f(stream)h (\(such)f(as)i(a)f(\002le\))0 2451 y(to)i(capture)f(messages.)25 b(It)c(can)f(be)g(particularly)f(useful)g(when)h(deb)n(ugging)d(une)o (xpected)h(SO)m(AP)j(f)o(aults.)0 2598 y(The)g(\002rst)h(e)o(xample)e (pro)o(vided)e(belo)n(w)j(demonstrates)f(ho)n(w)g(to)i(use)f(the)g Fl(NamedParamBinding)e Fn(class)j(to)g(connect)d(to)j(a)f(remote)0 2698 y(service)f(and)g(perform)e(an)i(operation.)236 3027 y Fe(#!/usr/bin/env)43 b(python)236 3118 y(import)h(sys,time)236 3210 y(from)g(ZSI.client)g(import)f(NamedParamBinding)f(as)j(NPBinding) 236 3392 y(b)g(=)g(NPBinding\(url='http://127.0.0.1/cgi-)o(bin/so)o (apstru)o(ct',)39 b(tracefile=sys.stdout\))236 3484 y(print)44 b("Hello:)g(",)g(b.hello\(\))236 3575 y(print)g("Echo:)g(",)h (b.echo\(name="josh",)c(year=2006,)i(pi=3.14,)h(time=time.gmtime\(\)\)) 236 3666 y(print)g("Sum:)g(",)h(b.sum\(one=1,)e(two=2,)g(three=3\))236 3758 y(print)h("Average:)g(",)g(b.average\(one=100,)e(two=200,)h (three=300,)g(four=400\))0 4316 y Ff(2.2.2)100 b(Comple)m(x)29 b(Example:)35 b(pic)n(kler)-5 b(.p)m(y)0 4519 y Fn(If)23 b(the)g(operation)e(in)m(v)n(ok)o(ed)g(returns)h(a)h(Comple)o(xT)-7 b(ype,)21 b(typecode)g(information)f(must)j(be)g(pro)o(vided)d(in)j (order)f(to)h(tell)g Fl(ZSI)g Fn(ho)n(w)f(to)0 4619 y(deserialize)e (the)g(response.)k(Here)c(is)h(a)g(sample)f(serv)o(er)n(-side)f (implementation)f(\(for)h(the)h(complete)f(e)o(xample)g(see)i Fk(Appendix)d(D)p Fn(\):)p 0 5549 3901 4 v 0 5649 a Fi(2.2.)52 b(Client)24 b(Side)h(Examples)2875 b(7)p eop end %%Page: 8 14 TeXDict begin 8 13 bop 236 174 a Fe(class)44 b(Person:)326 266 y(def)g(__init__\(self,)f(name=None,)g(age=0\):)416 357 y(self.name)g(=)i(name)416 448 y(self.age)e(=)i(age)236 631 y(Person.typecode)e(=)h(TC.Struct\(Person,)416 722 y([TC.String\('name'\),)460 814 y(TC.InonNegativeInteger\('age'\)],)416 905 y('myApp:Person'\))236 1088 y(#)h(my)f(web)h(service)e(that)i (returns)e(a)i(complex)e(structure)236 1179 y(def)i(getPerson\(name\):) 326 1270 y(fp)f(=)h(open\('\045s.person.pickle',)c(\045)k(name,)e ('r'\))326 1362 y(return)h(pickle.load\(fp\))236 1544 y(#)h(my)f(web)h(service)e(that)i(accepts)e(a)i(complex)e(structure)236 1636 y(def)i(savePerson\(person\):)326 1727 y(fp)f(=)h (open\('\045s.person.pickle')c(\045)k(person.name,)d('w'\))326 1818 y(pickle\(person,)g(fp\))326 1910 y(fp.close\(\))0 2196 y Fn(In)25 b(order)e(for)i Fl(ZSI)g Fn(to)g(transparently)e (deserialize)h(the)h(returned)e(comple)o(x)g(type)i(into)g(a)g Fl(Person)f Fn(instance,)i(a)f(module)f(de\002ning)0 2296 y(the)d(class)g(and)g(its)g(typecode)e(can)i(be)g(passed)f(into)h (the)g Fl(Binding)p Fn(.)26 b(It)21 b(is)g(also)g(possible)g(to)g(e)o (xplicitly)e(tell)j Fl(ZSI)f Fn(what)f(typecode)f(to)0 2395 y(use)h(by)g(passing)g(it)h(as)g(a)f(parameter)f(to)h(the)h Fl(Binding.Receive\(\))c Fn(method.)0 2542 y(The)j(follo)n(wing)e (fragment)h(sho)n(ws)h(both)f(styles:)236 2780 y Fe(import)44 b(sys)236 2872 y(from)g(ZSI.client)g(import)f(Binding)236 2963 y(from)h(MyComplexTypes)f(import)h(Person)236 3146 y(b)h(=)g(Binding\(url='http://localhost/test3/)o(pickle)o(r.py',)38 b(tracefile=sys.stdout\))236 3237 y(person)44 b(=)h (Person\('christopher',)c(26\))236 3328 y(rsp)k(=)f (b.savePerson\(person\))0 3706 y Fn(Because)19 b(the)g(returned)e (comple)o(x)h(type)g(is)i(de\002ned)e(in)h(a)h(class)g(present)e(in)h Fk(typesmodule)p Fn(,)f(transparent)f(deserialization)h(is)i(possible.) 0 3806 y(When)g(sending)f(comple)o(x)f(types)i(to)h(the)f(serv)o(er)m (,)f(it)i(is)g(not)f(necessary)f(to)i(list)g(the)f(module)f(in)h Fk(typesmodule)p Fn(:)p 0 5549 3901 4 v 0 5649 a Fi(8)3050 b(Chapter)24 b(2.)52 b(Examples)p eop end %%Page: 9 15 TeXDict begin 9 14 bop 236 174 a Fe(import)44 b(sys)236 266 y(import)g(MyComplexTypes)236 357 y(from)g(ZSI.client)g(import)f (NamedParamBinding)f(as)j(NPBinding,)e(Binding)236 448 y(from)h(ZSI)h(import)f(TC)236 631 y(kw)h(=)f ({'url':'http://localhost/test3/pickler.py)o(',)39 b ('tracefile':sys.stdout})236 722 y(b)45 b(=)g(NPBinding\()866 735 y(**)956 722 y(kw\))236 814 y(rsp)g(=)f (b.getPerson\(name='christopher'\))236 905 y(assert)g(type\(rsp\))f(is) i(dict,)f('expecting)f(a)i(dict')236 996 y(assert)f (rsp['Person']['name'])d(==)k('christopher',)d('wrong)i(person')236 1179 y(b)h(=)g(NPBinding\(typesmodule=MyComplexTypes)o(,)2119 1192 y(**)2209 1179 y(kw\))236 1270 y(rsp)g(=)f (b.getPerson\(name='christopher'\))236 1362 y(assert)g (isinstance\(rsp['Person'],)d(MyComplexTypes.Person\),)g(\()416 1453 y('expecting)i(instance)g(of)i(\045s')f (\045MyComplexTypes.Person\))236 1636 y(b)h(=)g (Binding\(typesmodule=MyComplexTypes,)2029 1649 y(**)2119 1636 y(kw\))236 1727 y(class)f(Name\(str\):)416 1818 y(typecode)f(=)i(TC.String\("name"\))236 2001 y(rsp)g(=)f (b.getPerson\(Name\('christopher'\)\))236 2092 y(assert)g (isinstance\(rsp['Person'],)d(MyComplexTypes.Person\),)g(\()416 2183 y('expecting)i(instance)g(of)i(\045s')f (\045MyComplexTypes.Person\))p 0 5549 3901 4 v 0 5649 a Fi(2.2.)52 b(Client)24 b(Side)h(Examples)2875 b(9)p eop end %%Page: 10 16 TeXDict begin 10 15 bop 0 5549 3901 4 v 0 5649 a Fi(10)p eop end %%Page: 11 17 TeXDict begin 11 16 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3495 427 y Fh(THREE)p 0 515 V 2890 978 a Ft(Exceptions)0 1452 y Fo(exception)19 b Fj(ZSIException)208 1551 y Fn(Base)i(class)g(for)e (all)i(ZSI)f(Exceptions,)f(it)i(is)g(a)g(subtype)e(of)h(the)g(Python)f Fl(Exception)g Fn(class.)0 1698 y Fo(exception)g Fj(ParseException)208 1798 y Fl(ZSI)26 b Fn(can)g(raise)h(this)g(e)o(xception)d(while)j (creating)e(a)i Fl(ParsedSoap)e Fn(object.)43 b(It)27 b(is)h(a)e(subtype)g(of)g(the)g Fl(ZSIException)208 1897 y Fn(class.)e(The)17 b(string)f(form)g(of)g(a)h Fl(ParseException)e Fn(object)h(consists)h(of)g(a)g(line)g(of)f(human-readable)d(te)o(xt.) 24 b(If)16 b(the)h(backtrace)208 1997 y(is)k(a)n(v)n(ailable,)e(it)i (will)g(be)f(concatenated)e(as)j(a)g(second)e(line.)0 2144 y(The)h(follo)n(wing)e(attrib)n(utes)j(are)f(read-only:)0 2291 y Fj(inheader)208 2390 y Fn(A)g(boolean)f(that)h(indicates)g(if)h (the)f(error)f(w)o(as)i(detected)e(in)i(the)f(SO)m(AP)h Fl(Header)e Fn(element.)0 2537 y Fj(str)208 2637 y Fn(A)h(te)o(xt)g (string)g(describing)f(the)h(error)-5 b(.)0 2784 y Fj(trace)208 2883 y Fn(A)23 b(te)o(xt)g(string)g(containing)f(a)h(backtrace)f(to)i (the)f(error)-5 b(.)33 b(This)24 b(may)e(be)i Fl(None)f Fn(if)g(it)h(w)o(as)g(not)f(possible,)g(such)g(as)h(when)f(there)208 2983 y(w)o(as)e(a)f(general)f(DOM)i(e)o(xception,)d(or)i(when)f(the)h Fl(str)h Fn(te)o(xt)f(is)h(belie)n(v)o(ed)e(to)h(be)g(suf)n(\002cient.) 0 3130 y Fo(exception)f Fj(EvaluateException)208 3229 y Fn(This)g(e)o(xception)e(is)k(similar)e(to)h Fl(ParseException)p Fn(,)d(e)o(xcept)h(that)i Fl(ZSI)f Fn(may)g(raise)g(it)h(while)g(con)m (v)o(erting)c(between)j(SO)m(AP)208 3329 y(and)g(local)h(Python)f (objects.)0 3476 y(The)h(follo)n(wing)e(attrib)n(utes)j(are)f (read-only:)0 3623 y Fj(str)208 3722 y Fn(A)g(te)o(xt)g(string)g (describing)f(the)h(error)-5 b(.)0 3869 y Fj(trace)208 3969 y Fn(A)20 b(te)o(xt)g(backtrace,)f(as)i(described)e(abo)o(v)o(e)f (for)i Fl(ParseException)p Fn(.)p 0 5549 3901 4 v 3808 5649 a Fi(11)p eop end %%Page: 12 18 TeXDict begin 12 17 bop 0 5549 3901 4 v 0 5649 a Fi(12)p eop end %%Page: 13 19 TeXDict begin 13 18 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3561 427 y Fh(FOUR)p 0 515 V 3234 978 a Ft(Utilities)0 1457 y Fl(ZSI)20 b Fn(de\002nes)g(some)g(utility)g(methods)f(that)i(general) e(applications)g(may)h(w)o(ant)g(to)g(use.)0 1604 y Fj(Version)p Fl(\(\))208 1703 y Fn(Returns)f(a)h(three-element)e(tuple)h(containing) e(the)j(numbers)e(representing)f(the)j(major)m(,)e(minor)m(,)g(and)h (release)h(identifying)e(the)208 1803 y Fl(ZSI)i Fn(v)o(ersion.)49 b(Ne)n(w)21 b(in)f(v)o(ersion)f(1.1.)0 2130 y Fg(4.1)121 b(Lo)n(w-Le)l(v)m(el)35 b(Utilities)0 2363 y Fl(ZSI)26 b Fn(also)g(de\002nes)g(some)f(lo)n(w-le)n(v)o(el)g(utilities)i(for)e (its)i(o)n(wn)e(use)h(that)g(start)g(with)g(a)h(leading)e(underscore)e (and)j(must)f(be)h(imported)0 2463 y(e)o(xplicitly)-5 b(.)24 b(The)o(y)19 b(are)h(documented)d(here)j(because)f(the)o(y)h (can)g(be)g(useful)g(for)f(de)n(v)o(eloping)f(ne)n(w)i(typecode)e (classes.)0 2610 y(These)h(functions)e(are)i(mostly)g(used)f(in)h(in)h Fl(parse)e Fn(methods)g(and)g(the)h Fl(ParsedSoap)f Fn(class.)25 b(The)19 b(serialization)f(routines)g(use)i(the)0 2709 y Fl(ElementProxy)f Fn(class)i(to)f(encapsulate)f(common)f(DOM-le)n(v)o (el)i(operations.)0 2856 y(Some)f Fl(lambda)p Fn(')-5 b(s)18 b(are)h(de\002ned)f(so)h(that)g(some)g(DOM)g(accessors)f(will)i (return)e(an)g(empty)g(list)i(rather)e(than)h Fl(None)p Fn(.)24 b(This)19 b(means)f(that)0 2956 y(rather)h(than)h(writing:)236 3102 y Fe(if)45 b(elt.childNodes:)371 3194 y(for)f(N)h(in)f (elt.childNodes:)505 3285 y(...)0 3524 y Fn(One)20 b(can)g(write:)236 3671 y Fe(for)45 b(N)f(in)h(_children\(elt\):)371 3763 y(...)0 4049 y Fn(Other)20 b Fl(lambda)p Fn(')-5 b(s)20 b(return)f(SO)m(AP-related)g(attrib)n(utes)i(from)e(an)h(element,)f(or) h Fl(None)g Fn(if)h(not)e(present.)0 4196 y Fj(_attrs)p Fl(\()p Fk(element)q Fl(\))208 4296 y Fn(Returns)h(a)g(list)h(of)f(all) h(attrib)n(utes)f(of)g(the)g(speci\002ed)g Fl(element)p Fn(.)0 4442 y Fj(_backtrace)p Fl(\()p Fk(elt,)e(dom)p Fl(\))208 4542 y Fn(This)23 b(function)f(returns)h(a)h(te)o(xt)g (string)f(that)h(traces)g(a)g(\223path\224)f(from)f Fl(dom)p Fn(,)j(a)f(DOM)g(root,)f(to)h Fl(elt)p Fn(,)g(an)g(element)f(within)g (that)208 4642 y(document,)18 b(in)i(XP)o(ath)g(syntax.)0 4789 y Fj(_child_elements)p Fl(\()p Fk(element)q Fl(\))208 4888 y Fn(Returns)g(a)g(list)h(of)f(all)h(children)e(elements)h(of)g (the)g(speci\002ed)g Fl(element)p Fn(.)0 5035 y Fj(_children)p Fl(\()p Fk(element)q Fl(\))208 5135 y Fn(Returns)g(a)g(list)h(of)f(all) h(children)e(of)h(the)g(speci\002ed)g Fl(element)p Fn(.)p 5 5282 25 4 v 30 5282 a(cop)o(yright)p 373 5282 V 48 w(empty)p 612 5282 V 28 w(nsuri)p 807 5282 V 29 w(list)0 5381 y Fj(_find_arraytype)p Fl(\()p Fk(element)q Fl(\))p 0 5549 3901 4 v 3808 5649 a Fi(13)p eop end %%Page: 14 20 TeXDict begin 14 19 bop 208 83 a Fn(The)19 b(v)n(alue)h(of)g(the)g(SO)m (AP)h Fl(arrayType)e Fn(attrib)n(ute.)50 b(Ne)n(w)21 b(in)f(v)o(ersion)f(1.2.)0 230 y Fj(_find_attr)p Fl(\()p Fk(element,)f(name)p Fl(\))208 330 y Fn(The)h(v)n(alue)h(of)g(the)g (unquali\002ed)e Fl(name)i Fn(attrib)n(ute.)0 476 y Fj(_find_attrNS)p Fl(\()p Fk(element,)d(namespaceURI,)h(localName)p Fl(\))208 576 y Fn(The)h(v)n(alue)h(of)g(a)g Fl(name)g Fn(attrib)n(ute)g(in)h(a)f (namespace)f Fl(namespaceURI)p Fn(.)0 723 y Fj(_find_attrNodeNS)p Fl(\()p Fk(element,)e(namespaceURI,)g(localName)p Fl(\))208 823 y Fn(W)-7 b(orks)20 b(just)h(lik)o(e)g Fl(_find_attrNS)p Fn(,)d(b)n(ut)i(this)h(function)e(grabs)g(the)i(attrib)n(ute)f(Node)f (to)i(distinquish)e(between)g(an)i(unspeci-)208 922 y(\002ed)f(attrib)n (ute\(None\))e(and)h(one)h(set)h(to)f(empty)g(string\(\224\224\).)0 1069 y Fj(_find_default_namespace)p Fl(\()p Fk(element)q Fl(\))208 1169 y Fn(Returns)g(the)g(v)n(alue)f(of)h(the)g(def)o(ault)g (namespace.)0 1316 y Fj(_find_encstyle)p Fl(\()p Fk(element)q Fl(\))208 1415 y Fn(The)f(v)n(alue)h(of)g(the)g(SO)m(AP)h Fl(encodingStyle)d Fn(attrib)n(ute.)0 1562 y Fj(_find_href)p Fl(\()p Fk(element)q Fl(\))208 1662 y Fn(The)h(v)n(alue)h(of)g(the)g (unquali\002ed)e Fl(href)i Fn(attrib)n(ute.)0 1808 y Fj(_find_type)p Fl(\()p Fk(element)q Fl(\))208 1908 y Fn(The)f(v)n(alue)h(of)g(the)g(XML)g(Schema)g Fl(type)g Fn(attrib)n(ute.)0 2055 y Fj(_find_xmlns_prefix)p Fl(\()p Fk(element,)c(pr)m(e\002x)p Fl(\))208 2155 y Fn(The)j(v)n(alue)h(of)g (the)g(xmlns:pre\002x)f Fl(type)h Fn(attrib)n(ute.)0 2301 y Fj(_find_xsi_attr)p Fl(\()p Fk(element,)d(attrib)n(ute)p Fl(\))208 2401 y Fn(Find)j(the)g(attrib)n(ute)g(in)g(an)o(y)f(of)h(the) g(XMLSchema)g(namespaces.)0 2548 y Fj(_get_element_nsuri_name)p Fl(\()p Fk(element)q Fl(\))208 2648 y Fn(Returns)g(a)g Fl(\(namespace,name\))e Fn(tuple)i(representing)e(the)i(element)g(tag.) 0 2794 y Fj(_get_idstr)p Fl(\()p Fk(obj)p Fl(\))208 2894 y Fn(Substitute)g(for)h Fl(id)g Fn(function.)k(Python)20 b(2.3.x)g(generates)g(a)h Fl(FutureWarning)e Fn(for)i(ne)o(gati)n(v)o (e)e(IDs,)i(so)g(we)h(use)f(a)g(dif)n(ferent)208 2994 y(pre\002x)e(character)g(to)h(ensure)g(uniqueness,)e(and)i(call)g (abs\(\))g(to)h(a)n(v)n(oid)e(the)i(w)o(arning.)0 3141 y Fj(_get_postvalue_from_absoluteURI)p Fl(\()p Fk(url)p Fl(\))208 3240 y Fn(Returns)f(POST)g(v)n(alue)g(from)f Fl(url)p Fn(,)h(and)g(caches)g(these)g(v)n(alues.)0 3387 y Fj(_resolve_prefix)p Fl(\()p Fk(element,)d(pr)m(e\002x)p Fl(\))208 3487 y Fn(resolv)o(e)h Fl(prefix)h Fn(to)h(a)g(namespaceURI.) e(If)h Fl(None)g Fn(or)h(empty)e Fl(str)p Fn(,)i(return)e(def)o(ault)h (namespace)f(or)h Fl(None)h Fn(if)g(not)f(de\002ned.)0 3634 y Fj(_valid_encoding)p Fl(\()p Fk(elt)q Fl(\))208 3733 y Fn(Return)24 b(true)h(if)g(the)g(element)f Fl(elt)h Fn(has)g(a)h(SO)m(AP)f(encoding)e(that)i(can)g(be)g(handled)e(by)i Fl(ZSI)g Fn(\(currently)d(Section)j(5)g(of)g(the)208 3833 y(SO)m(AP)c(1.1)e(speci\002cation)h(or)f(an)i(empty)e(encoding)f (for)i(XML\).)p 0 5549 3901 4 v 0 5649 a Fi(14)3101 b(Chapter)24 b(4.)52 b(Utilities)p eop end %%Page: 15 21 TeXDict begin 15 20 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3634 427 y Fh(FIVE)p 0 515 V 709 978 a Ft(The)57 b Fd(ParsedSoap)g Ft(module)g(\227)g(basic)2224 1227 y(message)g(handling)0 1717 y Fn(This)20 b(class)i(represents)d(an)h(input)f(stream)h(that)h (has)f(been)g(parsed)f(as)i(a)g(SO)m(AP)g(message.)0 1864 y Fo(class)g Fj(ParsedSoap)p Fl(\()p Fk(input)q Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 1963 y Fn(Creates)26 b(a)g Fl(ParsedSoap)f Fn(object)g(from)g(the)h (pro)o(vided)d(input)j(source.)41 b(If)26 b Fl(input)f Fn(is)i(not)f(a)g(string,)h(then)e(it)i(must)f(be)g(an)208 2063 y(object)19 b(with)i(a)f Fl(read\(\))g Fn(method)f(that)h (supports)f(the)h(standard)f(Python)g(\223\002le)i(read\224)f (semantics.)208 2196 y(The)f(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o (guments)g(may)i(be)g(used:)303 2325 y Fo(K)n(eyw)o(ord)p 900 2355 4 100 v 322 w(Default)p 1262 2355 V 98 w(Description)p 254 2358 3601 4 v 303 2428 a Fl(envelope)p 900 2458 4 100 v 280 w(True)p 1262 2458 V 130 w Fn(e)o(xpect)g(a)g(SO)m(AP)h(En)m (v)o(elope)303 2528 y Fl(keepdom)p 900 2856 4 399 v 305 w(False)p 1262 2856 V 105 w Fn(Do)54 b(not)g(release)f(the)h(DOM)g (when)f(this)i(object)e(is)i(destro)o(yed.)124 b(T)-7 b(o)54 b(ac-)1313 2627 y(cess)42 b(the)e(DOM)g(object,)k(use)d(the)f Fl(GetDomAndReader\(\))e Fn(method.)83 b(The)1313 2727 y(reader)45 b(object)g(is)i(necessary)e(to)g(properly)f(free)h(the)h (DOM)g(structure)e(using)1313 2827 y Fl(reader.releaseNode\(dom\))p Fn(.)j(Ne)n(w)21 b(in)f(v)o(ersion)f(1.2.)303 2926 y Fl(readerclass)p 900 3056 4 200 v 130 w(None)p 1262 3056 V 130 w Fn(Class)26 b(used)d(to)h(create)g(DOM-creating)e(XML)i (readers;)h(described)e(belo)n(w)-5 b(.)71 b(Ne)n(w)1313 3026 y(in)21 b(v)o(ersion)e(1.2.)303 3125 y Fl(resolver)p 900 3155 4 100 v 280 w(None)p 1262 3155 V 130 w Fn(V)-9 b(alue)20 b(for)g(the)g Fl(resolver)f Fn(attrib)n(ute;)h(see)h(belo)n (w)-5 b(.)303 3225 y Fl(trailers)p 900 3255 V 255 w(False)p 1262 3255 V 105 w Fn(Allo)n(w)21 b(trailing)e(data)h(elements)g(to)h (appear)e(after)g(the)i Fl(Body)p Fn(.)0 3367 y(The)f(follo)n(wing)e (attrib)n(utes)j(of)e(a)i Fl(ParsedSoap)e Fn(are)h(read-only:)0 3514 y Fj(body)208 3614 y Fn(The)27 b(root)h(of)f(the)h(SO)m(AP)h Fl(Body)f Fn(element.)48 b(Using)28 b(the)g Fl(GetElementNSdict\(\))d Fn(method)i(on)h(this)g(attrib)n(ute)g(can)g(be)208 3713 y(useful)19 b(to)i(get)f(a)g(dictionary)f(to)h(be)g(used)g(with)h(the)f Fl(SoapWriter)f Fn(class.)0 3860 y Fj(body_root)208 3960 y Fn(The)j(element)f(that)i(contains)e(the)i(SO)m(AP)g(serialization)e (root;)i(that)g(is,)g(the)g(element)e(in)i(the)f(SO)m(AP)h Fl(Body)f Fn(that)h(\223starts)g(of)n(f)5 b(\224)208 4059 y(the)20 b(data.)0 4206 y Fj(data_elements)208 4306 y Fn(A)g(\(possibly)f(empty\))g(list)j(of)e(all)g(child)g(elements)g (of)g(the)g Fl(Body)g Fn(other)g(than)f(the)h(root.)0 4453 y Fj(header)208 4552 y Fn(The)h(root)h(of)g(the)g(SO)m(AP)h Fl(Header)f Fn(element.)30 b(Using)22 b(the)g Fl(GetElementNSdict\(\))e Fn(method)g(on)i(this)h(attrib)n(ute)f(can)g(be)208 4652 y(useful)d(to)i(get)f(a)g(dictionary)f(to)h(be)g(used)g(with)h(the)f Fl(SoapWriter)f Fn(class.)0 4799 y Fj(header_elements)208 4899 y Fn(A)h(\(possibly)f(empty\))g(list)j(of)e(all)g(elements)g(in)h (the)f(SO)m(AP)h Fl(Header)p Fn(.)0 5045 y Fj(trailer_elements)208 5145 y Fn(Returns)j(a)h(\(possibly)e(empty\))g(list)j(of)e(all)h (elements)f(follo)n(wing)e(the)j Fl(Body)p Fn(.)37 b(If)24 b(the)h Fl(trailers)e Fn(k)o(e)o(yw)o(ord)g(w)o(as)i(not)f(used)208 5245 y(when)19 b(the)h(object)g(w)o(as)h(constructed,)d(this)j(attrib)n (ute)f(will)h(not)f(be)g(instantiated)f(and)h(retrie)n(ving)e(it)j (will)g(raise)g(an)f(e)o(xception.)0 5392 y(The)g(follo)n(wing)e (attrib)n(ute)i(may)g(be)g(modi\002ed:)p 0 5549 3901 4 v 3808 5649 a Fi(15)p eop end %%Page: 16 22 TeXDict begin 16 21 bop 0 83 a Fj(resolver)208 183 y Fn(If)24 b(not)g Fl(None)p Fn(,)i(this)f(attrib)n(ute)f(can)h(be)f(in)m (v)n(ok)o(ed)f(to)i(handle)f(absolute)g Fl(href)p Fn(')-5 b(s)25 b(in)f(the)h(SO)m(AP)h(data.)38 b(It)25 b(will)g(be)g(in)m(v)n (ok)o(ed)e(as)208 282 y(follo)n(ws:)208 415 y Fj(resolver)p Fl(\()p Fk(uri,)18 b(tc,)j(ps,)f(**k)o(e)n(ywor)m(ds)p Fl(\))390 515 y Fn(The)i Fl(uri)g Fn(parameter)f(is)i(the)f(URI)h(to)g (resolv)o(e.)30 b(The)22 b Fl(tc)g Fn(parameter)f(is)i(the)f(typecode)f (that)h(needs)g(to)g(resolv)o(e)g Fl(href)p Fn(;)390 614 y(this)f(may)e(be)h(needed)f(to)h(properly)e(interpret)g(the)i (content)f(of)h(a)h(MIME)e(bodypart,)f(for)h(e)o(xample.)k(The)d Fl(ps)g Fn(parameter)390 714 y(is)h(the)f Fl(ParsedSoap)e Fn(object)i(that)g(is)g(in)m(v)n(oking)e(the)i(resolution)e(\(this)i (allo)n(ws)h(a)f(single)g(resolv)o(er)e(instance)i(to)g(handle)390 814 y(multiple)g(SO)m(AP)h(parsers\).)390 930 y(F)o(ailure)g(to)h (resolv)o(e)f(the)h(URI)g(should)f(result)g(in)h(an)g(e)o(xception)e (being)g(raised.)30 b(If)21 b(there)g(is)i(no)e(content,)g(return)g Fl(None)p Fn(;)390 1029 y(this)26 b(is)g(not)f(the)g(same)g(as)h(an)f (empty)f(string.)40 b(If)25 b(there)f(is)i(content,)f(the)h(data)f (returned)e(should)h(be)h(in)g(a)h(form)e(under)n(-)390 1129 y(standable)c(by)f(the)i(typecode.)0 1276 y(The)f(follo)n(wing)e (methods)i(are)g(a)n(v)n(ailable:)0 1423 y Fj(Backtrace)p Fl(\()p Fk(elt)q Fl(\))208 1522 y Fn(Returns)g(a)g(human-readable)d (\223trace\224)j(from)f(the)h(document)e(root)i(to)g(the)g(speci\002ed) g(element.)0 1669 y Fj(FindLocalHREF)p Fl(\()p Fk(hr)m(ef)o(,)e(elt)q Fl(\))208 1769 y Fn(Returns)28 b(the)g(element)g(that)g(has)h(an)f Fl(id)h Fn(attrib)n(ute)f(whose)g(v)n(alue)f(is)j(speci\002ed)e(by)g (the)g Fl(href)g Fn(fragment)f(identi\002er)-5 b(.)49 b(The)208 1869 y Fl(href)37 b Fk(must)g Fn(be)h(a)f(fragment)f (reference)g(\227)h(that)h(is,)k(it)c(must)g(start)f(with)h(a)g(pound)d (sign.)76 b(This)38 b(method)e(raises)i(an)208 1968 y Fl(EvaluateException)28 b Fn(e)o(xception)g(if)j(the)g(element)f(isn')o (t)g(found.)55 b(It)31 b(is)g(mainly)f(for)g(use)h(by)f(the)h(parsing)f (methods)208 2068 y(in)20 b(the)g Fl(TypeCode)f Fn(module.)0 2215 y Fj(GetElementNSdict)p Fl(\()p Fk(elt)q Fl(\))208 2314 y Fn(Return)i(a)i(dictionary)e(for)g(all)i(the)g(namespace)e (entries)h(acti)n(v)o(e)g(at)h(the)f(current)f(element.)31 b(Each)22 b(dictionary)e(k)o(e)o(y)i(will)h(be)g(the)208 2414 y(pre\002x)c(and)h(the)g(v)n(alue)f(will)i(be)f(the)h(namespace)e (URI.)0 2561 y Fj(GetMyHeaderElements)p Fl(\()p Fc([)p Fk(actorlist=None)12 b Fc(])p Fl(\))208 2660 y Fn(Returns)31 b(a)h(list)g(of)f(all)i(elements)e(in)g(the)h Fl(Header)f Fn(that)g(are)h(intended)e(for)g Fk(this)i Fn(SO)m(AP)h(processor)-5 b(.)58 b(This)31 b(includes)g(all)208 2760 y(elements)22 b(that)i(either)f(ha)n(v)o(e)f(no)h(SO)m(AP)h Fl(actor)f Fn(attrib)n(ute,)g(or)g(whose)g(v)n(alue)g(is)h(either)f(the)g(special) g(\223ne)o(xt)g(actor\224)f(v)n(alue)h(or)208 2860 y(in)d(the)g Fl(actorlist)f Fn(list)i(of)f(URI')-5 b(s.)0 3007 y Fj(GetDomAndReader) p Fl(\(\))208 3106 y Fn(Returns)24 b(a)h(tuple)g(containing)e(the)h (dom)g(and)g(reader)g(objects,)i Fl(\(dom,)49 b(reader\))p Fn(.)37 b(Unless)26 b(k)o(eepdom)d(is)i(true,)h(the)e(dom)208 3206 y(and)c(reader)h(objects)g(will)h(go)f(out)g(of)g(scope)g(when)g (the)h(P)o(arsedSoap)e(instance)h(is)h(deleted.)28 b(If)21 b(k)o(eepdom)f(is)i(true,)f(the)h(reader)208 3305 y(object)d(is)i (needed)e(to)i(properly)d(clean)i(up)f(the)i(dom)e(tree)h(with)g Fl(reader.releaseNode\(dom\))p Fn(.)0 3452 y Fj(IsAFault)p Fl(\(\))208 3552 y Fn(Returns)g(true)f(if)i(the)f(message)g(is)h(a)g (SO)m(AP)g(f)o(ault.)0 3699 y Fj(Parse)p Fl(\()p Fk(how)p Fl(\))208 3798 y Fn(P)o(arses)38 b(the)f(SO)m(AP)i Fl(Body)e Fn(according)e(to)j(the)g Fl(how)f Fn(parameter)m(,)j(and)d(returns)g (a)h(Python)e(object.)76 b(If)38 b Fl(how)f Fn(is)i(not)e(a)208 3898 y Fl(TC.TypeCode)18 b Fn(object,)i(then)f(it)i(should)e(be)i(a)f (Python)f(class)i(object)f(that)g(has)h(a)f Fl(typecode)g Fn(attrib)n(ute.)0 4045 y Fj(ResolveHREF)p Fl(\()p Fk(uri,)e(tc)p Fc([)p Fk(,)i(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4145 y Fn(This)24 b(method)f(is)i(in)m(v)n(ok)o(ed)e(to)h(resolv)o(e)f (an)i(absolute)e(URI.)i(If)f(the)g(typecode)f Fl(tc)h Fn(has)h(a)f Fl(resolver)g Fn(attrib)n(ute,)g(it)h(will)g(use)208 4244 y(it)30 b(to)h(resolv)o(e)e(the)h(URI)g(speci\002ed)g(in)g(the)h Fl(uri)f Fn(parameter)m(,)g(otherwise)g(it)g(will)h(use)f(its)i(o)n(wn) d Fl(resolver)p Fn(,)i(or)f(raise)h(an)208 4344 y Fl(EvaluateException) 17 b Fn(e)o(xception.)208 4477 y(An)o(y)i Fl(keyword)h Fn(parameters)f(will)i(be)f(passed)g(to)h(the)f(chosen)g(resolv)o(er)-5 b(.)24 b(If)d(no)e(content)h(is)h(a)n(v)n(ailable,)f(it)h(will)g (return)e Fl(None)p Fn(.)208 4576 y(If)h(unable)f(to)h(resolv)o(e)g (the)g(URI)h(it)g(will)g(raise)f(an)h Fl(EvaluateException)c Fn(e)o(xception.)23 b(Otherwise,)d(the)h(resolv)o(er)e(should)208 4676 y(return)25 b(data)i(in)f(a)i(form)d(acceptable)h(to)h(the)f (speci\002ed)h(typecode,)f Fl(tc)p Fn(.)45 b(\(This)26 b(will)i(almost)e(al)o(w)o(ays)i(be)e(a)h(\002le-lik)o(e)g(object)208 4776 y(holding)18 b(opaque)h(data;)h(for)f(XML,)h(it)h(may)f(be)g(a)h (DOM)f(tree.\))0 4922 y Fj(WhatActorsArePresent)p Fl(\(\))208 5022 y Fn(Returns)g(a)g(list)h(of)f(the)h(v)n(alues)e(of)h(all)h(the)f (SO)m(AP)h Fl(actor)f Fn(attrib)n(utes)g(found)f(in)h(child)g(elements) g(of)g(the)g(SO)m(AP)h Fl(Header)p Fn(.)0 5169 y Fj (WhatMustIUnderstand)p Fl(\(\))208 5269 y Fn(Returns)26 b(a)h(list)h(of)f(`)p Fl(\(uri,)48 b(localname\))p Fn(')25 b(tuples)i(for)f(all)i(elements)e(in)h(the)g(SO)m(AP)h Fl(Header)e Fn(that)h(ha)n(v)o(e)f(the)h(SO)m(AP)208 5368 y Fl(mustUnderstand)18 b Fn(attrib)n(ute)h(set)i(to)g(a)f (non-zero)e(v)n(alue.)p 0 5549 3901 4 v 0 5649 a Fi(16)1389 b(Chapter)24 b(5.)52 b(The)23 b Fl(ParsedSoap)e Fi(module)j(\227)f (basic)g(message)g(handling)p eop end %%Page: 17 23 TeXDict begin 17 22 bop 0 83 a Fl(ZSI)16 b Fn(supports)g(multiple)f (DOM)i(implementations.)22 b(The)16 b Fl(readerclass)f Fn(parameter)f(speci\002es)j(which)f(one)g(to)g(use.)24 b(The)16 b(def)o(ault)0 183 y(is)21 b(to)f(use)h(minidom,)d(pro)o (vided)g(through)g(the)i Fl(DefaultReader)f Fn(class)i(in)f(the)g Fl(ZSI.parse)f Fn(module.)0 330 y(The)h(speci\002ed)g(reader)f(class)i (must)f(support)f(the)h(follo)n(wing)f(methods:)0 476 y Fj(fromString)p Fl(\()p Fk(string)p Fl(\))208 576 y Fn(Return)g(a)i(DOM)f(object)g(from)f(a)i(string.)0 723 y Fj(fromStream)p Fl(\()p Fk(str)m(eam)p Fl(\))208 823 y Fn(Return)e(a)i(DOM)f(object)g(from)f(a)i(\002le-lik)o(e)f(stream.)0 969 y Fj(releaseNode)p Fl(\()p Fk(dom)p Fl(\))208 1069 y Fn(Free)g(the)g(speci\002ed)g(DOM)g(object.)0 1216 y(The)k(DOM)g(object)g(must)g(support)e(the)i(standard)f(Python)g (mapping)f(of)i(the)g(DOM)h(Le)n(v)o(el)e(2)h(speci\002cation.)36 b(While)24 b(only)g(a)g(small)0 1316 y(subset)d(of)g(speci\002cation)g (is)h(used,)f(the)g(particular)f(methods)g(and)h(attrib)n(utes)g(used)g (by)f Fl(ZSI)i Fn(are)f(a)n(v)n(ailable)f(only)h(by)f(inspecting)h(the) 0 1415 y(source.)0 1562 y(T)-7 b(o)32 b(use)g(the)g Fl(cDomlette)f Fn(DOM)h(pro)o(vided)e(by)h(the)h(4Suite)g(package,)h(use)g(the)f Fl(NonvalidatingReader)c Fn(class)33 b(in)g(the)0 1662 y Fl(Ft.Xml.Domlette)17 b Fn(module.)23 b(Due)c(to)g(name)f(changes)g (in)h(the)g(1.0)f(v)o(ersion)g(of)h(4Suite,)f(a)i(simple)f(adapter)f (class)h(is)h(required)d(to)0 1761 y(use)j(this)h(DOM)g (implementation.)236 1999 y Fe(from)44 b(4Suite.Xml.Domlette)e(import)i (NonvalidatingReaderBase)236 2182 y(class)g (4SuiteAdapterReader\(NonvalidatingReaderB)o(ase\):)416 2365 y(def)g(fromString\(self,)e(str\):)595 2456 y(return)i (self.parseString\(str\))416 2639 y(def)g(fromStream\(self,)e (stream\):)595 2730 y(return)i(self.parseStream\(stream\))416 2913 y(def)g(releaseNode\(self,)e(node\):)595 3004 y(pass)p 0 5549 3901 4 v 3808 5649 a Fi(17)p eop end %%Page: 18 24 TeXDict begin 18 23 bop 0 5549 3901 4 v 0 5649 a Fi(18)p eop end %%Page: 19 25 TeXDict begin 19 24 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3707 427 y Fh(SIX)p 0 515 V 1026 978 a Ft(The)57 b Fd(TypeCode)g Ft(classes)h(\227)f(data)2807 1227 y(con)l(v)-5 b(ersions)0 1706 y Fn(The)17 b Fl(TypeCode)f Fn(module)f(de\002nes)i(classes)h (used)f(for)f(con)m(v)o(erting)e(data)j(between)f(SO)m(AP)i(data)f(and) f(local)h(Python)f(objects.)24 b(Python)0 1805 y(numeric)j(and)g (string)h(types,)h(and)f(sequences)f(and)g(dictionaries,)i(are)f (supported)e(by)i Fl(ZSI)p Fn(.)f(The)h Fl(TC.TypeCode)f Fn(class)i(is)g(the)0 1905 y(parent)19 b(class)i(of)f(all)h(datatypes)e (understood)f(by)i Fl(ZSI)p Fn(.)0 2052 y(All)h(typecodes)e(classes)i (ha)n(v)o(e)f(the)g(pre\002x)f Fl(TC.)p Fn(,)h(to)g(a)n(v)n(oid)g(name) g(clashes.)0 2199 y Fl(ZSI)27 b Fn(pro)o(vides)e(\002ne-grain)h (control)f(o)o(v)o(er)h(the)h(names)g(used)f(when)h(parsing)f(and)g (serializing)h(XML)g(into)f(local)h(Python)f(objects,)0 2298 y(through)g(the)i(use)h(of)f(tw)o(o)h(attrib)n(utes:)41 b(the)28 b Fl(pname)p Fn(,)i(the)e Fl(aname)p Fn(.)49 b(The)28 b Fl(pname)g Fn(speci\002es)h(the)f(name)g(e)o(xpected)e(on)i (the)h(XML)0 2398 y(element)20 b(being)g(parsed)g(and)g(the)h(name)f (to)h(use)g(for)f(the)g(output)g(element)g(when)g(serializing.)26 b(The)21 b Fl(aname)f Fn(is)i(the)e(name)g(to)h(use)g(for)0 2498 y(the)f(analogous)f(attrib)n(ute)g(in)i(the)f(local)g(Python)f (object.)0 2644 y(The)f Fl(pname)f Fn(is)i(the)f(parameter)f(name.)23 b(It)c(speci\002es)f(the)g(incoming)e(XML)i(element)g(name)f(and)g(the) h(def)o(ault)g(v)n(alues)f(for)h(the)g(Python)0 2744 y(attrib)n(ute)i(and)g(serialized)g(names.)26 b(All)c(typecodes)d(tak)o (e)h(the)h Fl(pname)f Fn(ar)o(gument.)k(This)d(name)f(can)g(be)g (speci\002ed)h(as)g(either)f(a)h(list)h(or)0 2844 y(a)d(string.)24 b(When)19 b(speci\002ed)g(as)g(a)g(list,)h(it)g(must)f(ha)n(v)o(e)f(tw) o(o)h(elements)g(which)f(are)h(interpreted)e(as)j(a)f (\223\(namespace-URI,)d(localname\)\224)0 2943 y(pair)-5 b(.)24 b(If)17 b(speci\002ed)g(this)h(w)o(ay)-5 b(,)18 b(both)e(the)i(namespace)e(and)h(the)g(local)g(element)g(name)g(must)g (match)g(for)g(the)h(parse)f(to)g(succeed.)24 b(F)o(or)17 b(the)0 3043 y(Python)j(attrib)n(ute,)g(and)h(when)f(generating)f (output,)g(only)h(the)h(\223localname\224)f(is)i(used.)k(If)21 b(a)g(namespace-URI)f(is)i(speci\002ed)e(then)h(the)0 3143 y(full)f(quali\002ed)f(name)h(is)h(used)f(for)g(output,)e(and)i (it)h(is)g(required)d(for)i(input;)f(this)i Fk(r)m(equir)m(es)g Fn(the)f(namespace)f(pre\002x)g(to)h(be)h(speci\002ed.)0 3289 y(The)h Fl(aname)g Fn(is)h(the)g(attrib)n(ute)f(name.)31 b(This)22 b(parameter)f(o)o(v)o(errides)g(an)o(y)g(v)n(alue)h(implied)g (by)g(the)g Fl(pname)p Fn(.)31 b(T)-7 b(ypecodes)21 b(nested)i(in)f(a)0 3389 y Fl(TC.Struct)d Fn(or)h Fl(TC.ComplexType)d Fn(can)j(use)g(this)h (parameter)d(to)j(specify)e(the)h(tag,)g(dictionary)e(k)o(e)o(y)-5 b(,)19 b(or)g(instance)h(attrib)n(ute)f(to)0 3489 y(set.)0 3636 y(The)25 b Fl(nsdict)f Fn(parameter)g(to)h(the)g Fl(SoapWriter)f Fn(construct)g(can)h(be)g(used)g(to)g(specify)f (pre\002x)h(to)g(namespace-URI)e(mappings,)0 3735 y(these)d(are)g (otherwise)g(handled)f(automatically)-5 b(.)0 4063 y Fg(6.1)121 b Fb(TC.TypeCode)0 4295 y Fn(The)20 b Fl(TypeCode)f Fn(class)i(is)g(the)g(parent)e(class)i(of)f(all)h(typecodes.)0 4442 y Fo(class)g Fj(TypeCode)p Fl(\()p Fk(**k)o(e)n(ywor)m(ds)p Fl(\))208 4542 y Fn(The)e(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o (guments)g(may)i(be)g(used:)p 0 5549 3901 4 v 3808 5649 a Fi(19)p eop end %%Page: 20 26 TeXDict begin 20 25 bop 257 70 a Fo(K)n(eyw)o(ord)p 853 100 4 100 v 390 w(Default)p 1352 100 V 166 w(Description)p 208 103 3736 4 v 257 173 a Fl(pname)p 853 203 4 100 v 498 w(None)p 1352 203 V 198 w Fn(parameter)19 b(name)g(of)h(the)g (object)257 272 y Fl(aname)p 853 302 V 498 w(None)p 1352 302 V 198 w Fn(attrib)n(ute)g(name)f(of)h(the)h(object)257 372 y Fl(minOccurs)p 853 402 V 372 w(1)p 1352 402 V 274 w Fn(schema)f(f)o(acet)g(minimum)f(occurances)257 472 y Fl(maxOccurs)p 853 501 V 372 w(1)p 1352 501 V 274 w Fn(schema)h(f)o(acet)g(maximum)f(occurances)257 571 y Fl(nillable)p 853 601 V 323 w(False)p 1352 601 V 173 w Fn(schema)h(f)o(acet)g(is)h(this)g(nillable)f(\()p Fl(xsi:nil="true")p Fn(\))257 671 y Fl(typed)p 853 900 4 299 v 498 w(True)p 1352 900 V 198 w Fn(Output)f(type)g(information)e (\(in)j(the)f Fl(xsi:type)g Fn(attrib)n(ute\))g(when)g(serializing.)24 b(By)1403 770 y(special)31 b(dispensation,)h(typecodes)e(within)h(a)g Fl(TC.Struct)f Fn(object)g(inherit)h(this)1403 870 y(from)19 b(the)h(container)-5 b(.)257 970 y Fl(unique)p 853 1099 4 200 v 522 w(0)p 1352 1099 V 274 w Fn(If)20 b(true,)f(the)h(object)g (is)h(unique)d(and)h(will)i(ne)n(v)o(er)e(be)h(\223aliased\224)f(with)i (another)d(object,)1403 1069 y(so)j(the)f Fl(id)g Fn(attrib)n(ute)g (need)g(not)f(be)i(output.)257 1169 y Fl(pyclass)p 853 1298 V 398 w(None)p 1352 1298 V 198 w Fn(when)j(parsing)g(data,)i (instances)f(of)g(this)g(class)h(can)f(be)g(created)f(to)h(store)g(the) g(data.)1403 1269 y(Def)o(ault)20 b(beha)n(vior)f(is)i(re\003ecti)n(v)o (e)e(of)h(speci\002c)g(T)-7 b(ypeCode)19 b(classes.)257 1368 y Fl(attrs_aname)p 853 1498 V 98 w('_attrs')p 1352 1498 V 98 w Fn(attrib)n(ute)31 b(name)g(of)h(the)f(object)g(where)g (attrib)n(ute)h(v)n(alues)f(are)g(stored.)59 b(Used)32 b(for)1403 1468 y(serialization)20 b(and)f(parsing.)208 1596 y(Optional)24 b(elements)i(are)f(those)h(which)f(do)g(not)g(ha)n (v)o(e)g(to)h(be)g(an)f(incoming)f(message,)i(or)g(which)f(ha)n(v)o(e)g (the)h(XML)f(Schema)208 1695 y Fl(nil)e Fn(attrib)n(ute)g(set.)35 b(When)24 b(parsing)e(the)h(message)h(as)g(part)f(of)g(a)h Fl(Struct)p Fn(,)f(then)g(the)g(Python)g(instance)g(attrib)n(ute)g (will)h(not)208 1795 y(be)d(set,)h(or)f(the)g(element)g(will)h(not)f (appear)f(as)i(a)g(dictionary)d(k)o(e)o(y)-5 b(.)27 b(When)21 b(being)g(parsed)f(as)i(a)g(simple)f(type,)g(the)g(v)n(alue)g Fl(None)208 1895 y Fn(is)g(returned.)k(When)20 b(serializing)g(an)h (optional)e(element,)h(a)h(non-e)o(xistent)e(attrib)n(ute,)h(or)g(a)i (v)n(alue)e(of)g Fl(None)g Fn(is)i(tak)o(en)e(to)h(mean)208 1994 y(not)e(present,)h(and)f(the)i(element)e(is)i(skipped.)0 2141 y Fj(typechecks)208 2241 y Fn(This)i(is)g(a)h(class)g(attrib)n (ute.)32 b(If)23 b(true)g(\(the)f(def)o(ault\))g(then)h(all)g(typecode) e(constructors)g(do)i(more)f(rigorous)f(type-checking)f(on)208 2340 y(their)f(parameters.)0 2487 y Fj(tag)208 2587 y Fn(This)35 b(is)h(a)f(class)h(attrib)n(ute.)69 b(Speci\002es)35 b(the)g(global)f(element)g(declaration)g(this)h(typecode)e(represents,) 38 b(the)d(v)n(alue)f(is)i(a)208 2687 y(`)p Fl(\(namespace,)47 b(name\))p Fn(')19 b(tuple.)0 2833 y Fj(type)208 2933 y Fn(This)44 b(is)h(a)g(class)g(attrib)n(ute.)97 b(Speci\002es)45 b(the)f(global)f(type)h(de\002nition)f(this)i(typecode)e(represents,)49 b(the)44 b(v)n(alue)g(is)h(a)208 3033 y(`)p Fl(\(namespace,)i(name\))p Fn(')19 b(tuple.)0 3180 y Fj(attribute_typecode_dict)208 3279 y Fn(This)h(is)h(a)g(class)g(attrib)n(ute.)26 b(This)20 b(is)h(a)g(dict)g(of)f(`)p Fl(\(URI,)48 b(NCName\))p Fn(')19 b(tuple)h(k)o(e)o(ys,)g(the)h(v)n(alues)f(of)g(each)g(is)h(a)g (typecode.)i(This)208 3379 y(is)28 b(ho)n(w)f(attrib)n(ute)h (declarations)e(other)h(than)g(SO)m(AP)h(and)f(XMLSchema)g(attrib)n (ute)g(declarations)g(\(e)o(g.)46 b Fl(xsi:type)p Fn(,)29 b Fl(id)p Fn(,)208 3478 y Fl(href)p Fn(,)19 b(etc\))i(are)f (represented.)0 3625 y Fj(logger)208 3725 y Fn(This)g(is)h(a)g(class)g (attrib)n(ute.)j(logger)19 b(instance)h(for)g(this)g(class.)0 3872 y(The)29 b(follo)n(wing)f(methods)g(are)i(useful)f(for)f (de\002ning)h(ne)n(w)g(typecode)e(classes;)36 b(see)30 b(the)f(section)g(on)g(dynamic)f(typing)h(for)f(more)0 3971 y(details.)d(In)20 b(all)h(of)f(the)g(follo)n(wing,)e(the)j Fl(ps)f Fn(parameter)f(is)i(a)f Fl(ParsedSoap)f Fn(object.)0 4118 y Fj(checkname)p Fl(\()p Fk(elt,)g(ps)p Fl(\))208 4218 y Fn(Checks)d(if)g(the)h(name)e(and)h(type)g(of)g(the)g(element)f Fl(elt)i Fn(are)f(correct)f(and)h(raises)h(a)f Fl(EvaluateException)e Fn(if)i(not.)24 b(Returns)208 4318 y(the)c(element')-5 b(s)20 b(type)f(as)i(a)g(`)p Fl(\(uri,)49 b(localname\))p Fn(')18 b(tuple)i(if)g(so.)0 4464 y Fj(checktype)p Fl(\()p Fk(elt,)f(ps)p Fl(\))208 4564 y Fn(Lik)o(e)46 b Fl(checkname\(\))f Fn(e)o(xcept)h(that)h(the)g(element)f(name)g(is)h(ignored.)103 b(This)47 b(method)e(is)j(actually)e(in)m(v)n(ok)o(ed)f(by)208 4664 y Fl(checkname\(\))19 b Fn(to)i(do)f(the)h(second)f(half)h(of)f (its)i(processing,)e(b)n(ut)g(is)i(useful)e(to)h(in)m(v)n(ok)o(e)f (directly)-5 b(,)20 b(such)g(as)i(when)e(resolving)208 4763 y(multi-reference)d(data.)0 4910 y Fj(nilled)p Fl(\()p Fk(elt,)i(ps)p Fl(\))208 5010 y Fn(If)33 b(the)h(element)f Fl(elt)g Fn(has)h(data,)j(this)d(returns)f Fl(False)p Fn(.)64 b(If)34 b(it)g(has)g(no)f(data,)k(and)c(the)g(typecode)f(is)j (not)e(optional,)j(an)208 5109 y Fl(EvaluateException)17 b Fn(is)k(raised;)f(if)h(it)g(is)g(optional,)e(a)h Fl(True)g Fn(is)h(returned.)0 5256 y Fj(simple_value)p Fl(\()p Fk(elt,)d(ps,)i(mixed=F)-6 b(alse)p Fl(\))208 5356 y Fn(Returns)38 b(the)h(te)o(xt)g(content)f(of)h(the)f(element)h Fl(elt)p Fn(.)81 b(If)39 b(no)f(v)n(alue)g(is)i(present,)j(or)38 b(the)h(element)g(has)g(non-te)o(xt)e(chil-)p 0 5549 3901 4 v 0 5649 a Fi(20)1751 b(Chapter)24 b(6.)51 b(The)24 b Fl(TypeCode)d Fi(classes)h(\227)h(data)h(con)n(v)n(ersions)p eop end %%Page: 21 27 TeXDict begin 21 26 bop 208 83 a Fn(dren,)47 b(an)c Fl (EvaluateException)e Fn(is)j(raised.)93 b(If)43 b Fl(mixed)f Fn(is)i Fl(False)f Fn(if)g(child)g(elements)g(are)g(disco)o(v)o(ered)e (an)208 183 y Fl(EvaluateException)17 b Fn(is)k(raised,)f(else)h(join)f (all)h(te)o(xt)f(nodes)f(and)h(return)f(the)h(result.)0 510 y Fg(6.2)121 b Fb(TC.Any)31 b Fg(\227)i(the)i(basis)e(of)h(dynamic) f(typing)0 743 y Fn(SO)m(AP)c(pro)o(vides)d(a)i(\003e)o(xible)g(set)g (of)g(serialization)f(rules,)j(ranging)c(from)h(completely)f (self-describing)g(to)i(completely)e(opaque,)0 843 y(requiring)18 b(an)i(e)o(xternal)f(schema.)24 b(F)o(or)c(e)o(xample,)e(the)i(follo)n (wing)f(are)h(all)h(possible)e(w)o(ays)i(of)f(encoding)e(an)i(inte)o (ger)e(element)i Fl(i)g Fn(with)0 942 y(a)h(v)n(alue)e(of)h Fl(12)p Fn(:)0 1227 y Ff(6.2.1)100 b(simple)29 b(data)0 1430 y Fn(\226)20 b(requires)f(type)h(information)236 1668 y Fe(12)236 1759 y(12)236 1851 y(12)236 1942 y(12)0 2229 y Fn(The)16 b(\002rst)h(three)f(lines)g(are) h(e)o(xamples)e(of)h Fk(typed)f Fn(elements.)24 b(If)16 b Fl(ZSI)g Fn(is)h(ask)o(ed)f(to)h(parse)f(an)o(y)f(of)h(the)g(abo)o(v) o(e)f(e)o(xamples,)h(and)f(a)i Fl(TC.Any)0 2328 y Fn(typecode)k(is)i (gi)n(v)o(en,)f(it)h(will)g(properly)d(create)i(a)h(Python)f(inte)o (ger)f(for)h(the)g(\002rst)h(three,)g(and)f(raise)g(a)h Fl(EvaluateException)d Fn(for)0 2428 y(the)g(fourth.)0 2713 y Ff(6.2.2)100 b(compound)30 b(data)0 2916 y Fn(\226)18 b(Struct)g(or)g(Array)f(Compound)f(data,)i(such)g(as)h(a)f Fl(struct)p Fn(,)g(may)f(also)i(be)f(self-describing)e(\(namespace)g (are)i(omitted)g(for)f(clarity\):)236 3063 y Fe()416 3154 y(12)416 3245 y(Hello)c(world) 236 3337 y()0 3623 y Fn(If)20 b(this)h(is)g(parsed)e(with)i (a)f Fl(TC.Any)g Fn(typecode,)e(either)i(a)h(Python)e Fl(dict)h Fn(is)h(created)e(or)h(if)h Fl(aslist)e Fn(is)i(T)m(rue)f(a)h Fl(list)p Fn(:)236 3861 y Fe(ps)45 b(=)f(ParsedSoap\(xml,)f (envelope=False\))236 3953 y(print)h(ps.Parse\(TC.Any\(\)\))236 4044 y({)135 b('name':)43 b(u'Hello)h(world',)178 b('i':)44 b(12)134 b(})236 4227 y(print)44 b(ps.Parse\(TC.Any\(aslist=True\)\)) 236 4318 y([)h(12,)f(u'Hello)g(world')g(])0 4557 y Fn(Note)20 b(that)g(one)g(preserv)o(es)f(order)m(,)f(while)j(the)f(other)f (preserv)o(es)g(the)h(element)g(names.)0 4842 y Ff(6.2.3)100 b(class)28 b(descr)q(iption)0 5040 y Fo(class)21 b Fj(Any)p Fl(\()p Fk(name)p Fc([)p Fk(,)d(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 5140 y Fn(Used)20 b(for)f(parsing)h(incoming)e(SO)m (AP)j(data)f(\(that)g(is)h(typed\),)e(and)h(serializing)f(outgoing)f (Python)h(data.)208 5273 y(The)g(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o (guments)g(may)i(be)g(used:)p 0 5549 3901 4 v 0 5649 a Fi(6.2.)52 b Fl(TC.Any)22 b Fi(\227)h(the)h(basis)f(of)g(dynamic)g (typing)2189 b(21)p eop end %%Page: 22 28 TeXDict begin 22 27 bop 415 70 a Fo(K)n(eyw)o(ord)p 788 100 4 100 v 98 w(Default)p 1150 100 V 99 w(Description)p 365 103 3377 4 v 415 173 a Fl(aslist)p 788 402 4 299 v 131 w(False)p 1150 402 V 106 w Fn(If)30 b(true,)i(then)e(the)g(data)g (is)h(\(recursi)n(v)o(ely\))d(treated)h(as)i(a)g(list)g(of)f(v)n (alues.)55 b(The)29 b(de-)1202 272 y(f)o(ault)20 b(is)h(a)g(Python)e (dictionary)-5 b(,)18 b(which)h(preserv)o(es)g(parameter)g(names)h(b)n (ut)g(loses)h(the)1202 372 y(ordering.)48 b(Ne)n(w)21 b(in)f(v)o(ersion)f(1.1.)208 500 y(In)f(addition,)f(if)i(the)g(Python)e (object)i(being)e(serialized)i(with)g(an)f Fl(Any)h Fn(has)g(a)g Fl(typecode)e Fn(attrib)n(ute,)i(then)f(the)h Fl(serialize)208 600 y Fn(method)29 b(of)i(the)g(typecode)e(will)i(be)g(in)m(v)n(ok)o (ed)e(to)i(do)g(the)g(serialization.)56 b(This)31 b(allo)n(ws)g (objects)g(to)g(o)o(v)o(erride)d(the)j(def)o(ault)208 699 y(dynamic)18 b(serialization.)0 846 y(Referring)h(back)h(to)g(the)h (compound)c(XML)k(data)f(abo)o(v)o(e,)e(it)j(is)h(possible)e(to)g (create)g(a)h(ne)n(w)f(typecode)f(capable)g(of)i(parsing)e(elements)0 946 y(of)g(type)g Fl(mytype)p Fn(.)25 b(This)19 b(class)i(w)o(ould)e (kno)n(w)f(that)i(the)f Fl(i)h Fn(element)f(is)i(an)e(inte)o(ger)m(,)f (so)i(that)g(the)f(e)o(xplicit)g(typing)f(becomes)h(optional,)0 1045 y(rather)g(than)h(required.)0 1330 y Ff(6.2.4)100 b(Adding)30 b(ne)n(w)e(types)0 1533 y Fn(Most)d(of)f(the)h Fl(TypeCodes)f Fn(classes)i(in)f Fl(TC)g Fn(are)f(re)o(gistered)g(with) h Fl(Any)p Fn(,)g(making)f(an)g(instance)h(of)f(itself)i(a)n(v)n (ailable)e(for)g(dynamic)0 1633 y(typing.)50 b(Ne)n(w)29 b Fl(TypeCode)f Fn(classes)i(can)f(be)g(created)f(and)g(re)o(gistered)g (with)h Fl(Any)g Fn(by)f(using)h Fl(RegisterType)p Fn(.)49 b(In)29 b(order)e(to)0 1732 y(o)o(v)o(erride)22 b(an)i(e)o(xisting)f (entry)g(in)h(the)g(re)o(gistry)f(call)h Fl(RegisterType)e Fn(with)i Fl(clobber=True)p Fn(.)35 b(The)24 b(serialization)f(entries) h(are)0 1832 y(mappings)c(between)h(b)n(uiltin)g(Python)g(types)g(and)h (a)g Fl(TypeCode)e Fn(instance,)i(it)g(is)h(not)e(possible)g(to)h(ha)n (v)o(e)f(one)g(Python)g(type)g(map)g(to)0 1932 y(multiple)j(typecodes.) 38 b(The)25 b(parsing)f(entries)h(are)g(mappings)e(between)i Fl(\(namespaceURI,name\))d Fn(tuples,)k(representing)d(the)0 2031 y Fl(xsi:type)17 b Fn(attrib)n(ute,)h(and)g(a)g Fl(TypeCode)f Fn(instance.)24 b(Thus,)18 b(only)f(one)h(instance)g(of)f (a)i Fl(TypeCode)e Fn(class)i(can)f(represent)f(a)i(XML)0 2131 y(Schema)h(type.)k(So)c(this)h(mechanism)e(is)i(not)f(appropriate) e(for)h(representing)g(XML)h(Schema)f(element)h(information.)0 2278 y Fo(class)h Fa(NEWTYPECODE)p Fj(\(TypeCode\))p Fl(\()p Fk(...)p Fl(\))208 2377 y Fn(The)f(ne)n(w)h(typecode)f(should)g (be)h(deri)n(v)o(ed)e(from)i(the)g Fl(TC.TypeCode)e Fn(class,)k(and)d Fl(TypeCode.__init__\(\))e Fn(must)k(be)208 2477 y(in)m(v)n(ok)o(ed)c (in)i(the)h(ne)n(w)f(class')-5 b(s)21 b(constructor)-5 b(.)0 2624 y Fj(parselist)208 2724 y Fn(This)38 b(is)h(a)f(class)h (attrib)n(ute,)j(used)37 b(when)h(parsing)e(incoming)h(SO)m(AP)h(data.) 78 b(It)39 b(should)e(be)g(a)i(sequence)e(of)g(`)p Fl(\(uri,)208 2823 y(localname\))p Fn(')24 b(tuples)i(to)g(identify)f(the)i (datatype.)41 b(If)26 b Fl(uri)g Fn(is)h Fl(None)p Fn(,)h(it)e(is)i (tak)o(en)d(to)i(mean)e(either)h(the)g(XML)g(Schema)208 2923 y(namespace)15 b(or)i(the)g(SO)m(AP)h(encoding)d(namespace;)i (this)g(should)f(only)g(be)h(used)g(if)g(adding)e(support)h(for)g (additional)g(primiti)n(v)o(e)208 3022 y(types.)24 b(If)d(this)f(list)i (is)f(empty)-5 b(,)19 b(then)g(the)i(type)e(of)h(the)h(incoming)d(SO)m (AP)j(data)f(is)i(assumed)d(to)i(be)f(correct;)f(an)i(empty)e(list)i (also)208 3122 y(means)e(that)i(incoming)d(typed)h(data)h(cannot)g(by)f (dynamically)g(parsed.)0 3269 y Fj(errorlist)208 3369 y Fn(This)26 b(is)i(a)f(class)g(attrib)n(ute,)g(used)g(when)f (reporting)e(a)j(parsing)e(error)-5 b(.)44 b(It)26 b(is)i(a)f(te)o(xt)f (string)g(naming)f(the)i(datatype)e(that)i(w)o(as)208 3468 y(e)o(xpected.)c(If)d(not)g(de\002ned,)f Fl(ZSI)h Fn(will)h(create)f(this)g(attrib)n(ute)g(from)f(the)i Fl(parselist)e Fn(attrib)n(ute)h(when)f(it)i(is)g(needed.)0 3615 y Fj(seriallist)208 3715 y Fn(This)28 b(is)g(a)g(class)h(attrib)n (ute,)g(used)f(when)f(serializing)g(Python)g(objects)g(dynamically)-5 b(.)46 b(It)28 b(speci\002es)g(what)g(types)g(of)f(object)208 3814 y(instances)19 b(\(or)f(Python)h(types\))f(this)i(typecode)e(can)h (serialize.)25 b(It)19 b(should)f(be)i(a)f(sequence,)f(where)h(each)g (element)g(is)h(a)g(Python)208 3914 y(class)25 b(object,)f(a)h(string)f (naming)f(the)i(class,)h(or)e(a)h(type)f(object)f(from)h(Python')-5 b(s)23 b Fl(types)h Fn(module)f(\(if)h(the)h(ne)n(w)f(typecode)f(is)208 4014 y(serializing)c(a)i(b)n(uilt-in)e(Python)g(type\).)0 4160 y Fj(parse)p Fl(\()p Fk(elt,)g(ps)p Fl(\))208 4260 y(ZSI)32 b Fn(in)m(v)n(ok)o(es)f(this)i(method)e(to)h(parse)g(the)h Fl(elt)f Fn(element)f(and)h(return)f(its)j(Python)d(v)n(alue.)60 b(The)32 b Fl(ps)h Fn(parameter)d(is)k(the)208 4360 y Fl(ParsedSoap)18 b Fn(object,)i(and)f(can)h(be)h(used)f(for)f (dereferencing)e Fl(href)p Fn(')-5 b(s,)20 b(calling)g Fl(Backtrace\(\))f Fn(to)h(report)f(errors,)g(etc.)0 4507 y Fj(serialize)p Fl(\()p Fk(sw)-6 b(,)19 b(pyobj)p Fc([)p Fk(,)g(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4606 y(ZSI)j Fn(in)m(v)n(ok)o(es)g(this)h(method)e(to)h(output)g(a)h (Python)e(object)h(to)h(a)g(SO)m(AP)g(stream.)23 b(The)16 b Fl(sw)f Fn(parameter)f(will)i(be)g(a)g Fl(SoapWriter)208 4706 y Fn(object,)j(and)h(the)g Fl(pyobj)g Fn(parameter)e(is)j(the)g (Python)e(object)g(to)i(serialize.)208 4839 y(The)e(follo)n(wing)g(k)o (e)o(yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)p 0 5549 3901 4 v 0 5649 a Fi(22)1751 b(Chapter)24 b(6.)51 b(The)24 b Fl(TypeCode)d Fi(classes)h(\227)h(data)h(con)n(v)n(ersions)p eop end %%Page: 23 29 TeXDict begin 23 28 bop 294 70 a Fo(K)n(eyw)o(ord)p 740 100 4 100 v 256 w(Default)p 1272 100 V 183 w(Description)p 244 103 3620 4 v 294 173 a Fl(attrtext)p 740 302 4 200 v 214 w(None)p 1272 302 V 215 w Fn(T)-6 b(e)o(xt)21 b(\(with)g(leading) f(space\))g(to)i(output)d(as)j(an)f(attrib)n(ute;)g(this)h(is)g (normally)d(used)i(by)1323 272 y(the)f Fl(TC.Array)g Fn(class)h(to)f(pass)h(do)n(wn)e(inde)o(xing)f(information.)294 372 y Fl(name)p 740 501 V 414 w(None)p 1272 501 V 215 w Fn(Name)e(to)g(use)h(for)e(serialization;)i(def)o(aults)f(to)g(the)h (name)e(speci\002ed)h(in)g(the)g(typecode,)1323 472 y(or)k(a)h (generated)d(name.)294 571 y Fl(typed)p 740 701 V 248 w Fk(per)n(-typecode)p 1272 701 V 97 w Fn(Whether)i(or)f(not)h(to)g (output)f(type)h(information;)e(the)i(def)o(ault)f(is)i(to)f(use)h(the) f(v)n(alue)f(in)1323 671 y(the)h(typecode.)0 813 y(Once)j(the)h(ne)n(w) f(typecode)f(class)j(has)f(been)f(de\002ned,)g(it)h(should)f(be)g(re)o (gistered)g(with)g Fl(ZSI)p Fn(')-5 b(s)24 b(dynamic)f(type)g(system)h (by)f(in)m(v)n(oking)0 912 y(the)d(follo)n(wing)f(function:)0 1059 y Fj(RegisterType)p Fl(\()p Fk(class)p Fc([)p Fk(,)f(clobber=0)p Fc([)p Fk(,)g(**k)o(e)n(ywor)m(ds)12 b Fc(])g(])p Fl(\))208 1159 y Fn(By)20 b(def)o(ault,)f(it)i(is)g(an)e(error)g(to)h(replace)f (an)h(e)o(xisting)g(type)f(re)o(gistration,)f(and)i(an)f(e)o(xception)f (will)j(be)f(raised.)25 b(The)19 b Fl(clobber)208 1259 y Fn(parameter)i(may)i(be)h(gi)n(v)o(en)e(to)h(allo)n(w)g(replacement.) 33 b(A)24 b(single)f(instance)g(of)g(the)g Fl(class)g Fn(object)g(will)h(be)g(created,)f(and)g(the)208 1358 y Fl(keyword)c Fn(parameters)g(are)h(passed)g(to)h(the)f(constructor)-5 b(.)0 1505 y(If)19 b(the)g(class)h(is)g(not)e(re)o(gistered,)g(then)g (instances)h(of)g(the)g(class)h(cannot)e(be)h(processed)f(as)h(dynamic) f(types.)24 b(This)19 b(may)g(be)g(acceptable)0 1605 y(in)h(some)g(en)m(vironments.)0 1932 y Fg(6.3)121 b Fb(TC.SimpleType)0 2165 y Fn(P)o(arent)20 b(class)h(of)f(all)g(simple)h (types.)0 2312 y Fj(empty_content)208 2411 y Fn(This)f(is)h(a)g(class)g (attrib)n(ute.)j(V)-9 b(alue)20 b(returned)f(when)g(tag)h(or)g(node)f (is)j(present,)d(is)i(not)f(nilled,)f(and)h(without)g(te)o(xt)g (content.)0 2739 y Fg(6.4)121 b(Str)r(ings)0 2972 y Fn(SO)m (AP/XMLSchema)19 b(Strings)h(are)h(Python)e(strings.)0 3119 y Fo(class)i Fj(String)p Fl(\()p Fk(name)p Fc([)p Fk(,)d(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3218 y Fn(The)19 b(parent)h(type)f(of)h(all)h(strings.)208 3351 y(The)e(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o(guments)g(may)i(be) g(used:)378 3480 y Fo(K)n(eyw)o(ord)p 825 3510 4 100 v 172 w(Default)p 1187 3510 V 99 w(Description)p 328 3513 3451 4 v 378 3583 a Fl(resolver)p 825 3713 4 200 v 130 w(None)p 1187 3713 V 131 w Fn(A)33 b(function)e(that)h(can)h (resolv)o(e)e(an)i(absolute)f(URI)h(and)f(return)f(its)j(content)d(as)j (a)1239 3683 y(string,)19 b(as)i(described)e(in)i(the)f Fl(ParsedSoap)f Fn(description.)378 3782 y Fl(strip)p 825 3812 4 100 v 280 w(True)p 1187 3812 V 131 w Fn(If)h(true,)f (leading)h(and)f(trailing)h(whitespace)f(are)i(stripped)e(from)g(the)h (content.)0 3948 y Fo(class)h Fj(Enumeration)p Fl(\()p Fk(value)p 973 3948 25 4 v 26 w(list,)g(name)p Fc([)p Fk(,)e(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4047 y Fn(Lik)o(e)20 b Fl(TC.String)p Fn(,)e(b)n(ut)j(the)f(v)n(alue)f(must) i(be)f(a)g(member)f(of)h(the)g Fl(choices)g Fn(sequence)f(of)h(te)o(xt) g(strings)0 4194 y(In)h(addition)f(to)i Fl(TC.String)p Fn(,)e(the)h(basic)h(string,)f(se)n(v)o(eral)g(subtypes)f(are)i(pro)o (vided)c(that)k(transparently)d(handle)i(common)e(encod-)0 4294 y(ings.)34 b(These)23 b(classes)i(create)e(a)h(temporary)d(string) i(object)f(and)h(pass)h(that)f(to)h(the)f Fl(serialize\(\))f Fn(method.)33 b(When)23 b(doing)f(RPC)0 4394 y(encoding,)h(and)g (checking)f(for)h(non-unique)e(strings,)k(the)f Fl(TC.String)e Fn(class)j(must)f(ha)n(v)o(e)g(the)g(original)e(Python)h(string,)h(as)h (well)0 4493 y(as)c(the)f(ne)n(w)g(output.)k(This)c(is)h(done)e(by)h (adding)f(a)i(parameter)d(to)j(the)f Fl(serialize\(\))f Fn(method:)311 4719 y Fo(K)n(eyw)o(ord)p 684 4749 4 100 v 99 w(Default)p 1047 4749 V 98 w(Description)p 262 4753 3377 4 v 311 4822 a Fl(orig)p 684 5052 4 299 v 256 w(None)p 1047 5052 V 131 w Fn(If)e(deri)n(ving)f(a)h(ne)n(w)g(typecode)f(from)g (the)i(string)e(class,)j(and)e(the)g(deri)n(v)n(ation)e(creates)j(a) 1098 4922 y(temporary)c(Python)h(string)h(\(such)g(as)h(by)e Fl(Base64String)p Fn(\),)g(than)h(this)h(parameter)1098 5022 y(is)k(the)f(original)f(string)h(being)f(serialized.)0 5223 y Fo(class)i Fj(Base64String)p Fl(\()p Fk(name)p Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 5322 y Fn(The)19 b(v)n(alue)h(is)h(encoded)d(in)j(Base-64.)p 0 5549 3901 4 v 0 5649 a Fi(6.3.)52 b Fl(TC.SimpleType)2968 b Fi(23)p eop end %%Page: 24 30 TeXDict begin 24 29 bop 0 83 a Fo(class)21 b Fj(HexBinaryString)p Fl(\()p Fk(name)p Fc([)p Fk(,)16 b(**k)o(e)n(ywor)m(ds)c Fc(])p Fl(\))208 183 y Fn(Each)19 b(byte)h(is)h(encoded)e(as)h(its)i (printable)d(v)o(ersion.)0 330 y Fo(class)i Fj(URI)p Fl(\()p Fk(name)p Fc([)p Fk(,)d(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 429 y Fn(The)19 b(v)n(alue)h(is)h(URL)g(quoted)e (\(e.g.,)g Fl(\04520)h Fn(for)f(the)i(space)f(character\).)0 576 y(It)g(is)h(often)e(the)g(case)i(that)f(a)g(parameter)e(will)i(be)g (typed)f(as)h(a)h(string)e(for)g(transport)g(purposes,)f(b)n(ut)i(will) g(in)g(f)o(act)g(ha)n(v)o(e)f(special)h(syntax)0 676 y(and)i(processing)f(requirements.)29 b(F)o(or)22 b(e)o(xample,)f(a)i (string)f(could)g(be)g(used)g(for)g(an)g(XP)o(ath)g(e)o(xpression,)f(b) n(ut)h(it)h(is)h(more)d(con)m(v)o(enient)0 775 y(for)f(the)g(Python)f (v)n(alue)g(to)i(actually)e(be)h(the)h(compiled)d(e)o(xpression.)24 b(Here)c(is)h(ho)n(w)f(to)g(do)g(that:)236 1013 y Fe(import)44 b(xml.xpath.pyxpath)236 1105 y(import)g(xml.xpath.pyxpath.Compile)d(as) j(_xpath_compile)236 1287 y(class)g(XPathString\(TC.String\):)416 1379 y(def)g(__init__\(self,)e(name,)1536 1392 y(**)1626 1379 y(kw\):)595 1470 y(TC.String.__init__\(self,)f(name,)1985 1483 y(**)2075 1470 y(kw\))416 1653 y(def)j(parse\(self,)f(elt,)h (ps\):)595 1744 y(val)g(=)h(TC.String.parse\(self,)c(elt,)j(ps\))595 1835 y(try:)774 1927 y(val)h(=)f(_xpath_compile\(val\))595 2018 y(except:)774 2109 y(raise)g(EvaluateException\("Invalid)d(XPath)j (expression",)1312 2201 y(ps.Backtrace\(elt\)\))595 2292 y(return)g(val)0 2579 y Fn(In)27 b(particular)m(,)h(it)h(is)f(common)e (to)i(send)g(XML)f(as)i(a)f(string,)h(using)e(entity)h(encoding)d(to)j (protect)f(the)h(ampersand)e(and)h(less-than)0 2678 y(characters.)0 2825 y Fo(class)21 b Fj(XMLString)p Fl(\()p Fk(name)p Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2925 y Fn(P)o(arses)19 b(the)h(data)f(as)h(a)g(string,)f(b)n(ut)g (returns)g(an)g(XML)g(DOM)h(object.)k(F)o(or)19 b(serialization,)g(tak) o(es)g(an)g(XML)h(DOM)f(\(or)g(element)208 3024 y(node\),)f(and)i (outputs)f(it)i(as)g(a)f(string.)208 3157 y(The)f(follo)n(wing)g(k)o(e) o(yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)303 3286 y Fo(K)n(eyw)o(ord)p 900 3316 4 100 v 322 w(Default)p 1262 3316 V 98 w(Description)p 254 3320 3601 4 v 303 3389 a Fl(readerclass)p 900 3519 4 200 v 130 w(None)p 1262 3519 V 130 w Fn(Class)53 b(used)d(to)h(create)f(DOM-creating)f (XML)h(readers;)66 b(described)49 b(in)i(the)1313 3489 y Fl(ParsedSoap)19 b Fn(chapter)-5 b(.)0 3791 y Fg(6.5)121 b(Integers)0 4024 y Fn(SO)m(AP/XMLSchema)19 b(inte)o(gers)h(are)g (Python)f(inte)o(gers.)0 4171 y Fo(class)i Fj(Integer)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4271 y Fn(The)19 b(parent)h(type)f(of)h(all)h(inte)o(gers.)j(This)c (class)i(handles)d(an)o(y)g(of)h(the)h(se)n(v)o(eral)e(types)h(\(and)f (ranges\))g(of)h(SO)m(AP)h(inte)o(gers.)208 4404 y(The)e(follo)n(wing)g (k)o(e)o(yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)415 4533 y Fo(K)n(eyw)o(ord)p 788 4563 4 100 v 98 w(Default)p 1150 4563 V 99 w(Description)p 365 4566 3377 4 v 415 4636 a Fl(format)p 788 4666 4 100 v 206 w(\045d)p 1150 4666 V 181 w Fn(F)o(ormat)f(string)h(for)g(serializing.)50 b(Ne)n(w)20 b(in)g(v)o(ersion)f(1.2.)0 4801 y Fo(class)i Fj(IEnumeration)p Fl(\()p Fk(c)o(hoices)p Fc([)p Fk(,)16 b(**k)o(e)n(ywor)m(ds)c Fc(])p Fl(\))208 4901 y Fn(Lik)o(e)20 b Fl(TC.Integer)p Fn(,)e(b)n(ut)i(the)h(v)n(alue)e(must)h(be)h(a)f (member)f(of)h(the)g Fl(choices)g Fn(sequence.)0 5048 y(A)h(number)d(of)i(sub-classes)g(are)g(de\002ned)g(to)g(handle)f (smaller)n(-ranged)f(numbers.)0 5194 y Fo(class)j Fj(Ibyte)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 5294 y Fn(A)20 b(signed)g(eight-bit)f(v)n(alue.)p 0 5549 3901 4 v 0 5649 a Fi(24)1751 b(Chapter)24 b(6.)51 b(The)24 b Fl(TypeCode)d Fi(classes)h(\227)h(data)h(con)n(v)n(ersions)p eop end %%Page: 25 31 TeXDict begin 25 30 bop 0 83 a Fo(class)21 b Fj(IunsignedByte)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 183 y Fn(An)20 b(unsigned)e(eight-bit)h(v)n(alue.)0 330 y Fo(class)i Fj(Ishort)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 429 y Fn(A)20 b(signed)g(16-bit)f(v)n(alue.)0 576 y Fo(class)i Fj(IunsignedShort)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m (ds)12 b Fc(])p Fl(\))208 676 y Fn(An)20 b(unsigned)e(16-bit)h(v)n (alue.)0 823 y Fo(class)i Fj(Iint)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m (ds)12 b Fc(])p Fl(\))208 922 y Fn(A)20 b(signed)g(32-bit)f(v)n(alue.)0 1069 y Fo(class)i Fj(IunsignedInt)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m (ds)12 b Fc(])p Fl(\))208 1169 y Fn(An)20 b(unsigned)e(32-bit)h(v)n (alue.)0 1316 y Fo(class)i Fj(Ilong)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 1415 y Fn(An)20 b(signed)f(64-bit)g(v)n(alue.)0 1562 y Fo(class)i Fj(IunsignedLong)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 1662 y Fn(An)20 b(unsigned)e(64-bit)h(v)n(alue.)0 1808 y Fo(class)i Fj(IpositiveInteger)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m (ds)12 b Fc(])p Fl(\))208 1908 y Fn(A)20 b(v)n(alue)g(greater)f(than)h (zero.)0 2055 y Fo(class)h Fj(InegativeInteger)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2155 y Fn(A)20 b(v)n(alue)g(less)h(than)f(zero.)0 2301 y Fo(class)h Fj(InonPositiveInteger)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2401 y Fn(A)20 b(v)n(alue)g(less)h(than)f(or)g (equal)f(to)i(zero.)0 2548 y Fo(class)g Fj(InonNegativeInteger)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2648 y Fn(A)20 b(v)n(alue)g(greater)f(than)h(or)g(equal)f(to)i(zero.)0 2975 y Fg(6.6)121 b(Floating-point)35 b(Numbers)0 3208 y Fn(SO)m(AP/XMLSchema)19 b(\003oating)h(point)f(numbers)g(are)h (Python)f(\003oats.)0 3355 y Fo(class)i Fj(Decimal)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3454 y Fn(The)19 b(parent)h(type)g(of)f(all)i(\003oating)f(point)f (numbers.)24 b(This)c(class)h(handles)f(an)o(y)f(of)h(the)h(se)n(v)o (eral)e(types)h(\(and)g(ranges\))f(of)h(SO)m(AP)208 3554 y(\003oating)f(point)g(numbers.)208 3687 y(The)g(follo)n(wing)g(k)o(e)o (yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)415 3816 y Fo(K)n(eyw)o(ord)p 788 3846 4 100 v 98 w(Default)p 1150 3846 V 99 w(Description)p 365 3849 3377 4 v 415 3919 a Fl(format)p 788 3949 4 100 v 206 w(\045f)p 1150 3949 V 181 w Fn(F)o(ormat)f(string)h(for)g(serializing.)50 b(Ne)n(w)20 b(in)g(v)o(ersion)f(1.2.)0 4084 y Fo(class)i Fj(FPEnumeration)p Fl(\()p Fk(value)p 1073 4084 25 4 v 26 w(list,)g(name)p Fc([)p Fk(,)e(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4184 y Fn(Lik)o(e)22 b Fl(TC.Decimal)p Fn(,)h(b)n(ut)g(the)g(v)n(alue)f(must)h(be)g(a)g(member)f(of)h(the)g Fl(value_list)e Fn(sequence.)32 b(Be)24 b(careful)e(of)h(round-of)n(f) 208 4284 y(errors)c(if)h(using)g(this)h(class.)0 4430 y(T)-7 b(w)o(o)20 b(sub-classes)h(are)f(de\002ned)f(to)h(handle)f (smaller)n(-ranged)g(numbers.)0 4577 y Fo(class)i Fj(FPfloat)p Fl(\()p Fk(name)p Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4677 y Fn(An)20 b(IEEE)f(single-precision)f(32-bit)i (\003oating)f(point)g(v)n(alue.)0 4824 y Fo(class)i Fj(FPdouble)p Fl(\()p Fk(name)p Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4923 y Fn(An)20 b(IEEE)f(double-precision)e(64-bit)i (\003oating)h(point)f(v)n(alue.)p 0 5549 3901 4 v 0 5649 a Fi(6.6.)52 b(Floating-point)25 b(Numbers)2755 b(25)p eop end %%Page: 26 32 TeXDict begin 26 31 bop 0 86 a Fg(6.7)121 b(Dates)34 b(and)h(Times)0 319 y Fn(SO)m(AP)25 b(dates)e(and)h(times)g(are)f (Python)g(time)h(tuples)g(in)f(UTC)i(\(GMT\),)e(as)h(documented)d(in)j (the)g(Python)e Fl(time)i Fn(module.)34 b(T)m(ime)24 b(is)0 419 y(trick)o(y)-5 b(,)19 b(and)h(processing)f(an)o(ything)f (other)i(than)g(a)h(simple)f(absolute)g(time)g(can)h(be)f(dif)n (\002cult.)25 b(\(Ev)o(en)19 b(then,)h(timezones)g(lie)h(in)f(w)o(ait)h (to)0 518 y(trip)f(up)g(the)g(unw)o(ary)-5 b(.\))23 b(A)e(fe)n(w)f(ca)n (v)o(eats)g(are)g(in)g(order:)104 748 y(1.)41 b(Some)18 b(date)i(and)e(time)i(formats)e(will)i(be)f(parsed)g(into)g(tuples)g (that)g(are)g(not)g(v)n(alid)g(time)g(v)n(alues.)24 b(F)o(or)19 b(e)o(xample,)f(75)h(minutes)g(is)208 848 y(a)h(v)n(alid)g(duration,)e (although)g(not)i(a)h(le)o(gal)e(v)n(alue)h(for)f(the)i(minutes)e (element)h(of)g(a)g(time)h(tuple.)104 1014 y(2.)41 b(Fractional)19 b(parts)h(of)g(a)h(second)e(may)h(be)g(lost)h(when)e(parsing,)g(and)h (may)f(ha)n(v)o(e)h(e)o(xtra)f(trailing)h(zero')-5 b(s)20 b(when)g(serializing.)104 1180 y(3.)41 b(Badly-formed)13 b(time)j(tuples)g(may)f(result)i(in)f(non-sensical)e(v)n(alues)i(being) f(serialized;)i(the)f(\002rst)h(six)f(v)n(alues)g(are)g(tak)o(en)f (directly)208 1280 y(as)20 b(year)m(,)g(month,)e(day)-5 b(,)19 b(hour)m(,)g(minute,)g(second)g(in)h(UTC.)104 1446 y(4.)41 b(Although)17 b(the)i(classes)h Fl(Duration)f Fn(and)f Fl(Gregorian)g Fn(are)i(de\002ned,)e(the)o(y)g(are)h(for)g (internal)f(use)i(only)e(and)h(should)f(not)h(be)208 1545 y(included)c(in)h(an)o(y)g Fl(TypeCode)g Fn(you)g(de\002ne.)23 b(Instead,)16 b(use)h(the)g(classes)g(be)o(ginning)d(with)j(a)g(lo)n (wer)f(case)h(g)g(in)g(your)e(typecodes.)0 1775 y(In)20 b(addition,)f(badly-formed)d(v)n(alues)k(may)g(result)g(in)g (non-sensical)f(serializations.)0 1922 y(When)h(serializing,)f(an)i (inte)o(gral)e(or)h(\003oating)f(point)g(number)g(is)i(tak)o(en)f(as)h (the)f(number)e(of)i(seconds)g(since)g(the)g(epoch,)f(in)h(UTC.)0 2069 y Fo(class)h Fj(Duration)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds) 12 b Fc(])p Fl(\))208 2169 y Fn(A)21 b(relati)n(v)o(e)f(time)h(period.) 26 b(Ne)o(gati)n(v)o(e)19 b(durations)g(ha)n(v)o(e)h(all)i(v)n(alues)e (less)i(than)e(zero;)h(this)h(mak)o(es)e(it)i(easy)f(to)g(add)f(a)h (duration)e(to)208 2268 y(a)h(Python)f(time)i(tuple.)0 2415 y Fo(class)g Fj(Gregorian)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds) 12 b Fc(])p Fl(\))208 2515 y Fn(An)20 b(absolute)f(time)i(period.)i (This)e(class)g(should)e(not)h(be)g(instantiated)f(directly;)h(use)g (one)g(of)g(the)g Fl(gXXX)g Fn(classes)h(instead.)0 2662 y Fo(class)g Fj(gDateTime)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2761 y Fn(A)20 b(date)g(and)g(time.)0 2908 y Fo(class)h Fj(gDate)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3008 y Fn(A)20 b(date.)0 3155 y Fo(class)h Fj(gYearMonth)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3254 y Fn(A)20 b(year)g(and)g(month.)0 3401 y Fo(class)h Fj(gYear)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3501 y Fn(A)20 b(year)-5 b(.)0 3648 y Fo(class)21 b Fj(gMonthDay)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3747 y Fn(A)20 b(month)f(and)h(day)-5 b(.)0 3894 y Fo(class)21 b Fj(gDay)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m (ds)12 b Fc(])p Fl(\))208 3994 y Fn(A)20 b(day)-5 b(.)0 4141 y Fo(class)21 b Fj(gTime)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds) 12 b Fc(])p Fl(\))208 4240 y Fn(A)20 b(time.)0 4568 y Fg(6.8)121 b(Boolean)0 4800 y Fn(SO)m(AP)21 b(Booleans)f(are)g(Python)f (inte)o(gers.)0 4947 y Fo(class)i Fj(Boolean)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 5047 y Fn(When)18 b(marshaling)e(zero)i(or)g(the)g(w)o(ord)f(\223f)o (alse\224)i(is)g(returned)d(as)j Fl(0)g Fn(and)e(an)o(y)h(non-zero)e(v) n(alue)h(or)h(the)g(w)o(ord)g(\223true\224)f(is)i(returned)208 5147 y(as)h Fl(1)p Fn(.)26 b(When)20 b(serializing,)f(the)h(number)f Fl(0)h Fn(or)g Fl(1)h Fn(will)g(be)f(generated.)p 0 5549 3901 4 v 0 5649 a Fi(26)1751 b(Chapter)24 b(6.)51 b(The)24 b Fl(TypeCode)d Fi(classes)h(\227)h(data)h(con)n(v)n(ersions)p eop end %%Page: 27 33 TeXDict begin 27 32 bop 0 86 a Fg(6.9)121 b(XML)0 319 y Fn(XML)20 b(is)g(a)g(Python)f(DOM)h(element)f(node.)k(If)d(the)f(v)n (alue)g(to)h(be)g(serialized)f(is)h(a)g(Python)f(string,)g(then)g(an)h Fl(href)f Fn(is)i(generated,)c(with)0 419 y(the)24 b(v)n(alue)f(used)h (as)g(the)g(URI.)g(This)g(can)g(be)g(used,)g(for)f(e)o(xample,)g(when)h (generating)d(SO)m(AP)k(with)f(attachments.)35 b(Otherwise,)25 b(the)0 518 y(XML)20 b(is)h(typically)f(put)g(inside)g(a)g(wrapper)f (element)h(that)g(sets)h(the)f(proper)f(SO)m(AP)i(encoding)d(style.)0 665 y(F)o(or)28 b(ef)n(\002cienc)o(y)-5 b(,)29 b(incoming)e(XML)i(is)h (returend)d(as)i(a)h(\223pointer\224)d(into)i(the)f(DOM)h(tree)g (maintained)e(within)i(the)g Fl(ParsedSoap)0 765 y Fn(object.)f(If)22 b(that)f(object)g(is)i(going)d(to)i(go)f(out)g(of)g(scope,)h(the)f (data)h(will)g(be)f(destro)o(yed)f(and)h(an)o(y)g(XML)h(objects)f(will) h(become)e(empty)0 865 y(elements.)45 b(The)26 b(class)i(instance)f(v)n (ariable)f Fl(copyit)p Fn(,)h(if)h(non-zero)c(indicates)j(that)g(a)g (deep)f(cop)o(y)g(of)h(the)g(XML)g(subtree)f(will)i(be)0 964 y(made)c(and)f(returned)g(as)i(the)f(v)n(alue.)36 b(Note)25 b(that)f(it)h(is)g(generally)e(more)g(ef)n(\002cient)h(to)g (k)o(eep)g(the)g Fl(ParsedSoap)f Fn(object)h(ali)n(v)o(e)g(until)0 1064 y(the)c(XML)g(data)h(is)g(no)e(longerneeded.)0 1211 y Fo(class)i Fj(XML)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 1310 y Fn(This)30 b(typecode)f(represents)h(a)h (portion)e(of)h(an)h(XML)f(document)f(embedded)f(in)j(a)g(SO)m(AP)g (message.)56 b(The)30 b(v)n(alue)g(is)i(the)208 1410 y(element)19 b(node.)208 1543 y(The)g(follo)n(wing)g(k)o(e)o(yw)o(ord)f (ar)o(guments)g(may)i(be)g(used:)257 1754 y Fo(K)n(eyw)o(ord)p 704 1784 4 100 v 310 w(Default)p 1342 1784 V 237 w(Description)p 208 1787 3727 4 v 257 1857 a Fl(copyit)p 704 1886 4 100 v 199 w Fn(TC.XML.cop)o(yit)p 1342 1886 V 97 w(Return)g(a)g(cop)o(y)g (of)g(the)g(parsed)f(data.)257 1956 y Fl(comments)p 704 1986 V 343 w(0)p 1342 1986 V 344 w Fn(Preserv)o(e)g(comments)g(in)i (output.)257 2056 y Fl(inline)p 704 2086 V 443 w(0)p 1342 2086 V 344 w Fn(The)f(XML)g(sub-tree)f(is)i(single-reference,)d (so)i(can)g(be)g(output)f(in-place.)257 2155 y Fl(resolver)p 704 2285 4 200 v 268 w(None)p 1342 2285 V 269 w Fn(A)30 b(function)d(that)j(can)f(resolv)o(e)g(an)g(absolute)f(URI)i(and)f (return)f(its)j(content)d(as)i(an)1394 2255 y(element)20 b(node,)e(as)j(described)e(in)i(the)f Fl(ParsedSoap)f Fn(description.)257 2355 y Fl(wrapped)p 704 2484 V 393 w(1)p 1342 2484 V 344 w Fn(If)c(zero,)h(the)f(XML)h(is)g(output)e (directly)-5 b(,)15 b(and)g(not)g(within)g(a)h(SO)m(AP)g(wrapper)e (element.)1394 2454 y(Ne)n(w)20 b(in)h(v)o(ersion)e(1.2.)0 2596 y(When)j(serializing,)f(it)h(may)f(be)h(necessary)f(to)h(specify)f (which)g(namespace)f(pre\002x)o(es)h(are)h(\223acti)n(v)o(e\224)f(in)h (the)f(XML.)h(This)g(is)g(done)f(by)0 2696 y(using)26 b(the)h Fl(unsuppressedPrefixes)c Fn(parameter)i(when)h(calling)g(the)h Fl(serialize\(\))e Fn(method.)43 b(\(This)26 b(will)h(only)f(w)o(ork)0 2796 y(when)20 b(XML)g(is)h(the)f(top-le)n(v)o(el)f(item)h(being)f (serialized,)h(such)g(as)h(when)e(using)h(typecodes)f(and)g (document-style)f(interf)o(aces.\))50 3104 y Fo(K)n(eyw)o(ord)p 1094 3133 4 100 v 770 w(Default)p 1457 3133 V 98 w(Description)p 0 3137 4049 4 v 50 3207 a Fl(unsuppressedPrefixes)p 1094 3236 4 100 v 199 w Fn([])p 1457 3236 V 203 w(An)e(array)f(of)g(strings) h(identifying)e(the)h(namespace)g(pre\002x)o(es)g(that)h(should)e(be)i (output.)0 3511 y Fg(6.10)121 b(Comple)l(xT)-14 b(ype)0 3744 y Fn(Represents)20 b(the)g(XMLSchema)f(Comple)o(xT)-7 b(ype)18 b(.)51 b(Ne)n(w)21 b(in)f(v)o(ersion)f(2.0.)0 3890 y Fo(class)i Fj(ComplexType)p Fl(\()p Fk(pyclass,)c(ofwhat)q Fc([)p Fk(,)j(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3990 y Fn(This)28 b(class)g(de\002nes)g(a)g(compound)d(data)j (structure.)47 b(If)28 b Fl(pyclass)f Fn(is)i Fl(None)p Fn(,)g(then)f(the)g(data)f(will)i(be)f(marshaled)f(into)g(a)208 4090 y(Python)d(dictionary)-5 b(,)24 b(and)h(each)g(item)h(in)g(the)f Fl(ofwhat)g Fn(sequence)f(speci\002es)i(a)g(\(possible\))f(dictionary)e (entry)-5 b(.)40 b(Otherwise,)208 4189 y Fl(pyclass)28 b Fn(must)i(be)g(a)g(Python)e(class)j(object.)52 b(The)30 b(data)f(is)i(then)e(marshaled)f(into)i(the)f(object,)j(and)d(each)g (item)h(in)g(the)208 4289 y Fl(ofwhat)19 b Fn(sequence)g(speci\002es)i (an)f(attrib)n(ute)g(of)g(the)g(instance)g(to)g(set.)208 4422 y(Note)g(that)g(each)g(typecode)e(in)j Fl(ofwhat)e Fn(must)i(ha)n(v)o(e)e(a)i(name.)208 4555 y(The)e(follo)n(wing)g(k)o(e) o(yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)p 0 5549 3901 4 v 0 5649 a Fi(6.9.)52 b(XML)3448 b(27)p eop end %%Page: 28 34 TeXDict begin 28 33 bop 261 70 a Fo(K)n(eyw)o(ord)p 857 100 4 100 v 364 w(Default)p 1305 100 V 141 w(Description)p 211 103 3687 4 v 261 173 a Fl(inorder)p 857 302 4 200 v 347 w(False)p 1305 302 V 148 w Fn(Items)18 b(within)f(the)h (structure)f(must)g(appear)g(in)h(the)f(order)f(speci\002ed)i(in)g(the) f Fl(ofwhat)1356 272 y Fn(sequence.)261 372 y Fl(inline)p 857 501 V 397 w(False)p 1305 501 V 148 w Fn(The)29 b(structure)f(is)i (single-reference,)e(so)h(ZSI)g(does)f(not)h(ha)n(v)o(e)f(to)h(use)g Fl(href/id)1356 472 y Fn(encodings.)261 571 y Fl(mutable)p 857 900 4 399 v 347 w(False)p 1305 900 V 148 w Fn(If)f(an)g(object)f (is)i(going)d(to)i(be)g(serialized)g(multiple)f(times,)j(and)d(its)i (state)f(may)g(be)1356 671 y(modi\002ed)d(between)g(serializations,)i (then)e(this)h(k)o(e)o(yw)o(ord)e(should)h(be)h(used,)g(other)n(-)1356 770 y(wise)20 b(a)f(single)g(instance)g(will)h(be)e(serialized,)h(with) g(multiple)g(references)e(to)i(it.)25 b(This)1356 870 y(ar)o(gument)18 b(implies)i(the)h Fl(inline)e Fn(ar)o(gument.)49 b(Ne)n(w)20 b(in)g(v)o(ersion)f(1.2.)261 970 y Fl(type)p 857 1498 4 598 v 522 w(None)p 1305 1498 V 173 w Fn(A)37 b(`)p Fl(\(uri,)48 b(localname\))p Fn(')34 b(tuple)h(that)h(de\002nes)g (the)f(type)h(of)f(the)h(structure.)1356 1069 y(If)41 b(present,)k(and)c(if)g(the)g(input)f(data)g(has)i(a)f Fl(xsi:type)f Fn(attrib)n(ute,)45 b(then)c(the)1356 1169 y(namespace-quali\002ed)22 b(v)n(alue)h(of)h(that)g(attrib)n(ute)g (must)g(match)g(the)g(v)n(alue)g(speci\002ed)1356 1269 y(by)32 b(this)g(parameter)-5 b(.)59 b(By)33 b(def)o(ault,)h (type-checking)29 b(is)j(not)g(done)f(for)g(structures;)1356 1368 y(matching)22 b(child)h(element)g(names)f(is)j(usually)d(suf)n (\002cient)h(and)g(senders)f(rarely)h(pro-)1356 1468 y(vide)d(type)g(information.)261 1567 y Fl(mixed)p 857 1597 4 100 v 447 w(False)p 1305 1597 V 148 w Fn(using)g(a)h(mix)o(ed)e (content)g(model,)g(allo)n(w)h(te)o(xt)g(and)g(element)f(content.)261 1667 y Fl(mixed_aname)p 857 1697 V 97 w('_text')p 1305 1697 V 98 w Fn(if)i(mix)o(ed)e(is)i(T)m(rue,)e(te)o(xt)h(content)g(is)h (set)g(in)f(this)h(attrib)n(ute)f(\(k)o(e)o(y\).)208 1788 y(If)j(the)h Fl(typed)f Fn(k)o(e)o(yw)o(ord)e(is)k(used,)f(then)f (its)h(v)n(alue)f(is)i(assigned)e(to)g(all)h(typecodes)f(in)g(the)h Fl(ofwhat)f Fn(parameter)-5 b(.)34 b(If)23 b(an)o(y)g(of)208 1888 y(the)c(typecodes)f(in)i Fl(ofwhat)f Fn(are)h(repeatable,)e(then)h (the)h Fl(inorder)f Fn(k)o(e)o(yw)o(ord)f(should)h(not)g(be)g(used)h (and)f(the)h Fl(hasextras)208 1987 y Fn(parameter)e Fk(must)j Fn(be)f(used.)208 2113 y(F)o(or)f(e)o(xample,)g(the)h(follo)n(wing)f(C) i(structure:)444 2330 y Fe(struct)44 b(foo)g({)623 2422 y(int)g(i;)623 2513 y(char)803 2526 y(*)892 2513 y(text;)444 2604 y(};)208 2761 y Fn(could)19 b(be)h(declared)f(as)i(follo)n(ws:)444 2978 y Fe(class)44 b(foo:)623 3069 y(def)g(__init__\(self,)f(name\):) 802 3160 y(self.name)h(=)g(name)623 3252 y(def)g(__str__\(self\):)802 3343 y(return)g(str\(\(self.name,)f(self.i,)g(self.text\)\))444 3526 y(foo.typecode)g(=)h(TC.Struct\(foo,)623 3617 y(\()h (TC.Integer\('i'\),)d(TC.String\('text'\))g(\),)623 3708 y('foo'\))0 4068 y Fg(6.11)121 b(Str)r(uct)0 4301 y Fn(SO)m(AP)24 b(Struct)e(is)i(a)f(comple)o(x)e(type)h(for)g(accessors)h(identi\002ed) f(by)g(name.)32 b(No)23 b(element)f(may)h(ha)n(v)o(e)f(the)h(same)f (name)h(as)g(an)o(y)f(other)m(,)0 4400 y(nor)f(may)g(an)o(y)f(element)h (ha)n(v)o(e)g(a)h(maxOccurs)e(\277)i(1.)29 b(SO)m(AP)23 b(Structs)e(are)h(either)f(Python)f(dictionaries)h(or)g(instances)g(of) g(application-)0 4500 y(speci\002ed)f(classes.)0 4821 y Fg(6.12)121 b(Arr)o(a)l(ys)0 5054 y Fn(SO)m(AP)22 b(arrays)f(are)h (Python)e(lists;)k(multi-dimensional)19 b(arrays)i(are)h(lists)h(of)e (lists)i(and)e(are)h(indistinguishable)d(from)i(a)h(SO)m(AP)g(array)0 5154 y(of)17 b(arrays.)24 b(Arrays)17 b(may)f(be)i Fk(spar)o(se)p Fn(,)g(in)g(which)f(case)h(each)f(element)g(in)g(the)h(array)e(is)j(a)e (tuple)h(of)f(`)p Fl(\(subscript,)47 b(data\))p Fn(')17 b(pairs.)0 5253 y(If)j(an)g(array)f(is)j(not)d(sparse,)h(a)h (speci\002ed)f Fk(\002ll)g Fn(element)g(will)h(be)f(used)g(for)g(the)g (missing)g(v)n(alues.)0 5400 y Fo(Curr)o(ently)f(only)h (singly-dimensioned)h(arrays)e(ar)o(e)h(supported.)p 0 5549 3901 4 v 0 5649 a Fi(28)1751 b(Chapter)24 b(6.)51 b(The)24 b Fl(TypeCode)d Fi(classes)h(\227)h(data)h(con)n(v)n(ersions)p eop end %%Page: 29 35 TeXDict begin 29 34 bop 0 83 a Fo(class)21 b Fj(Array)p Fl(\()p Fk(atype)o(,)d(ofwhat)q Fc([)p Fk(,)i(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 183 y Fn(The)20 b Fl(atype)h Fn(parameter)f(is)i(a)f Fl(\(URI,NCName\))f Fn(tuple)h(representing)e(the)i(SO)m(AP)h(array)e (type.)28 b(The)20 b Fl(ofwhat)h Fn(parameter)208 282 y(is)g(a)f(typecode)f(describing)f(the)j(array)e(elements.)0 429 y(The)h(follo)n(wing)e(k)o(e)o(yw)o(ord)h(ar)o(guments)f(may)i(be)g (used:)225 655 y Fo(K)n(eyw)o(ord)p 771 685 4 100 v 271 w(Default)p 1133 685 V 99 w(Description)p 175 689 3551 4 v 225 758 a Fl(childnames)p 771 788 4 100 v 129 w(None)p 1133 788 V 131 w Fn(Def)o(ault)g(name)f(to)i(use)f(for)g(the)g(child)g (elements.)225 858 y Fl(dimensions)p 771 888 V 204 w(1)p 1133 888 V 206 w Fn(The)g(number)e(of)i(dimensions)f(in)h(the)g(array) -5 b(.)225 958 y Fl(fill)p 771 988 V 429 w(None)p 1133 988 V 131 w Fn(The)20 b(v)n(alue)f(to)h(use)h(when)e(an)i(array)e (element)g(is)j(omitted.)225 1057 y Fl(mutable)p 771 1286 4 299 v 254 w(False)p 1133 1286 V 106 w Fn(If)27 b(an)h(object)f(is)i(going)e(to)h(be)f(serialized)h(multiple)f(times,)j (and)d(its)i(state)g(may)e(be)1185 1157 y(modi\002ed)d(between)h (serializations,)i(then)e(this)i(k)o(e)o(yw)o(ord)d(should)g(be)i (used,)h(other)n(-)1185 1257 y(wise)21 b(a)f(single)g(instance)g(will)h (be)f(serialized,)g(with)g(multiple)g(references)f(to)h(it.)225 1356 y Fl(nooffset)p 771 1486 4 200 v 304 w(0)p 1133 1486 V 206 w Fn(Do)j(not)g(use)h(the)f(SO)m(AP)h Fl(offset)f Fn(attrib)n(ute)g(so)h(skip)f(leading)f(elements)h(with)h(the)1185 1456 y(same)c(v)n(alue)g(as)h Fl(fill)p Fn(.)225 1555 y Fl(sparse)p 771 1585 4 100 v 304 w(False)p 1133 1585 V 106 w Fn(The)f(array)f(is)i(sparse.)225 1655 y Fl(size)p 771 1685 V 429 w(None)p 1133 1685 V 131 w Fn(An)f(inte)o(ger)f(or)h (list)h(of)f(inte)o(gers)g(that)g(speci\002es)g(the)h(maximum)d(array)h (dimensions.)225 1755 y Fl(undeclared)p 771 1785 V 104 w(False)p 1133 1785 V 106 w Fn(The)h(SO)m(AP)h(`)p Fl(arrayType)p Fn(')d(attrib)n(ute)i(need)f(not)h(appear)-5 b(.)0 2057 y Fg(6.13)121 b(Apache)35 b(Datatype)0 2290 y Fn(The)30 b(Apache)g(SO)m(AP)h(project,)h(urlhttp://xml.apache.or)o(g/soap)o (/inde)n(x.)o(html,)27 b(has)k(de\002ned)e(a)i(popular)e(SO)m(AP)j (datatype)d(in)i(the)0 2390 y Fl(http://xml.apache.org/xml-soap)15 b Fn(namespace,)k(a)h Fl(Map)p Fn(.)0 2536 y(The)f Fl(Map)h Fn(type)f(is)i(encoded)c(as)k(a)f(list)g(of)g Fl(item)f Fn(elements.)24 b(Each)c Fl(item)f Fn(has)h(a)g Fl(key)f Fn(and)g Fl(value)h Fn(child)f(element;)g(these)h(children)0 2636 y(must)g(ha)n(v)o(e)g(SO)m(AP)h(type)f(information.)i(An)e(Apache) g(Map)g(is)h(either)e(a)i(Python)e(dictionary)g(or)g(a)i(list)g(of)f (tw)o(o-element)f(tuples.)0 2783 y Fo(class)i Fj(Apache.Map)p Fl(\()p Fk(name)p Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2883 y Fn(An)20 b(Apache)f(map.)25 b(Note)20 b(that)g(the)g(class)h(name)f(is)h(dotted.)0 3029 y(The)f(follo)n(wing)e(k)o(e)o(yw)o(ord)h(ar)o(guments)f(may)i(be) g(used:)311 3256 y Fo(K)n(eyw)o(ord)p 684 3286 V 99 w(Default)p 1047 3286 V 98 w(Description)p 262 3289 3377 4 v 311 3359 a Fl(aslist)p 684 3389 4 100 v 231 w(0)p 1047 3389 V 206 w Fn(Use)h(a)f(list)i(of)e(tuples)g(rather)f(than)h(a)g (dictionary)-5 b(.)p 0 5549 3901 4 v 0 5649 a Fi(6.13.)52 b(Apache)24 b(Datatype)2935 b(29)p eop end %%Page: 30 36 TeXDict begin 30 35 bop 0 5549 3901 4 v 0 5649 a Fi(30)p eop end %%Page: 31 37 TeXDict begin 31 36 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3495 427 y Fh(SEVEN)p 0 515 V 270 978 a Ft(The)57 b Fd(SoapWriter)g Ft(module)g(\227)g(ser)s(ializing)3498 1227 y(data)0 1706 y Fn(The)20 b(SoapWriter)h(class)g(is)h(used)f(to)g(output)e(SO)m (AP)j(messages.)27 b(Note)20 b(that)h(its)h(output)e(is)h(encoded)e(as) j(UTF-8;)f(when)f(transporting)0 1805 y(SO)m(AP)h(o)o(v)o(er)e(HTTP)h (it)h(is)g(therefore)e(important)f(to)j(set)g(the)f Fl(charset)f Fn(attrib)n(ute)h(of)g(the)g Fl(Content-Type)f Fn(header)-5 b(.)0 1952 y(The)20 b Fl(SoapWriter)f Fn(class)i(reserv)o(es)e(some)h (namespace)f(pre\002x)o(es:)680 2155 y Fo(Pr)o(e\002x)p 1126 2185 4 100 v 286 w(URI)p 630 2188 2641 4 v 680 2258 a Fl(SOAP-ENV)p 1126 2288 4 100 v 98 w (http://schemas.xmlsoap.org/soap/env)o(elope)o(/)680 2358 y(SOAP-ENC)p 1126 2388 V 98 w(http://schemas.xmlsoap.org/soap/enc) o(oding)o(/)680 2457 y(ZSI)p 1126 2487 V 348 w (http://www.zolera.com/schemas/ZSI/)680 2557 y(xsd)p 1126 2587 V 348 w(http://www.w3.org/2001/XMLSchema)680 2657 y(xsi)p 1126 2687 V 348 w(http://www.w3.org/2001/XMLSchema-in)o (stanc)o(e)0 2812 y Fo(class)i Fj(SoapWriter)p Fl(\()p Fk(optional**k)o(e)n(ywor)m(d)o(s)p Fl(\))208 2911 y Fn(The)e(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o(guments)g(may)i(be)g (used:)257 3120 y Fo(K)n(eyw)o(ord)p 953 3150 V 589 w(Default)p 1650 3150 V 266 w(Description)p 208 3154 4035 4 v 257 3223 a Fl(encodingStyle)p 953 3353 4 200 v 307 w Fn(None)p 1650 3353 V 307 w(If)39 b(not)g Fl(None)p Fn(,)44 b(then)39 b(use)h(the)g(speci\002ed)f(v)n(alue)f(as)j(the)e(v)n(alue)g(for)g(the) g(SO)m(AP)1702 3323 y Fl(encodingStyle)18 b Fn(attrib)n(ute.)51 b(Ne)n(w)20 b(in)g(v)o(ersion)f(1.2.)257 3423 y Fl(envelope)p 953 3452 4 100 v 547 w(True)p 1650 3452 V 298 w Fn(Create)h(a)h(SO)m (AP)g(En)m(v)o(elope)39 b(Ne)n(w)20 b(in)g(v)o(ersion)f(1.2.)257 3522 y Fl(nsdict)p 953 3552 V 697 w({})p 1650 3552 V 348 w Fn(Dictionary)g(of)h(namespaces)f(to)h(declare)g(in)g(the)g(SO)m (AP)h Fl(Envelope)257 3622 y(header)p 953 3652 V 647 w(True)p 1650 3652 V 298 w Fn(create)f(a)g(SO)m(AP)i Fl(Header)d Fn(element)257 3721 y Fl(outputclass)p 953 3751 V 198 w(ElementProxy)p 1650 3751 V 97 w Fn(wrapper)g(around)f(DOM) i(or)g(other)g(XML)g(library)-5 b(.)0 3863 y(Creating)24 b(a)h Fl(SoapWriter)e Fn(object)h(with)g Fl(envelope)f Fn(set)j(to)e Fl(False)g Fn(results)h(in)f(an)h(object)e(that)i(can)f (be)g(used)g(for)g(serializing)0 3963 y(objects)c(into)g(a)h(string.)0 4110 y Fj(serialize)p Fl(\()p Fk(pyobj)p Fc([)p Fk(,)c(typecode=None)p Fc([)p Fk(,)h(r)l(oot=None)p Fc([)p Fk(,)h(header)p 2056 4110 25 4 v 28 w(pyobjs=None)p Fc([)p Fk(,)g(**k)o(e)n(ywor)m(ds)12 b Fc(])g(])g(])g(])p Fl(\))208 4210 y Fn(This)19 b(method)f(serializes) h(the)g Fl(pyobj)g Fn(Python)f(object)h(as)h(directed)e(by)h(the)g Fl(typecode)f Fn(typecode)f(object.)24 b(If)19 b Fl(typecode)208 4309 y Fn(is)i(omitted,)f(then)g Fl(pyobj)g Fn(should)g(be)g(a)i (Python)d(object)h(instance)g(of)h(a)g(class)g(that)g(has)g(a)g Fl(typecode)f Fn(attrib)n(ute.)26 b(It)20 b(returns)208 4409 y Fl(self)p Fn(,)d(so)g(that)g(serializations)g(can)f(be)h (chained)f(together)m(,)g(or)g(so)i(that)f(the)g Fl(close\(\))f Fn(method)f(can)i(be)g(in)m(v)n(ok)o(ed.)22 b(The)17 b Fl(root)208 4509 y Fn(parameter)k(may)i(be)g(used)g(to)h(e)o (xplicitly)e(indicate)h(the)g(root)f(\(main)h(element\))f(of)h(a)h(SO)m (AP)g(encoding,)e(or)h(indicate)f(that)i(the)208 4608 y(item)18 b(is)i(not)e(the)h(root.)24 b(If)18 b(speci\002ed,)h(it)g (should)f(ha)n(v)o(e)g(the)h(numeric)e(v)n(alue)h(of)h(zero)f(or)g (one.)24 b(An)o(y)18 b(other)g(k)o(e)o(yw)o(ord)f(parameters)208 4708 y(are)j(passed)g(to)g(the)g(typecode')-5 b(s)19 b Fl(serialize)g Fn(method.)0 4855 y Fj(close)p Fl(\(\))208 4954 y Fn(In)m(v)n(ok)o(es)h(all)i(the)g(callbacks,)f(if)h(an)o(y)-5 b(.)28 b(The)21 b Fl(close)g Fn(operations)f(can)i(only)e(happen)g (once,)h(if)h(in)m(v)n(ok)o(ed)e(a)i(second)f(time)g(it)i(will)208 5054 y(just)d(return.)k(This)c(method)f(will)i(be)f(in)m(v)n(ok)o(ed)f (automatically)f(if)j(the)f(object)g(is)h(deleted.)0 5201 y Fj(__str__)p Fl(\(\))208 5300 y Fn(In)m(v)n(ok)o(es)39 b(the)i Fl(close)f Fn(method,)45 b(and)40 b(returns)g(a)h(string)g (representation)e(of)h(the)h(serialized)g(object.)86 b(Assumes)41 b(that)208 5400 y Fl(serialize)19 b Fn(has)h(been)g(in)m (v)n(ok)o(ed.)p 0 5549 3901 4 v 3808 5649 a Fi(31)p eop end %%Page: 32 38 TeXDict begin 32 37 bop 0 83 a Fn(The)20 b(follo)n(wing)e(methods)i (are)g(primarily)e(useful)i(for)g(those)g(writing)f(ne)n(w)h (typecodes.)0 230 y Fj(AddCallback)p Fl(\()p Fk(func,)d(ar)m(g)p Fl(\))208 330 y Fn(Used)29 b(by)g(typecodes)f(when)h(serializing,)i (allo)n(ws)f(them)f(to)h(add)f(output)f(after)h(the)h(SO)m(AP)g Fl(Body)g Fn(is)g(written)f(b)n(ut)h(before)208 429 y(the)24 b(SO)m(AP)h Fl(Envelope)f Fn(is)h(closed.)37 b(The)24 b(function)f Fl(func\(\))h Fn(will)h(be)f(called)h(with)f(the)h Fl(SoapWriter)e Fn(object)h(and)g(the)208 529 y(speci\002ed)19 b Fl(arg)i Fn(ar)o(gument,)c(which)j(may)g(be)g(a)g(tuple.)0 676 y Fj(Forget)p Fl(\()p Fk(obj)p Fl(\))208 775 y Fn(F)o(or)o(get)e (that)j Fl(obj)f Fn(has)g(been)g(seen)g(before.)k(This)c(is)h(useful)f (when)f(repeatedly)g(serializing)g(a)i(mutable)e(object.)0 922 y Fj(Known)p Fl(\()p Fk(obj)p Fl(\))208 1022 y Fn(If)h Fl(obj)g Fn(has)g(been)g(seen)g(before)f(\(based)g(on)h(its)h(Python)e Fl(id)p Fn(\),)h(return)f Fl(1)p Fn(.)25 b(Otherwise,)20 b(remember)e Fl(obj)j Fn(and)e(return)g Fl(0)p Fn(.)0 1169 y Fj(ReservedNS)p Fl(\()p Fk(pr)m(e\002x,)e(uri)p Fl(\))208 1268 y Fn(Returns)j(true)f(if)i(the)f(speci\002ed)g (namespace)f Fl(prefix)h Fn(and)f Fl(uri)h Fn(collide)g(with)h(those)f (used)g(by)f(the)h(implementation.)0 1415 y Fj(writeNSDict)p Fl(\()p Fk(nsdict)q Fl(\))208 1515 y Fn(Outputs)g Fl(nsdict)h Fn(as)h(a)f(namespace)f(dictionary)-5 b(.)26 b(It)21 b(is)h(assumed)f(that)g(an)g(XML)g(start-element)g(is)h(pending)d(on)i (the)g(output)208 1614 y(stream.)p 0 5549 3901 4 v 0 5649 a Fi(32)1725 b(Chapter)23 b(7.)52 b(The)23 b Fl(SoapWriter)f Fi(module)i(\227)f(ser)q(ializing)h(data)p eop end %%Page: 33 39 TeXDict begin 33 38 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3535 427 y Fh(EIGHT)p 0 515 V 391 978 a Ft(The)57 b Fd(Fault)g Ft(module)g(\227)g(repor)8 b(ting)57 b(errors)0 1468 y Fn(SO)m(AP)28 b(de\002nes)f(a)g Fk(fault)g Fn(message)g(as)h(the)f(w) o(ay)g(for)f(a)i(recipient)e(to)h(indicate)g(it)g(w)o(as)h(unable)e(to) h(process)g(a)g(message.)46 b(The)27 b Fl(ZSI)0 1568 y(Fault)20 b Fn(class)h(encapsulates)e(this.)0 1715 y Fo(class)i Fj(Fault)p Fl(\()p Fk(code)o(,)d(string)p Fc([)p Fk(,)i(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 1814 y Fn(The)26 b Fk(code)g Fn(parameter)f(is)j(a)f(te)o(xt)f(string)h (identifying)d(the)j(SO)m(AP)h(f)o(ault)e(code,)i(a)f (namespace-quali\002ed)c(name.)44 b(The)27 b(class)208 1914 y(attrib)n(ute)18 b Fl(Fault.Client)g Fn(can)h(be)g(used)g(to)h (indicate)f(a)g(problem)f(with)h(an)h(incoming)d(message,)i Fl(Fault.Server)f Fn(can)208 2013 y(be)24 b(used)g(to)h(indicate)f(a)g (problem)f(occurred)g(while)h(processing)f(the)i(request,)f(or)g Fl(Fault.MU)g Fn(can)g(be)h(used)f(to)g(indicate)g(a)208 2113 y(problem)g(with)j(the)g(SO)m(AP)g Fl(mustUnderstand)d Fn(attrib)n(ute.)44 b(The)26 b Fk(string)h Fn(parameter)e(is)j(a)f (human-readable)22 b(te)o(xt)27 b(string)208 2213 y(describing)18 b(the)i(f)o(ault.)208 2346 y(The)f(follo)n(wing)g(k)o(e)o(yw)o(ord)f (ar)o(guments)g(may)i(be)g(used:)369 2475 y Fo(K)n(eyw)o(ord)p 834 2505 4 100 v 190 w(Default)p 1196 2505 V 99 w(Description)p 319 2508 3470 4 v 369 2578 a Fk(actor)p 834 2707 4 200 v 372 w Fl(None)p 1196 2707 V 131 w Fn(A)25 b(string)g(identifying)e (the)i Fl(actor)g Fn(attrib)n(ute)f(that)h(caused)g(the)g(problem)e (\(usually)1248 2677 y(because)c(it)i(is)g(unkno)n(wn\).)369 2777 y Fk(detail)p 834 3006 4 299 v 358 w Fl(None)p 1196 3006 V 131 w Fn(A)k(sequence)f(of)h(elements)f(to)h(output)f(in)h(the)g Fl(detail)f Fn(element;)j(it)f(may)e(also)h(be)1248 2877 y(a)d(te)o(xt)h(string,)f(in)g(which)g(case)g(it)h(is)g(output)e (as-is,)j(and)d(should)g(therefore)g(be)h(XML)1248 2976 y(te)o(xt.)369 3076 y Fk(header)m(detail)p 834 3205 4 200 v 129 w Fl(None)p 1196 3205 V 131 w Fn(Data,)i(treated)e(the)h (same)g(as)h(the)f Fl(detail)f Fn(k)o(e)o(yw)o(ord,)f(to)j(be)e(output) g(in)h(the)g(SO)m(AP)1248 3175 y(header)-5 b(.)24 b(See)d(the)f(follo)n (wing)e(paragraph.)208 3304 y(If)j(the)h(f)o(ault)f(occurred)f(in)h (the)h(SO)m(AP)g Fl(Header)p Fn(,)f(the)h(speci\002cation)f(requires)f (that)i(the)g(detail)f(be)h(sent)g(back)e(as)j(an)e(element)208 3403 y(within)26 b(the)h(SO)m(AP)g Fl(Header)f Fn(element.)44 b(Unfortunately)-5 b(,)25 b(the)h(SO)m(AP)i(speci\002cation)e(does)g (not)g(describe)g(ho)n(w)g(to)h(encode)208 3503 y(this;)20 b Fl(ZSI)h Fn(de\002nes)f(and)f(uses)i(a)f Fl(ZSI:detail)f Fn(element,)h(which)f(is)j(analogous)c(to)i(the)g(SO)m(AP)i Fl(detail)d Fn(element.)0 3650 y(The)h(follo)n(wing)e(attrib)n(utes)j (are)f(read-only:)0 3797 y Fj(actor)208 3896 y Fn(A)g(te)o(xt)g(string) g(holding)f(the)h(v)n(alue)f(of)h(the)g(SO)m(AP)i Fl(faultactor)c Fn(element.)0 4043 y Fj(code)208 4143 y Fn(A)i(te)o(xt)g(string)g (holding)f(the)h(v)n(alue)f(of)h(the)g(SO)m(AP)i Fl(faultcode)d Fn(element.)0 4290 y Fj(detail)208 4389 y Fn(A)i(te)o(xt)g(string)g(or) g(sequence)f(of)h(elements)g(containing)f(holding)f(the)j(v)n(alue)e (of)h(the)g(SO)m(AP)i Fl(detail)d Fn(element,)h(when)g(a)n(v)n(ail-)208 4489 y(able.)0 4636 y Fj(headerdetail)208 4735 y Fn(A)29 b(te)o(xt)g(string)g(or)g(sequence)g(of)g(elements)g(containing)e (holding)h(the)h(v)n(alue)f(of)h(the)h Fl(ZSI)f Fn(header)f(detail)h (element,)i(when)208 4835 y(a)n(v)n(ailable.)0 4982 y Fj(string)208 5081 y Fn(A)20 b(te)o(xt)g(string)g(holding)f(the)h(v)n (alue)f(of)h(the)g(SO)m(AP)i Fl(faultstring)c Fn(element.)0 5228 y Fj(AsSOAP)p Fl(\()p Fc([)p Fk(,)h(**kw)12 b Fc(])p Fl(\))208 5328 y Fn(This)29 b(method)f(serializes)i(the)f Fl(Fault)g Fn(object)g(into)g(a)h(SO)m(AP)h(message.)52 b(The)29 b(message)g(is)i(returned)c(as)j(a)g(string.)52 b(An)o(y)p 0 5549 3901 4 v 3808 5649 a Fi(33)p eop end %%Page: 34 40 TeXDict begin 34 39 bop 208 83 a Fn(k)o(e)o(yw)o(ord)26 b(ar)o(guments)h(are)i(passed)g(to)f(the)h Fl(SoapWriter)f Fn(constructor)-5 b(.)100 b(Ne)n(w)29 b(in)g(v)o(ersion)f(1.1;)k(the)d (old)f Fl(AsSoap\(\))208 183 y Fn(method)18 b(is)k(still)f(a)n(v)n (ailable.)0 330 y(If)f(other)f(data)h(is)h(going)e(to)h(be)g(sent)g (with)h(the)f(f)o(ault,)f(the)i(follo)n(wing)d(tw)o(o)i(methods)f(can)h (be)g(used.)25 b(Because)20 b(some)g(data)g(might)f(need)0 429 y(to)h(be)g(output)f(in)i(the)f(SO)m(AP)h Fl(Header)p Fn(,)e(serializing)h(a)h(f)o(ault)f(is)h(a)g(tw)o(o-step)e(process.)0 576 y Fj(DataForSOAPHeader)p Fl(\(\))208 676 y Fn(This)c(method)f (returns)g(a)i(te)o(xt)f(string)g(that)g(can)g(be)g(included)f(as)i (the)f Fl(header)g Fn(parameter)e(for)i(constructing)e(a)j Fl(SoapWriter)208 775 y Fn(object.)0 922 y Fj(serialize)p Fl(\()p Fk(sw)p Fl(\))208 1022 y Fn(This)k(method)f(outputs)g(the)h(f)o (ault)g(object)g(onto)f(the)i Fk(sw)g Fn(object,)e(which)h(is)h(a)g Fl(SoapWriter)e Fn(instance.)0 1169 y(Some)h(con)m(v)o(enience)d (functions)i(are)h(a)n(v)n(ailable)g(to)g(create)g(a)h Fl(Fault)e Fn(from)g(common)g(conditions.)0 1316 y Fj(FaultFromActor)p Fl(\()p Fk(uri)p Fc([)p Fk(,)e(actor)d Fc(])p Fl(\))208 1415 y Fn(This)19 b(function)e(could)g(be)i(used)g(when)f(an)g (application)g(recei)n(v)o(es)g(a)h(message)g(that)f(has)h(a)h(SO)m(AP) f Fl(Header)f Fn(element)h(directed)208 1515 y(to)h(an)h(actor)f(that)h (cannot)f(be)g(processed.)26 b(The)20 b Fk(uri)i Fn(parameter)d (identi\002es)h(the)h(actor)-5 b(.)27 b(The)20 b Fk(actor)j Fn(parameter)c(can)h(be)h(used)f(to)208 1614 y(specify)f(a)i(URI)f (that)h(identi\002es)f(the)g(application,)f(if)h(it)h(is)g(not)f(the)g (ultimate)g(recipient)f(of)h(the)g(SO)m(AP)h(message.)0 1761 y Fj(FaultFromException)p Fl(\()p Fk(e)n(x,)c(inheader)r Fc([)p Fk(,)h(tb)p Fc([)p Fk(,)i(actor)14 b Fc(])e(])p Fl(\))208 1861 y Fn(This)27 b(function)f(creates)i(a)g Fl(Fault)f Fn(from)g(a)h(general)e(Python)h(e)o(xception.)45 b(A)28 b(SO)m(AP)h(\223serv)o(er\224)d(f)o(ault)i(is)g(created.)47 b(The)27 b Fk(e)n(x)208 1961 y Fn(parameter)k(should)g(be)i(the)f (Python)g(e)o(xception.)60 b(The)32 b Fk(inheader)h Fn(parameter)e (should)g(be)i(true)f(if)h(the)g(error)e(w)o(as)i(found)208 2060 y(on)28 b(a)h(SO)m(AP)g Fl(Header)f Fn(element.)50 b(The)28 b(optional)f Fk(tb)i Fn(parameter)e(may)h(be)g(a)h(Python)f (traceback)f(object,)j(as)f(returned)e(by)208 2160 y(`)p Fl(sys.exc_info\(\)[2])p Fn('.)d(The)c Fk(actor)j Fn(parameter)d(can)g (be)h(used)g(to)g(specify)g(a)g(URI)h(that)f(identi\002es)g(the)g (application,)e(if)208 2259 y(it)h(is)i(not)d(the)i(ultimate)f (recipient)f(of)h(the)g(SO)m(AP)h(message.)0 2406 y Fj (FaultFromFaultMessage)p Fl(\()p Fk(ps)p Fl(\))208 2506 y Fn(This)29 b(function)g(creates)g(a)i Fl(Fault)e Fn(from)g(a)h Fl(ParsedSoap)e Fn(object)h(passed)h(in)g(as)h Fk(ps)p Fn(.)54 b(It)30 b(should)e(only)h(be)h(used)f(if)i(the)208 2606 y Fl(IsAFault\(\))18 b Fn(method)h(returned)g(true.)0 2752 y Fj(FaultFromNotUnderstood)p Fl(\()p Fk(uri,)d(localname)o(,)p Fc([)p Fk(,)i(actor)c Fc(])p Fl(\))208 2852 y Fn(This)26 b(function)e(could)h(be)g(used)h(when)f(an)h(application)e(recei)n(v)o (es)h(a)h(message)g(with)g(the)g(SO)m(AP)h Fl(mustUnderstand)c Fn(at-)208 2952 y(trib)n(ute)17 b(that)h(it)g(does)g(not)f(understand.) 22 b(The)c Fk(uri)g Fn(and)f Fk(localname)f Fn(parameters)h(should)g (identify)f(the)i(unkno)n(wn)d(element.)24 b(The)208 3051 y Fk(actor)f Fn(parameter)d(can)h(be)h(used)f(to)g(specify)g(a)h (URI)g(that)g(identi\002es)f(the)h(application,)e(if)i(it)g(is)g(not)g (the)f(ultimate)g(recipient)g(of)208 3151 y(the)f(SO)m(AP)h(message.)0 3298 y Fj(FaultFromZSIException)p Fl(\()p Fk(e)n(x)p Fc([)p Fk(,)c(actor)d Fc(])p Fl(\))208 3397 y Fn(This)k(function)e (creates)i(a)h Fl(Fault)f Fn(object)f(from)g(a)i Fl(ZSI)f Fn(e)o(xception,)e Fl(ParseException)h Fn(or)g Fl(EvaluateException)p Fn(,)208 3497 y(passed)29 b(in)h(as)h Fk(e)n(x)p Fn(.)55 b(A)30 b(SO)m(AP)h(\223client\224)e(f)o(ault)h(is)h(created.)53 b(The)30 b Fk(actor)h Fn(parameter)e(can)g(be)h(used)g(to)g(specify)f (a)h(URI)g(that)208 3597 y(identi\002es)20 b(the)g(application,)e(if)j (it)g(is)g(not)f(the)g(ultimate)g(recipient)f(of)h(the)g(SO)m(AP)h (message.)p 0 5549 3901 4 v 0 5649 a Fi(34)1958 b(Chapter)24 b(8.)52 b(The)23 b Fl(Fault)f Fi(module)i(\227)f(repor)s(ting)h(errors) p eop end %%Page: 35 41 TeXDict begin 35 40 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3614 427 y Fh(NINE)p 0 515 V 598 978 a Ft(The)57 b Fd(resolvers)g Ft(module)g(\227)g(f)-6 b(etching)2798 1227 y(remote)57 b(data)0 1706 y Fn(The)33 b Fl(resolvers)f Fn(module)g(pro)o(vides)g (some)h(functions)f(and)h(classes)h(that)g(can)f(be)g(used)g(as)h(the)g Fl(resolver)e Fn(attrib)n(ute)h(for)0 1805 y Fl(TC.String)c Fn(or)g Fl(TC.XML)g Fn(typecodes.)53 b(The)o(y)29 b(process)g(an)h (absolute)f(URL,)h(as)g(described)f(abo)o(v)o(e,)h(and)f(return)g(the)h (content.)0 1905 y(Because)d(the)h Fl(resolvers)e Fn(module)f(can)i (import)f(a)i(number)d(of)i(other)g(lar)o(ge)f(modules,)h(it)h(must)f (be)h(imported)d(directly)-5 b(,)28 b(as)f(in)0 2005 y(`)p Fl(from)49 b(ZSI)g(import)g(resolvers)p Fn('.)0 2151 y(These)22 b(\002rst)h(tw)o(o)g(functions)e(pass)i(the)f(URI)h (directly)e(to)i(the)f Fl(urlopen)g Fn(function)e(in)j(the)f Fl(urllib)g Fn(module.)30 b(Therefore,)20 b(if)j(used)0 2251 y(directly)17 b(as)i(resolv)o(ers,)f(a)h(client)f(could)f(direct)h (the)g(SO)m(AP)h(application)e(to)i(fetch)e(an)o(y)h(\002le)h(on)f(the) g(netw)o(ork)f(or)h(local)g(disk.)24 b(Needless)0 2351 y(to)c(say)-5 b(,)20 b(this)h(could)e(pose)h(a)h(security)e(risks.)0 2498 y Fj(Opaque)p Fl(\()p Fk(uri,)g(tc,)i(ps)p Fc([)p Fk(,)f(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2597 y Fn(This)20 b(function)e(returns)h(the)g(data)h(contained)e(at)j(the)f (speci\002ed)f Fl(uri)h Fn(as)h(a)f(Python)f(string.)24 b(Base-64)19 b(decoding)f(will)j(be)f(done)208 2697 y(if)g(necessary)-5 b(.)24 b(The)c Fl(tc)g Fn(and)g Fl(ps)g Fn(parameters)f(are)h(ignored;) f(the)h Fl(keywords)f Fn(are)h(passed)g(to)h(the)f Fl(urlopen)f Fn(method.)0 2844 y Fj(XML)p Fl(\()p Fk(uri,)h(tc,)g(ps)p Fc([)p Fk(,)g(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2943 y Fn(This)21 b(function)f(returns)h(a)g(list)i(of)e(the)h(child)f (element)g(nodes)f(of)h(the)h(XML)f(document)f(at)i(the)f(speci\002ed)h Fl(uri)p Fn(.)28 b(The)21 b Fl(tc)h Fn(and)208 3043 y Fl(ps)e Fn(parameters)f(are)h(ignored;)e(the)j Fl(keywords)e Fn(are)h(passed)g(to)h(the)f Fl(urlopen)f Fn(method.)0 3190 y(The)h Fl(NetworkResolver)e Fn(class)j(pro)o(vides)d(a)j (simple-minded)d(w)o(ay)i(to)g(limit)h(the)f(URI')-5 b(s)21 b(that)g(will)g(be)f(resolv)o(ed.)0 3337 y Fo(class)h Fj(NetworkResolver)p Fl(\()p Fc([)p Fk(pr)m(e\002xes=None)12 b Fc(])p Fl(\))208 3436 y Fn(The)23 b Fl(prefixes)f Fn(parameter)g(is)j (a)f(list)h(of)e(strings)g(de\002ning)g(the)g(allo)n(wed)g(pre\002x)o (es)g(of)g(an)o(y)g(URI')-5 b(s.)36 b(If)23 b(ask)o(ed)h(to)f(fetch)h (the)208 3536 y(content)19 b(for)g(a)i(URI)g(that)f(does)g(start)h (with)f(one)g(of)f(the)i(pre\002x)o(es,)e(it)i(will)g(raise)f(an)g(e)o (xception.)208 3669 y(In)i(addition)g(to)h Fl(Opaque)g Fn(and)f Fl(XML)h Fn(methods,)f(this)i(class)g(pro)o(vides)d(a)i Fl(Resolve)g Fn(method)e(that)i(e)o(xamines)f(the)h(typecode)208 3768 y(to)d(determine)f(what)h(type)g(of)f(data)i(is)g(desired.)0 3915 y(If)27 b(the)f(SO)m(AP)i(application)d(is)j(gi)n(v)o(en)d(a)i (multi-part)f(MIME)g(document,)g(the)h Fl(MIMEResolver)e Fn(class)j(can)e(be)h(used)f(to)h(process)0 4015 y(SO)m(AP)21 b(with)f(Attachments.)0 4162 y(The)50 b Fl(MIMEResolver)f Fn(class)j(will)f(read)f(the)h(entire)f(multipart)f(MIME)i(document,)k (noting)50 b(an)o(y)g Fl(Content-ID)f Fn(or)0 4261 y Fl(Content-Location)29 b Fn(headers)h(that)i(appear)e(on)h(the)g (headers)f(of)h(an)o(y)g(of)g(the)g(message)g(parts,)j(and)d(use)g (them)g(to)g(resolv)o(e)0 4361 y(an)o(y)19 b Fl(href)h Fn(attrib)n(utes)h(that)f(appear)f(in)h(the)g(SO)m(AP)h(message.)0 4508 y Fo(class)g Fj(MIMEResolver)p Fl(\()p Fk(ct,)d(f)12 b Fc([)p Fk(,)20 b(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 4608 y Fn(The)19 b Fl(ct)h Fn(parameter)e(is)j(a)f(string)g(that)g (contains)f(the)h(v)n(alue)f(of)g(the)h(MIME)f Fl(Content-Type)g Fn(header)-5 b(.)24 b(The)19 b Fl(f)h Fn(parameter)f(is)208 4707 y(the)h(input)f(stream,)h(which)g(should)f(be)h(positioned)f(just) h(after)g(the)g(message)h(headers.)208 4840 y(The)e(follo)n(wing)g(k)o (e)o(yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)p 0 5549 3901 4 v 3808 5649 a Fi(35)p eop end %%Page: 36 42 TeXDict begin 36 41 bop 378 70 a Fo(K)n(eyw)o(ord)p 825 100 4 100 v 172 w(Default)p 1187 100 V 99 w(Description)p 328 103 3451 4 v 378 173 a Fl(seekable)p 825 402 4 299 v 205 w(0)p 1187 402 V 206 w Fn(Whether)25 b(or)g(not)g(the)g(input)g (stream)g(is)h(seekable;)i(passed)d(to)h(the)f(constructor)f(for)1239 272 y(the)19 b(internal)f Fl(multifile)g Fn(object.)49 b(Changed)18 b(in)h(v)o(ersion)f(2.0:)h(def)o(ault)f(had)h(been)1239 372 y(1.)378 472 y Fl(next)p 825 601 4 200 v 330 w(None)p 1187 601 V 131 w Fn(A)k(resolv)o(er)f(object)g(that)i(will)f(be)g(ask)o (ed)g(to)g(resolv)o(e)f(the)h(URI)h(if)f(it)h(is)g(not)f(found)e(in) 1239 571 y(the)f(MIME)g(document.)48 b(Ne)n(w)21 b(in)f(v)o(ersion)f (1.1.)378 671 y Fl(uribase)p 825 900 4 299 v 180 w(None)p 1187 900 V 131 w Fn(The)j(base)h(URI)g(to)g(be)g(used)f(when)g (resolving)f(relati)n(v)o(e)h(URI')-5 b(s;)25 b(this)e(will)h (typically)1239 770 y(be)30 b(the)h(v)n(alue)f(of)g(the)h Fl(Content-Location)d Fn(header)m(,)j(if)g(present.)112 b(Ne)n(w)31 b(in)1239 870 y(v)o(ersion)19 b(1.1.)0 1012 y(In)h(addition)f(to)h(to)h(the)f Fl(Opaque)p Fn(,)f Fl(Resolve)p Fn(,)g(and)h Fl(XML)g Fn(methods)f(as)i(described)e(abo)o (v)o(e,)f(the)j(follo)n(wing)d(method)h(is)i(a)n(v)n(ailable:)0 1159 y Fj(GetSOAPPart)p Fl(\(\))208 1259 y Fn(This)f(method)f(returns)g (a)i(stream)f(containing)e(the)i(SO)m(AP)h(message)f(te)o(xt.)0 1405 y(The)g(follo)n(wing)e(attrib)n(utes)j(are)f(read-only:)0 1552 y Fj(parts)208 1652 y Fn(An)65 b(array)g(of)g(tuples,)76 b(one)65 b(for)g(each)g(MIME)g(bodypart)e(found.)159 b(Each)65 b(tuple)g(has)h(tw)o(o)g(elements,)76 b(a)208 1752 y Fl(mimetools.Message)26 b Fn(object)j(which)f(contains)h(the)g (headers)f(for)h(the)g(bodypart,)g(and)f(a)i Fl(StringIO)e Fn(object)g(con-)208 1851 y(taining)19 b(the)h(data.)0 1998 y Fj(id_dict)208 2098 y Fn(A)32 b(dictionary)d(whose)i(k)o(e)o(ys) h(are)f(the)h(v)n(alues)f(of)g(an)o(y)g Fl(Content-ID)f Fn(headers,)j(and)e(whose)g(v)n(alue)g(is)h(the)g(appropriate)208 2197 y Fl(parts)19 b Fn(tuple.)0 2344 y Fj(loc_dict)208 2444 y Fn(A)k(dictionary)e(whose)i(k)o(e)o(ys)g(are)g(the)g(v)n(alues)f (of)h(an)o(y)f Fl(Content-Location)f Fn(headers,)i(and)f(whose)h(v)n (alue)f(is)i(the)f(appro-)208 2543 y(priate)c Fl(parts)h Fn(tuple.)p 0 5549 3901 4 v 0 5649 a Fi(36)1575 b(Chapter)24 b(9.)52 b(The)23 b Fl(resolvers)e Fi(module)k(\227)e(f)n(etching)g (remote)g(data)p eop end %%Page: 37 43 TeXDict begin 37 42 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3661 427 y Fh(TEN)p 0 515 V 1602 978 a Ft(Dispatching)57 b(and)g(In)l(v)-5 b(oking)0 1468 y Fn(Ne)n(w)20 b(in)h(v)o(ersion)e(1.1.)0 1615 y Fl(ZSI)f Fn(is)g(focused)e(on)h(parsing)g(and)g(generating)f(SO) m(AP)i(messages,)g(and)f(pro)o(vides)f(limited)h(f)o(acilities)h(for)f (dispatching)f(to)i(the)f(appro-)0 1714 y(priate)22 b(message)g (handler)-5 b(.)29 b(This)23 b(is)g(because)e Fl(ZSI)h Fn(w)o(orks)g(within)g(man)o(y)f(client)h(and)g(serv)o(er)f(en)m (vironments,)e(and)j(the)g(dispatching)0 1814 y(styles)f(for)e(these)i (dif)n(ferent)d(en)m(vironments)g(can)i(be)g(v)o(ery)f(dif)n(ferent.)0 1961 y(Ne)n(v)o(ertheless,)f Fl(ZSI)g Fn(includes)g(some)h(dispatch)f (and)g(in)m(v)n(ocation)e(functions.)23 b(T)-7 b(o)19 b(use)g(them,)f(the)o(y)g(must)h(be)f(e)o(xplicitly)g(imported,)f(as)0 2061 y(sho)n(wn)i(in)i(the)f(e)o(xample)f(at)h(the)h(start)f(of)g(this) h(document.)0 2207 y(The)d(implementation)e(\(and)h(names\))h(of)g(the) g(these)h(classes)g(re\003ects)f(the)h(orientation)d(of)i(using)g(SO)m (AP)h(for)f(remote)f(procedure)f(calls)0 2307 y(\(RPC\).)0 2454 y(Both)k(client)g(and)g(serv)o(er)f(share)h(a)h(class)g(that)f (de\002nes)g(the)h(mechanism)d(a)j(client)f(uses)h(to)f(authenticate)f (itself.)0 2601 y Fo(class)i Fj(AUTH)p Fl(\(\))208 2700 y Fn(This)j(class)h(de\002nes)e(constants)h(used)g(to)g(identify)f(ho)n (w)g(the)h(client)g(authenticated:)31 b Fl(none)24 b Fn(if)g(no)g(authentication)e(w)o(as)j(pro-)208 2800 y(vided;)k Fl(httpbasic)d Fn(if)i(HTTP)f(basic)h(authentication)d(w)o (as)j(used,)g(or)f Fl(zsibasic)f Fn(if)i Fl(ZSI)f Fn(basic)g (authentication)e(\(see)208 2900 y(belo)n(w\)\))18 b(w)o(as)j(used.)0 3047 y(The)i Fl(ZSI)f Fn(schema)h(\(see)g(the)g(last)h(chapter)d(of)i (this)g(manual\))f(de\002nes)g(a)i(SO)m(AP)f(header)f(element,)h Fl(BasicAuth)p Fn(,)f(that)h(contains)f(a)0 3146 y(name)e(and)f(passw)o (ord.)24 b(This)d(is)g(similar)f(to)g(the)g(HTTP)h(basic)f (authentication)e(header)m(,)h(e)o(xcept)g(that)h(it)h(can)f(be)g(used) g(independently)0 3246 y(from)f(an)h(HTTP)h(transport.)0 3573 y Fg(10.1)121 b(Dispatching)0 3806 y Fn(The)28 b Fl(ZSI.dispatch)e Fn(module)h(allo)n(ws)i(you)e(to)i(e)o(xpose)e (Python)g(functions)g(as)i(a)f(web)g(service.)49 b(The)28 b(module)f(pro)o(vides)g(the)0 3906 y(infrastructure)20 b(to)i(parse)g(the)g(request,)f(dispatch)g(to)i(the)f(appropriate)d (handler)m(,)i(and)g(then)h(serialize)g(an)o(y)f(return)g(v)n(alue)g (back)g(to)i(the)0 4005 y(client.)35 b(The)23 b(v)n(alue)g(returned)f (by)h(the)g(function)f(will)j(be)e(serialized)g(back)g(to)h(the)f (client.)35 b(If)24 b(an)f(e)o(xception)f(occurs,)h(a)h(SO)m(AP)h(f)o (ault)0 4105 y(will)c(be)f(sent)h(back)e(to)h(the)h(client.)0 4390 y Ff(10.1.1)101 b(Dispatch)28 b(Beha)n(viors)0 4593 y Fn(By)22 b(def)o(ault)e(the)i(callback)e(is)j(in)m(v)n(ok)o(ed)c (with)j(the)f(p)o(yobj)f(representation)g(of)h(the)g(body)f(root)h (element,)f(and)h(it)h(is)h(e)o(xpected)c(to)j(return)0 4692 y(a)28 b(self-describing)d(request)i(\(w/typecode\).)44 b(P)o(arsing)27 b(is)h(done)e(via)i(a)f(typecode)f(from)g(typesmodule,) h(or)g(An)o(y)-5 b(.)45 b(Other)27 b(k)o(e)o(yw)o(ord)0 4792 y(options)19 b(are)h(a)n(v)n(ailable)g(in)g(dispatch)g(mechanisms) f(\(see)i(belo)n(w\))e(that)h(result)g(in)h(dif)n(ferent)d(beha)n(vior) -5 b(.)0 5060 y Fi(r)r(pc)0 5263 y Fn(An)19 b(rpc)f(service)g(will)h (ignore)e(the)i(body)e(root)h(\(RPC)h(Wrapper\))e(of)h(the)h(request,)f (and)g(parse)g(all)h(\224parts\224)f(of)h(message)f(via)g(indi)n (vidual)0 5363 y(typecodes.)55 b(The)30 b(callback)g(function)f(is)j(e) o(xpected)d(to)i(return)f(the)g(parts)h(of)f(the)h(message)g(in)g(a)g (dict)g(or)f(a)h(list.)58 b(The)30 b(dispatch)p 0 5549 3901 4 v 3808 5649 a Fi(37)p eop end %%Page: 38 44 TeXDict begin 38 43 bop 0 83 a Fn(mechanism)22 b(will)i(try)f(to)h (serialize)g(it)g(as)g(a)g(Struct)f(b)n(ut)g(if)h(this)g(is)g(not)f (possible)g(it)i(will)f(be)f(serialized)g(as)h(an)g(Array)-5 b(.)33 b(P)o(arsing)23 b(done)0 183 y(via)d(a)h(typecode)d(from)h (typesmodule,)f(or)i(An)o(y)-5 b(.)24 b(Not)c(compatible)f(with)h Fk(docstyle)p Fn(.)0 451 y Fi(docstyle)0 654 y Fn(Callback)15 b(is)i(in)m(v)n(ok)o(ed)d(with)h(a)h(P)o(arsedSoap)f(instance)g (representing)e(the)j(request,)g(and)f(the)g(return)g(v)n(alue)f(is)j (serialized)e(with)h(an)g(XML)0 753 y(typecode)h(\(DOM\).)g(The)h (result)h(in)f(wrapped)f(as)i(an)g(rpc-style)e(message,)h(with)h Fk(Response)e Fn(appended)g(to)h(the)g(request)g(wrapper)-5 b(.)23 b(Not)0 853 y(compatible)c(with)h Fk(rpc)p Fn(.)0 1138 y Ff(10.1.2)101 b(Special)29 b(Modules)0 1341 y Fn(These)20 b(are)g(k)o(e)o(yw)o(ord)e(options)i(a)n(v)n(ailable)f(to)i (all)g(dispatch)e(mechansism)g(\(see)i(belo)n(w\).)0 1609 y Fi(modules)0 1812 y Fn(Dispatch)g(is)i(based)e(solely)g(on)g (the)h(name)f(of)g(the)g(root)g(element)g(in)h(the)f(incoming)f(SO)m (AP)i(request;)g(the)f(request)g(URL)h(is)h(ignored.)0 1912 y(These)e(modules)f(will)i(be)f(search)g(for)f(a)i(matching)e (function.)26 b(If)21 b(no)f(modules)g(are)i(speci\002ed,)e(only)h(the) g Fl(__main__)f Fn(module)g(will)0 2011 y(be)g(searched.)0 2280 y Fi(typesmodule)0 2483 y Fn(Used)28 b(for)g(parsing.)47 b(This)28 b(module)f(should)g(contain)g(class)i(de\002nitions)e(with)h (the)g Fl(typecode)f Fn(attrib)n(ute)h(set)h(to)f(a)g Fl(TypeCode)0 2582 y Fn(instance.)i(By)22 b(def)o(ault,)g(a)g(class)h (de\002nition)e(matching)g(the)h(root)f(element)g(name)h(will)g(be)g (retrie)n(v)o(ed)f(or)g(the)h(An)o(y)g(typecode)e(will)j(be)0 2682 y(used.)i(If)20 b(using)f Fk(rpc)p Fn(,)i(each)e(child)h(of)g(the) g(root)g(element)f(will)i(be)f(used)g(to)h(retrie)n(v)o(e)e(a)h(class)i (de\002nition)d(of)g(the)i(same)f(name.)0 2967 y Ff(10.1.3)101 b(Dispatch)28 b(Mechanisms)0 3170 y Fn(Three)e(dispatch)g(mechanisms)f (are)i(pro)o(vided:)35 b(one)26 b(supports)f(standard)h(CGI)h(scripts,) h(one)e(runs)g(a)h(dedicated)e(serv)o(er)h(based)g(on)0 3269 y(the)19 b Fl(BaseHTTPServer)e Fn(module,)g(and)i(the)f(third)h (uses)g(the)g(JonPY)g(package,)e Fl(http://jonpy.sourceforge.net)p Fn(,)d(to)0 3369 y(support)19 b(F)o(astCGI.)0 3516 y Fj(AsServer)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3615 y Fn(This)21 b(creates)g(a)g Fl(HTTPServer)f Fn(object)g(with)h(a)h(request)e(handler)g(that)h(only) f(supports)g(the)h(\223POST\224)g(method.)26 b(Dispatch)21 b(is)208 3715 y(based)e(solely)h(on)g(the)g(name)g(of)g(the)g(root)g (element)f(in)i(the)f(incoming)e(SO)m(AP)j(request;)f(the)g(request)g (URL)g(is)h(ignored.)208 3848 y(The)e(follo)n(wing)g(k)o(e)o(yw)o(ord)f (ar)o(guments)g(may)i(be)g(used:)257 4059 y Fo(K)n(eyw)o(ord)p 853 4089 4 100 v 464 w(Default)p 1501 4089 V 242 w(Description)p 208 4092 3886 4 v 257 4162 a Fl(port)p 853 4192 4 100 v 672 w(80)p 1501 4192 V 324 w Fn(Port)g(to)g(listen)h(on.)257 4261 y Fl(addr)p 853 4291 V 672 w('')p 1501 4291 V 324 w Fn(Address)e(to)i(listen)f(on.)257 4361 y Fl(docstyle)p 853 4391 V 397 w(False)p 1501 4391 V 249 w Fn(Exhibit)f(the)h Fk(docstyle)g Fn(beha)n(vior)-5 b(.)257 4461 y Fl(rpc)p 853 4490 V 647 w(False)p 1501 4490 V 249 w Fn(Exhibit)19 b(the)h Fk(rpc)g Fn(beha)n(vior)-5 b(.)257 4560 y Fl(modules)p 853 4590 V 298 w(\(__main__,\))p 1501 4590 V 98 w Fn(List)20 b(of)g(modules)f(containing)g(functions)g(that)h(can)g(be)g(in)m(v)n (ok)o(ed.)257 4660 y Fl(typesmodule)p 853 4789 4 200 v 98 w(\(__main__,\))p 1501 4789 V 98 w Fn(This)e(module)e(is)j(used)f (for)g(parsing,)f(it)i(contains)e(class)i(de\002nitions)e(that)h (specify)g(the)1553 4759 y Fl(typecode)h Fn(attrib)n(ute.)257 4859 y Fl(nsdict)p 853 4889 4 100 v 572 w({})p 1501 4889 V 324 w Fn(Namespace)g(dictionary)f(to)j(send)f(in)g(the)g(SO)m(AP)h Fl(Envelope)0 5024 y Fj(AsCGI)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds) 12 b Fc(])p Fl(\))208 5124 y Fn(This)20 b(method)e(parses)i(the)g(CGI)g (input)g(and)f(in)m(v)n(ok)o(es)g(a)h(function)e(that)i(has)g(the)g (same)g(name)g(as)g(the)g(top-le)n(v)o(el)e(SO)m(AP)j(request)208 5224 y(element.)208 5356 y(The)e(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o (guments)g(may)i(be)g(used:)p 0 5549 3901 4 v 0 5649 a Fi(38)2399 b(Chapter)23 b(10.)52 b(Dispatching)24 b(and)g(In)n(v)n (oking)p eop end %%Page: 39 45 TeXDict begin 39 44 bop 257 161 a Fo(K)n(eyw)o(ord)p 853 191 4 100 v 464 w(Default)p 1501 191 V 242 w(Description)p 208 194 3886 4 v 257 264 a Fl(rpc)p 853 294 4 100 v 647 w(False)p 1501 294 V 249 w Fn(Exhibit)19 b(the)h Fk(rpc)g Fn(beha)n(vior)-5 b(.)257 364 y Fl(modules)p 853 394 V 298 w(\(__main__,\))p 1501 394 V 98 w Fn(List)20 b(of)g(modules)f (containing)g(functions)g(that)h(can)g(be)g(in)m(v)n(ok)o(ed.)257 463 y Fl(typesmodule)p 853 593 4 200 v 98 w(\(__main__,\))p 1501 593 V 98 w Fn(This)e(module)e(is)j(used)f(for)g(parsing,)f(it)i (contains)e(class)i(de\002nitions)e(that)h(specify)g(the)1553 563 y Fl(typecode)h Fn(attrib)n(ute.)257 663 y Fl(nsdict)p 853 692 4 100 v 572 w({})p 1501 692 V 324 w Fn(Namespace)g(dictionary)f (to)j(send)f(in)g(the)g(SO)m(AP)h Fl(Envelope)0 828 y Fj(AsHandler)p Fl(\()p Fk(r)m(equest=None)p Fc([)p Fk(,)c(**k)o(e)n (ywor)m(ds)12 b Fc(])p Fl(\))208 927 y Fn(This)20 b(method)f(is)i(used) f(within)g(a)g(JonPY)h(handler)d(to)j(do)e(dispatch.)208 1055 y(The)g(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o(guments)g(may)i(be) g(used:)257 1261 y Fo(K)n(eyw)o(ord)p 853 1291 V 464 w(Default)p 1501 1291 V 242 w(Description)p 208 1294 3886 4 v 257 1364 a Fl(request)p 853 1394 4 100 v 472 w(None)p 1501 1394 V 274 w Fn(modp)o(ython)d(HTTPRequest)i(instance.) 257 1464 y Fl(modules)p 853 1494 V 298 w(\(__main__,\))p 1501 1494 V 98 w Fn(List)h(of)g(modules)f(containing)g(functions)g (that)h(can)g(be)g(in)m(v)n(ok)o(ed.)257 1563 y Fl(docstyle)p 853 1593 V 397 w(False)p 1501 1593 V 249 w Fn(Exhibit)f(the)h Fk(docstyle)g Fn(beha)n(vior)-5 b(.)257 1663 y Fl(rpc)p 853 1693 V 647 w(False)p 1501 1693 V 249 w Fn(Exhibit)19 b(the)h Fk(rpc)g Fn(beha)n(vior)-5 b(.)257 1762 y Fl(typesmodule)p 853 1892 4 200 v 98 w(\(__main__,\))p 1501 1892 V 98 w Fn(This)18 b(module)e(is)j(used)f(for)g(parsing,)f(it)i(contains)e (class)i(de\002nitions)e(that)h(specify)g(the)1553 1862 y Fl(typecode)h Fn(attrib)n(ute.)257 1962 y Fl(nsdict)p 853 1992 4 100 v 572 w({})p 1501 1992 V 324 w Fn(Namespace)g (dictionary)f(to)j(send)f(in)g(the)g(SO)m(AP)h Fl(Envelope)0 2127 y Fj(AsJonPy)p Fl(\()p Fk(r)m(equest=None)p Fc([)p Fk(,)c(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2227 y Fn(This)20 b(method)f(is)i(used)f(within)g(a)g(JonPY)h(handler)d(to)j (do)e(dispatch.)208 2354 y(The)g(follo)n(wing)g(k)o(e)o(yw)o(ord)f(ar)o (guments)g(may)i(be)g(used:)257 2560 y Fo(K)n(eyw)o(ord)p 853 2590 V 464 w(Default)p 1501 2590 V 242 w(Description)p 208 2593 3886 4 v 257 2663 a Fl(request)p 853 2693 4 100 v 472 w(None)p 1501 2693 V 274 w Fn(jonp)o(y)f(Request)h(instance.) 257 2763 y Fl(modules)p 853 2793 V 298 w(\(__main__,\))p 1501 2793 V 98 w Fn(List)g(of)g(modules)f(containing)g(functions)g (that)h(can)g(be)g(in)m(v)n(ok)o(ed.)257 2862 y Fl(docstyle)p 853 2892 V 397 w(False)p 1501 2892 V 249 w Fn(Exhibit)f(the)h Fk(docstyle)g Fn(beha)n(vior)-5 b(.)257 2962 y Fl(rpc)p 853 2992 V 647 w(False)p 1501 2992 V 249 w Fn(Exhibit)19 b(the)h Fk(rpc)g Fn(beha)n(vior)-5 b(.)257 3062 y Fl(typesmodule)p 853 3191 4 200 v 98 w(\(__main__,\))p 1501 3191 V 98 w Fn(This)18 b(module)e(is)j(used)f(for)g(parsing,)f(it)i(contains)e (class)i(de\002nitions)e(that)h(specify)g(the)1553 3161 y Fl(typecode)h Fn(attrib)n(ute.)257 3261 y Fl(nsdict)p 853 3291 4 100 v 572 w({})p 1501 3291 V 324 w Fn(Namespace)g (dictionary)f(to)j(send)f(in)g(the)g(SO)m(AP)h Fl(Envelope)208 3384 y Fn(The)e(follo)n(wing)g(code)g(sho)n(ws)i(a)f(sample)g(use:)444 3603 y Fe(import)44 b(jon.fcgi)444 3694 y(from)g(ZSI)g(import)g (dispatch)444 3786 y(import)g(MyHandler)444 3968 y(class)g (Handler\(cgi.Handler\):)623 4060 y(def)g(process\(self,)f(req\):)802 4151 y(dispatch.AsJonPy\(modules=\(MyHandler,\),)c(request=req\))444 4334 y(jon.fcgi.Server\({jon.fcgi.FCGI_RESPOND)o(ER:)g (Handler}\).run\(\))0 4671 y Ff(10.1.4)101 b(Other)27 b(Dispatch)i(Stuff)0 4855 y Fj(GetClientBinding)p Fl(\(\))208 4954 y Fn(More)19 b(sophisticated)g(scripts)i(may)e(w)o(ant)i(to)f(use) g(access)h(the)f(client)h(binding)d(object,)h(which)h(encapsulates)f (all)i(information)208 5054 y(about)i(the)i(client)f(in)m(v)n(oking)e (the)j(script.)38 b(This)24 b(function)f(returns)h Fl(None)g Fn(or)g(the)h(binding)e(information,)f(an)j(object)f(of)g(type)208 5154 y Fl(ClientBinding)p Fn(,)18 b(described)h(belo)n(w)-5 b(.)0 5300 y Fo(class)21 b Fj(ClientBinding)p Fl(\()p Fk(...)p Fl(\))208 5400 y Fn(This)f(object)g(contains)f(information)f (about)h(the)h(client.)25 b(It)c(is)g(created)e(internally)g(by)h Fl(ZSI)p Fn(.)p 0 5549 3901 4 v 0 5649 a Fi(10.1.)52 b(Dispatching)3139 b(39)p eop end %%Page: 40 46 TeXDict begin 40 45 bop 0 83 a Fj(GetAuth)p Fl(\(\))208 183 y Fn(This)15 b(returns)g(a)h(tuple)g(containing)e(information)f (about)i(the)g(client)h(identity)-5 b(.)22 b(The)16 b(\002rst)g (element)f(will)i(be)f(one)f(of)g(the)h(constants)208 282 y(from)i(the)h Fl(AUTH)g Fn(class)h(described)e(abo)o(v)o(e.)23 b(F)o(or)c(HTTP)g(or)g Fl(ZSI)g Fn(basic)g(authentication,)f(the)h(ne)o (xt)f(tw)o(o)i(elements)f(will)g(be)h(the)208 382 y(name)f(and)h(passw) o(ord)f(pro)o(vided)f(by)i(the)g(client.)0 529 y Fj(GetNS)p Fl(\(\))208 628 y Fn(Returns)g(the)g(namespace)f(URI)h(that)h(the)f (client)g(is)h(using,)f(or)g(an)g(empty)f(string.)25 b(This)20 b(can)g(be)g(useful)g(for)f(v)o(ersioning.)0 775 y Fj(GetRequest)p Fl(\(\))208 875 y Fn(Returns)h(the)g Fl(ParsedSoap)f Fn(object)g(of)h(the)g(incoming)f(request.)0 1022 y(The)h(follo)n(wing)e(attrib)n(ute)i(is)h(read-only:)0 1169 y Fj(environ)208 1268 y Fn(A)f(dictionary)f(of)h(the)g(en)m (vironment)d(v)n(ariables.)24 b(This)c(is)i(most)e(useful)f(when)h Fl(AsCGI\(\))f Fn(is)j(used.)0 1596 y Fg(10.2)121 b(The)34 b Fb(client)e Fg(module)i(\227)f(sending)i(SO)n(AP)d(messages)0 1829 y Fl(ZSI)23 b Fn(includes)e(a)i(module)f(to)g(connect)g(to)g(a)h (SO)m(AP)h(serv)o(er)e(o)o(v)o(er)f(HTTP)-9 b(,)22 b(send)g(requests,)h (and)f(parse)g(the)h(response.)31 b(It)23 b(is)g(b)n(uilt)g(on)0 1928 y(the)i(standard)g(Python)f Fl(httplib)h Fn(and)f Fl(Cookie)h Fn(modules.)40 b(It)25 b(must)h(be)f(e)o(xplicitly)g (imported,)f(as)j(in)e(`)p Fl(from)49 b(ZSI.client)0 2028 y(import)g(AUTH,Binding)p Fn('.)0 2313 y Ff(10.2.1)p 383 2313 30 4 v 136 w(Binding)0 2512 y Fo(class)21 b Fj(_Binding)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2612 y Fn(This)19 b(class)h(encapsulates)e(a)h (connection)e(to)j(a)f(serv)o(er)m(,)f(kno)n(wn)f(as)j(a)g Fk(binding)p Fn(.)j(A)c(single)g(binding)e(may)i(be)g(used)g(for)f (multiple)208 2711 y(RPC)j(calls.)26 b(Between)20 b(calls,)h (modi\002ers)e(may)h(be)g(used)g(to)g(change)f(the)h(URL)h(being)e (posted)h(to,)g(etc.)208 2844 y(Cookies)i(are)h(also)g(supported;)f(if) i(a)f(response)f(comes)g(back)h(with)g(a)g Fl(Set-Cookie)f Fn(header)m(,)f(it)j(will)g(be)e(parsed)g(and)h(used)208 2944 y(in)d(subsequent)f(interactions.)208 3077 y(The)g(follo)n(wing)g (k)o(e)o(yw)o(ord)f(ar)o(guments)g(may)i(be)g(used:)257 3288 y Fo(K)n(eyw)o(ord)p 903 3318 4 100 v 865 w(Default)p 2253 3318 V 592 w(Description)p 208 3321 3808 4 v 257 3391 a Fl(auth)p 903 3620 4 299 v 824 w(\(AUTH.none,\))p 2253 3620 V 423 w Fn(A)28 b(tuple)f(with)h(authentication)d (information;)j(the)g(\002rst)2304 3490 y(v)n(alue)39 b(should)g(be)g(one)g(of)g(the)h(constants)f(from)f(the)2304 3590 y Fl(AUTH)20 b Fn(class.)257 3689 y Fl(nsdict)p 903 3819 4 200 v 973 w({})p 2253 3819 V 674 w Fn(Namespace)57 b(dictionary)f(to)i(send)f(in)h(the)f(SO)m(AP)2304 3789 y Fl(Envelope)257 3889 y(soapaction)p 903 3919 4 100 v 773 w('')p 2253 3919 V 674 w Fn(V)-9 b(alue)20 b(for)g(the)g Fl(SOAPAction)f Fn(HTTP)h(header)-5 b(.)257 3988 y Fl(readerclass)p 903 4118 4 200 v 673 w(None)p 2253 4118 V 624 w Fn(Class)23 b(used)e(to)g(create)g(DOM-creating)e(XML)i(readers;)2304 4088 y(see)g(the)f(description)f(in)h(the)h Fl(ParsedSoap)d Fn(class.)257 4188 y Fl(writerclass)p 903 4317 V 673 w(None)p 2253 4317 V 624 w Fn(ElementProxy)23 b(Class)j(used)f(to)g (create)f(XML)h(writers;)2304 4287 y(see)c(the)f(description)f(in)h (the)h Fl(SoapWriter)d Fn(class.)257 4387 y Fl(tracefile)p 903 4516 V 773 w(None)p 2253 4516 V 624 w Fn(An)33 b(object)f(with)g(a) h Fl(write)f Fn(method,)i(where)e(pack)o(et)2304 4486 y(traces)21 b(will)g(be)f(recorded.)257 4586 y Fl(transport)p 903 4616 4 100 v 248 w Fn(HTTPConnection/HTTPSConnection)p 2253 4616 V 94 w(transport)f(class)257 4686 y Fl(transdict)p 903 4716 V 831 w Fm(fg)p 2253 4716 V 682 w Fn(k)o(e)o(yw)o(ord)g(ar)o (guments)f(for)h(connection)f(initialization)257 4785 y Fl(url)p 903 4815 V 1122 w Fn(n/a)p 2253 4815 V 673 w(URL)j(to)f(post)h(to.)257 4885 y Fl(wsAddressURI)p 903 5015 4 200 v 633 w Fn(None)p 2253 5015 V 633 w(URI,)37 b(identi\002es)e(the)h(WS-Address)g(speci\002cation)f(to)2304 4985 y(use.)26 b(By)20 b(def)o(ault)g(it')-5 b(s)21 b(not)f(used.)257 5084 y Fl(sig_handler)p 903 5114 4 100 v 683 w Fn(None)p 2253 5114 V 633 w(XML)h(Signature)e(handler)m(,)f(must)i(sign)g(and)g (v)o(erify)-5 b(.)208 5212 y(If)15 b(using)g(SSL,)h(the)f Fl(cert_file)g Fn(and)g Fl(key_file)f Fn(k)o(e)o(yw)o(ord)g(parameters) g(may)h(be)g(passed)h(to)f(the)h(transport')-5 b(s)14 b(constructor)208 5312 y(via)20 b(the)g Fl(transdict)p Fn(.)k(F)o(or)c(details)g(about)f(HTTPSConnection)g(see)h(the)h (documentation)c(for)i(the)i Fl(httplib)e Fn(module.)p 0 5549 3901 4 v 0 5649 a Fi(40)2399 b(Chapter)23 b(10.)52 b(Dispatching)24 b(and)g(In)n(v)n(oking)p eop end %%Page: 41 47 TeXDict begin 41 46 bop 0 83 a Fn(Once)28 b(a)g Fl(_Binding)g Fn(object)f(has)h(been)g(created,)h(the)f(follo)n(wing)e(modi\002ers)i (are)g(a)n(v)n(ailable.)48 b(All)29 b(of)f(them)f(return)g(the)h (binding)0 183 y(object,)19 b(so)i(that)f(multiple)g(modi\002ers)f(can) h(be)g(chained)f(together)-5 b(.)0 330 y Fj(AddHeader)p Fl(\()p Fk(header)c(,)17 b(value)p Fl(\))208 429 y Fn(Output)i(the)h (speci\002ed)g Fl(header)g Fn(and)f Fl(value)h Fn(with)h(the)f(HTTP)g (headers.)0 576 y Fj(SetAuth)p Fl(\()p Fk(style)o(,)f(name)o(,)h (passwor)m(d)r Fl(\))208 676 y Fn(The)c Fl(style)g Fn(should)f(be)i (one)f(of)g(the)h(constants)f(from)f(the)i Fl(AUTH)f Fn(class)h(described)f(abo)o(v)o(e.)22 b(The)16 b(remaining)f (parameters)g(will)208 775 y(v)n(ary)k(depending)e(on)j(the)g Fl(style)p Fn(.)25 b(Currently)19 b(only)g(basic)i(authentication)d (data)i(of)g(name)f(and)h(passw)o(ord)f(are)i(supported.)0 922 y Fj(SetNS)p Fl(\()p Fk(uri)p Fl(\))208 1022 y Fn(Set)f(the)h(def)o (ault)e(namespace)g(for)h(the)g(request)f(to)i(the)f(speci\002ed)g Fl(uri)p Fn(.)0 1169 y Fj(SetURL)p Fl(\()p Fk(url)p Fl(\))208 1268 y Fn(Set)g(the)h(URL)f(where)g(the)g(post)g(is)h(made)f(to)g Fl(url)p Fn(.)0 1415 y Fj(ResetHeaders)p Fl(\(\))208 1515 y Fn(Remo)o(v)o(e)f(an)o(y)g(headers)g(that)i(were)f(added)f(by)g Fl(AddHeader\(\))p Fn(.)0 1662 y(The)h(follo)n(wing)e(attrib)n(ute)i (may)g(also)g(be)h(modi\002ed:)0 1808 y Fj(trace)208 1908 y Fn(If)e(this)h(attrib)n(ute)f(is)h(not)f Fl(None)p Fn(,)g(it)h(should)f(be)g(an)g(object)g(with)h(a)f Fl(write)g Fn(method,)f(where)h(pack)o(et)g(traces)g(will)i(be)e(recorded.)0 2055 y(Once)j(the)f(necessary)g(parameters)g(ha)n(v)o(e)g(been)g (speci\002ed)h(\(at)f(a)i(minimum,)d(the)i(URL)g(must)g(ha)n(v)o(e)f (been)g(gi)n(v)o(en)g(in)h(the)f(constructor)0 2155 y(are)f(through)e Fl(SetURL)p Fn(\),)h(in)m(v)n(ocations)g(can)h(be)g(made.)0 2301 y Fj(RPC)p Fl(\()p Fk(url,)g(opname)o(,)e(pyobj,)h(r)m (eplytype=None)p Fc([)p Fk(,)g(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2401 y Fn(This)24 b(is)h(the)g(highest-le)n(v)o(el)d (in)m(v)n(ocation)h(method.)36 b(It)24 b(calls)h Fl(Send\(\))f Fn(to)h(send)f Fl(pyobj)g Fn(to)g(the)h(speci\002ed)f Fl(url)g Fn(to)h(perform)208 2501 y(the)20 b Fl(opname)f Fn(operation,)f(and)i(calls)h Fl(Receive\(\))e Fn(e)o(xpecting)f(to)j (get)f(a)h(reply)e(of)h(the)g(speci\002ed)g Fl(replytype)p Fn(.)208 2634 y(This)28 b(method)e(will)j(raise)f(a)h Fl(TypeError)d Fn(if)j(the)f(response)f(does)g(not)h(appear)f(to)h(be)g (a)g(SO)m(AP)h(message,)g(or)f(if)g(is)h(v)n(alid)208 2733 y(SO)m(AP)21 b(b)n(ut)f(contains)f(a)i(f)o(ault.)0 2880 y Fj(Send)p Fl(\()p Fk(url,)e(opname)o(,)g(pyboj)p Fc([)p Fk(,)g(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 2980 y Fn(This)21 b(sends)g(the)h(speci\002ed)f Fl(pyobj)g Fn(to)g(the)g(speci\002ed)g Fl(url)p Fn(,)h(in)m(v)n(oking)d(the)i Fl(opname)g Fn(method.)27 b(The)21 b Fl(url)g Fn(can)g(be)g Fl(None)g Fn(if)208 3079 y(it)f(w)o(as)h(speci\002ed)f(in)g(the)g Fl(Binding)f Fn(constructor)f(or)i(if)g Fl(SetURL)f Fn(has)i(been)e (called.)25 b(See)20 b(belo)n(w)f(for)h(a)g(shortcut)f(v)o(ersion)g(of) 208 3179 y(this)h(method.)208 3312 y(The)f(follo)n(wing)g(k)o(e)o(yw)o (ord)f(ar)o(guments)g(may)i(be)g(used:)257 3523 y Fo(K)n(eyw)o(ord)p 1254 3553 4 100 v 1080 w(Default)p 2331 3553 V 456 w(Description)p 208 3556 3886 4 v 257 3626 a Fl(auth_header)p 1254 3755 4 200 v 888 w(None)p 2331 3755 V 488 w Fn(String)e(\(containing)f (presumably)g(serialized)h(XML\))h(to)2383 3725 y(output)g(as)i(an)f (authentication)e(header)-5 b(.)257 3825 y(SO)m(AP)21 b Fl(Envelope)f(nsdict)p 1254 3954 V 537 w({})p 2331 3954 V 539 w Fn(Namespace)57 b(dictionary)f(to)h(send)h(in)f(the)h(SO)m (AP)2383 3924 y Fl(Envelope)257 4024 y(requesttypecode)p 1254 4054 4 100 v 737 w Fn(n/a)p 2331 4054 V 537 w(T)-7 b(ypecode)18 b(specifying)h(ho)n(w)h(to)g(serialize)g(the)h(data.)257 4124 y Fl(soapaction)p 1254 4154 V 548 w Fn(Obtained)e(from)g(the)i Fl(Binding)p 2331 4154 V 98 w Fn(V)-9 b(alue)20 b(for)f(the)i Fl(SOAPAction)d Fn(HTTP)j(header)-5 b(.)0 4266 y(Methods)19 b(are)h(a)n(v)n(ailable)g(to)h(determine)d(the)i(type)g(of)g(response)f (that)i(came)f(back:)0 4413 y Fj(IsSOAP)p Fl(\(\))208 4512 y Fn(Returns)g(true)h(if)g(the)g(message)g(appears)f(to)h(be)g(a)g (SO)m(AP)h(message.)27 b(\(Some)20 b(serv)o(ers)g(return)g(an)h(HTML)f (page)h(under)e(certain)208 4612 y(error)g(conditions.\))0 4759 y Fj(IsAFault)p Fl(\(\))208 4858 y Fn(Returns)h(true)f(if)i(the)f (message)g(is)h(a)g(SO)m(AP)g(f)o(ault.)0 5005 y(Ha)n(ving)h (determined)e(the)j(type)f(of)g(the)g(message)h(\(or)m(,)f(more)f(lik)o (ely)-5 b(,)22 b(assuming)g(it)h(w)o(as)h(good)d(and)h(catching)f(an)h (e)o(xception)f(if)h(not\),)0 5105 y(the)17 b(follo)n(wing)e(methods)h (are)h(a)n(v)n(ailable)f(to)h(actually)f(parse)h(the)f(data.)24 b(The)o(y)16 b(will)h(continue)f(to)h(return)e(the)i(same)g(v)n(alue)f (until)h(another)0 5205 y(message)j(is)h(sent.)0 5351 y Fj(ReceiveRaw)p Fl(\(\))p 0 5549 3901 4 v 0 5649 a Fi(10.2.)52 b(The)23 b Fl(client)f Fi(module)j(\227)e(sending)h(SO)n (AP)g(messages)1737 b(41)p eop end %%Page: 42 48 TeXDict begin 42 47 bop 208 83 a Fn(Returns)20 b(the)g(unparsed)e (message)i(body)-5 b(.)0 230 y Fj(ReceiveSoap)p Fl(\(\))208 330 y Fn(Returns)24 b(a)i Fl(ParsedSOAP)d Fn(object)i(containing)e(the) i(parsed)f(message.)39 b(Raises)26 b(a)f Fl(TypeError)f Fn(if)h(the)g(message)g(w)o(asn')o(t)208 429 y(SO)m(AP)-9 b(.)0 576 y Fj(ReceiveFault)p Fl(\(\))208 676 y Fn(Returns)28 b(a)g Fl(Fault)g Fn(object)g(containing)f(the)h(SO)m(AP)h(f)o(ault)f (message.)49 b(Raises)30 b(a)f Fl(TypeError)e Fn(if)h(the)h(message)f (did)g(not)208 775 y(contain)19 b(a)h(f)o(ault.)0 922 y Fj(Receive)p Fl(\()p Fk(r)m(eplytype=None)p Fl(\))208 1022 y Fn(P)o(arses)29 b(a)g(SO)m(AP)h(message.)50 b(The)28 b Fl(replytype)g Fn(speci\002es)h(ho)n(w)f(to)h(parse)g(the)g(data.)50 b(If)29 b(it)g(s)h Fl(None)p Fn(,)g(dynamic)e(parsing)208 1121 y(will)c(be)g(used,)g(usually)f(resulting)f(in)i(a)g(Python)f (list.)36 b(If)24 b Fl(replytype)e Fn(is)j(a)f(Python)e(class,)k(then)d (the)h(class')-5 b(s)24 b Fl(typecode)208 1221 y Fn(attrib)n(ute)19 b(will)i(be)f(used,)g(otherwise)g Fl(replytype)f Fn(is)i(tak)o(en)f(to) g(be)g(the)g(typecode)f(to)h(use)h(for)e(parsing)g(the)h(data.)0 1368 y(Once)f(a)g(reply)g(has)g(been)f(parsed)h(\(or)f(its)i(type)f(e)o (xamined\),)e(the)i(follo)n(wing)f(read-only)e(attrib)n(utes)j(are)g(a) n(v)n(ailable.)25 b(Their)18 b(v)n(alues)h(will)0 1468 y(remain)g(unchanged)f(until)i(another)e(reply)i(is)h(parsed.)0 1614 y Fj(reply_code)208 1714 y Fn(The)e(HTTP)i(reply)e(code,)g(a)i (number)-5 b(.)0 1861 y Fj(reply_headers)208 1961 y Fn(The)19 b(HTTP)i(headers,)e(as)i(a)f Fl(mimetools)f Fn(object.)0 2107 y Fj(reply_msg)208 2207 y Fn(A)h(te)o(xt)g(string)g(containing)e (the)j(HTTP)f(reply)f(te)o(xt.)0 2492 y Ff(10.2.2)101 b(Binding)0 2695 y Fn(If)24 b(an)h(attrib)n(ute)f(is)h(fetched)e(other) h(than)g(one)g(of)g(those)g(described)g(in)g Fl(_Binding)p Fn(,)h(it)g(is)g(tak)o(en)f(to)h(be)f(the)h Fl(opname)e Fn(of)i(a)f(remote)0 2794 y(procedure,)k(and)f(a)i(callable)f(object)g (is)h(returned.)47 b(This)29 b(object)f(dynamically)e(parses)i(its)h (ar)o(guments,)f(recei)n(v)o(es)g(the)g(reply)-5 b(,)29 b(and)0 2894 y(parses)20 b(that.)0 3041 y Fo(class)h Fj(Binding)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m(ds)12 b Fc(])p Fl(\))208 3141 y Fn(F)o(or)19 b(other)h(k)o(e)o(yw)o(ord)e(ar) o(guments)g(see)j Fl(_Binding)p Fn(.)719 3256 y Fo(K)n(eyw)o(ord)p 1315 3286 4 100 v 321 w(Default)p 1677 3286 V 99 w(Description)p 669 3289 2771 4 v 719 3359 a Fl(typesmodule)p 1315 3389 4 100 v 129 w(None)p 1677 3389 V 131 w Fn(See)f(e)o(xplanation)e(in)i (Dispatching)0 3500 y Fj(opname)p Fl(\()p Fk(*ar)m(gs)p Fl(\))208 3599 y Fn(Using)g(this)g(shortcut)g(requires)f(that)h(the)g Fk(url)h Fn(attrib)n(ute)f(is)h(set,)g(either)e(throught)g(the)h (constructor)e(or)i Fl(SetURL\(\))p Fn(.)0 3884 y Ff(10.2.3)101 b(NamedP)l(ar)o(amBinding)0 4087 y Fn(If)24 b(an)h(attrib)n(ute)f(is)h (fetched)e(other)h(than)g(one)g(of)g(those)g(described)g(in)g Fl(_Binding)p Fn(,)h(it)g(is)g(tak)o(en)f(to)h(be)f(the)h Fl(opname)e Fn(of)i(a)f(remote)0 4187 y(procedure,)k(and)f(a)i (callable)f(object)g(is)h(returned.)47 b(This)29 b(object)f (dynamically)e(parses)i(its)h(ar)o(guments,)f(recei)n(v)o(es)g(the)g (reply)-5 b(,)29 b(and)0 4286 y(parses)20 b(that.)0 4433 y Fo(class)h Fj(NamedParamBinding)p Fl(\()p Fc([)p Fk(**k)o(e)n(ywor)m (ds)12 b Fc(])p Fl(\))208 4533 y Fn(F)o(or)19 b(other)h(k)o(e)o(yw)o (ord)e(ar)o(guments)g(see)j Fl(_Binding)p Fn(.)719 4648 y Fo(K)n(eyw)o(ord)p 1315 4678 V 321 w(Default)p 1677 4678 V 99 w(Description)p 669 4681 2771 4 v 719 4751 a Fl(typesmodule)p 1315 4781 4 100 v 129 w(None)p 1677 4781 V 131 w Fn(See)f(e)o(xplanation)e(in)i(Dispatching)0 4893 y Fj(opname)p Fl(\()p Fk(**kwar)m(gs)p Fl(\))208 4993 y Fn(Using)g(this)g(shortcut)g(requires)f(that)h(the)g Fk(url)h Fn(attrib)n(ute)f(is)h(set,)g(either)e(throught)g(the)h (constructor)e(or)i Fl(SetURL\(\))p Fn(.)p 0 5549 3901 4 v 0 5649 a Fi(42)2399 b(Chapter)23 b(10.)52 b(Dispatching)24 b(and)g(In)n(v)n(oking)p eop end %%Page: 43 49 TeXDict begin 43 48 bop 0 83 3901 9 v 3503 230 a Fi(CHAPTER)3422 427 y Fh(ELEVEN)p 0 515 V 2778 978 a Ft(Bib)l(liog)n(r)n(aph)-6 b(y)p 0 5549 3901 4 v 3808 5649 a Fi(43)p eop end %%Page: 44 50 TeXDict begin 44 49 bop 0 5549 3901 4 v 0 5649 a Fi(44)p eop end %%Page: 45 51 TeXDict begin 45 50 bop 2362 794 a Ft(BIBLIOGRAPHY)42 1605 y Fn([1])40 b(This)20 b(is)h(the)g(\002rst)f(item)h(in)f(the)g (Bibliography)-5 b(.)42 1772 y([2])40 b(This)20 b(is)h(the)g(second)e (item)h(in)h(the)f(Bibliography)-5 b(.)p 0 5549 3901 4 v 3808 5649 a Fi(45)p eop end %%Page: 46 52 TeXDict begin 46 51 bop 0 5549 3901 4 v 0 5649 a Fi(46)p eop end %%Page: 47 53 TeXDict begin 47 52 bop 0 83 3901 9 v 3480 230 a Fi(APPENDIX)3814 427 y Fh(A)p 0 515 V 2402 978 a Ft(CGI)57 b(Scr)s(ipt)h(Arr)n(a)-6 b(y)0 1506 y Fg(A.1)120 b(Intro)0 1739 y Fn(This)19 b(is)h(an)e(e)o (xample)g(of)g(a)h(simple)g(web)g(service)f(CGI)h(Script.)25 b(The)18 b(service)h(returns)e(and)i(e)o(xpects)f(SO)m(AP)h(Arrays)g (\(p)o(ython)d Fl(list)p Fn(\).)0 1839 y(A)21 b(sample)f(soap)g(trace)g (is)h(pro)o(vided)c(belo)n(w)-5 b(.)24 b(In)c(this)h(e)o(xample)e(the)h (CGI)h(script)f(is)h(dispatched)e(as)i(a)f Fk(rpc)h Fn(service.)0 2124 y Ff(A.1.1)100 b(r)s(pc)28 b(wr)o(apper)0 2327 y Fn(The)f(wrapper)e(element)h(of)h(the)g(request)f(is)i(the)f(dispatch)g (k)o(e)o(y)f(to)h(the)g(callback)f(function,)h(the)g(child)f(elements)h (are)g(passes)g(as)h(a)0 2426 y Fl(list)e Fn(or)f Fl(dict)h Fn(of)g(v)n(alues)f(to)h(the)g(callback)f(function.)40 b(The)26 b(callback)f(function)f(is)j(e)o(xpected)d(to)i(return)f(a)h Fl(list)g Fn(or)f Fl(dict)h Fn(of)0 2526 y(v)n(alues,)20 b(the)g(response)f(wrapper)g(is)i(by)f(def)o(ault)f(set)i(to)f(the)h (request)e(wrapper)g(name)g(appended)f Fk(Response)p Fn(.)0 2853 y Fg(A.2)120 b(CGI)34 b(Scr)r(ipt)0 3178 y Fe(#!/usr/local/bin/python2.4)0 3269 y(#)45 b(SOAP)f(Array)0 3451 y(def)g(hello\(\):)179 3543 y(return)g(["Hello,)g(world"])0 3725 y(def)g(echo\()404 3738 y(*)449 3725 y(args\):)179 3817 y(return)g(args)0 3999 y(def)g(sum\()359 4012 y(*)404 3999 y(args\):)179 4091 y(sum)h(=)f(0)179 4182 y(for)h(i)f(in)h(args:)f (sum)g(+=)h(i)179 4273 y(return)f([sum])0 4456 y(def)g(average\()539 4469 y(*)584 4456 y(args\):)179 4547 y(return)g([sum\()718 4560 y(*)763 4547 y(args\))f(/)i(len\(args\)])0 4730 y(from)f(ZSI)g(import)g(dispatch)0 4821 y(dispatch.AsCGI\(rpc=True\))p 0 5549 3901 4 v 3808 5649 a Fi(47)p eop end %%Page: 48 54 TeXDict begin 48 53 bop 0 86 a Fg(A.3)120 b(client)33 b(test)h(scr)r(ipt)0 410 y Fe(#!/usr/bin/env)42 b(python)0 502 y(#)j(client.py)0 593 y(import)f(sys)0 684 y(from)g(ZSI.client)f (import)h(Binding)0 776 y(b)h(=)f (Binding\(url='http://127.0.0.1/cgi-bin/sim)o(ple',)38 b(tracefile=sys.stdout\))0 867 y(print)44 b(b.hello\(\))0 958 y(try:)179 1050 y(print)g(b.hello\(1\))0 1141 y(except)g (Exception,)f(ex:)179 1232 y(print)h("Fault:)g(",)g(ex)0 1415 y(print)g(b.echo\("whatever",)e("hi",)i(1,)g(2\))0 1506 y(print)g(b.sum\()539 1519 y(*)584 1506 y([2)674 1519 y(*)719 1506 y(i)f(for)h(i)h(in)f(range\(5\)]\))0 1598 y(print)g(b.average\()719 1611 y(*)764 1598 y([2)854 1611 y(*)899 1598 y(i)e(for)j(i)f(in)h(range\(5\)]\))0 2046 y Fg(A.4)120 b(SO)n(AP)32 b(T)-14 b(r)o(ace)0 2296 y Ff(A.4.1)100 b(hello)0 2590 y Fe($)45 b(./client.py)0 2681 y(Hello:)89 b(_________________________________)39 b(Wed)44 b(Oct)89 b(4)45 b(17:36:33)f(2006)g(REQUEST:)0 2773 y()0 3321 y()0 3412 y()0 3503 y()0 3595 y()0 3686 y()0 3869 y(_________________________________)39 b(Wed)45 b(Oct)89 b(4)44 b(17:36:34)g(2006)g(RESPONSE:)0 3960 y(200)0 4143 y() 0 4599 y()0 4691 y()0 4782 y()0 4873 y(Hello,)e (world
)0 4965 y()0 5056 y()0 5147 y()0 5239 y([u'Hello,)i(world'])p 0 5549 3901 4 v 0 5649 a Fi(48)2712 b(Appendix)24 b(A.)47 b(CGI)22 b(Scr)q(ipt)i(Arr)o(a)n(y)p eop end %%Page: 49 55 TeXDict begin 49 54 bop 0 83 a Ff(A.4.2)100 b(hello)29 b(f)m(ault)0 377 y Fe(_________________________________)39 b(Wed)45 b(Oct)89 b(4)44 b(17:36:34)g(2006)g(REQUEST:)0 469 y()0 1017 y()0 1108 y()0 1199 y()0 1290 y(1
)0 1382 y()0 1473 y()0 1564 y()0 1656 y(_________________________________)c(Wed)45 b(Oct)89 b(4)44 b(17:36:35)g(2006)g(RESPONSE:)0 1747 y(500)0 1930 y() 0 2386 y()0 2478 y()0 2569 y()0 2660 y (SOAP-ENV:Server)0 2752 y (Processing)f(Failure)0 2843 y()0 2934 y()0 3026 y (exceptions:TypeError)e(hello\(\))44 b(takes)g(no)h (arguments)e(\(1)h(given\))0 3117 y (build/bdist.darwin-8.8.0-Pow)o(er_Mac)o(intosh)o(/egg/Z)o (SI/dis)o(patch.)o(py:86:)o(_Dispa)o(tch)0 3208 y()0 3300 y()0 3391 y ()0 3482 y()0 3574 y ()0 3756 y(Fault:)89 b(Processing)43 b(Failure)0 3848 y(exceptions:TypeError)0 3939 y(hello\(\))h(takes)g (no)g(arguments)f(\(1)i(given\))0 4030 y([trace:)f (build/bdist.darwin-8.8.0-Power_Macint)o(osh/eg)o(g/ZSI/)o(dispat)o (ch.py:)o(86:_Di)o(spatch)o(])p 0 5549 3901 4 v 0 5649 a Fi(A.4.)52 b(SO)n(AP)24 b(T)-10 b(r)o(ace)3155 b(49)p eop end %%Page: 50 56 TeXDict begin 50 55 bop 0 83 a Ff(A.4.3)100 b(echo)0 377 y Fe(_________________________________)39 b(Wed)45 b(Oct)89 b(4)44 b(17:36:35)g(2006)g(REQUEST:)0 469 y ()0 1017 y()0 1108 y()0 1199 y()0 1290 y(whatever
)0 1382 y(hi
)0 1473 y(1
)0 1564 y(2
)0 1656 y()0 1747 y()0 1838 y() 0 1930 y(_________________________________)c(Wed)45 b(Oct)89 b(4)44 b(17:36:36)g(2006)g(RESPONSE:)0 2021 y(200)0 2204 y() 0 2660 y()0 2752 y()0 2843 y()0 2934 y(whatever
)0 3026 y(hi)0 3117 y(1)0 3208 y(2)0 3300 y()0 3391 y()0 3482 y()0 3665 y([u'whatever',)g(u'hi',)g(1,)i(2])p 0 5549 3901 4 v 0 5649 a Fi(50)2712 b(Appendix)24 b(A.)47 b(CGI)22 b(Scr)q(ipt)i(Arr)o(a)n(y)p eop end %%Page: 51 57 TeXDict begin 51 56 bop 0 83 a Ff(A.4.4)100 b(sum)0 377 y Fe(_________________________________)39 b(Wed)45 b(Oct)89 b(4)44 b(17:36:36)g(2006)g(REQUEST:)0 469 y()0 1017 y()0 1108 y()0 1199 y()0 1290 y(0)0 1382 y(2)0 1473 y(4)0 1564 y(6)0 1656 y(8)0 1747 y()0 1838 y()0 1930 y()0 2021 y(_________________________________)c(Wed)45 b(Oct)89 b(4)44 b(17:36:37)g(2006)g(RESPONSE:)0 2112 y(200)0 2295 y() 0 2752 y()0 2843 y()0 2934 y()0 3026 y(20)0 3117 y()0 3208 y()0 3300 y()0 3391 y([20])p 0 5549 3901 4 v 0 5649 a Fi(A.4.)52 b(SO)n(AP)24 b(T)-10 b(r)o(ace)3155 b(51)p eop end %%Page: 52 58 TeXDict begin 52 57 bop 0 83 a Ff(A.4.5)100 b(a)n(v)n(er)o(age)0 377 y Fe(_________________________________)39 b(Wed)45 b(Oct)89 b(4)44 b(17:36:37)g(2006)g(REQUEST:)0 469 y ()0 1017 y()0 1108 y()0 1199 y()0 1290 y(0)0 1382 y(2)0 1473 y(4)0 1564 y(6)0 1656 y(`8)0 1747 y()0 1838 y()0 1930 y ()0 2021 y(_________________________________)c(Wed) 45 b(Oct)89 b(4)44 b(17:36:38)g(2006)g(RESPONSE:)0 2112 y(200)0 2295 y() 0 2752 y()0 2843 y()0 2934 y()0 3026 y(4)0 3117 y()0 3208 y()0 3300 y()0 3391 y([4])p 0 5549 3901 4 v 0 5649 a Fi(52)2712 b(Appendix)24 b(A.)47 b(CGI)22 b(Scr)q(ipt)i(Arr)o(a)n(y)p eop end %%Page: 53 59 TeXDict begin 53 58 bop 0 83 3901 9 v 3480 230 a Fi(APPENDIX)3814 427 y Fh(B)p 0 515 V 2344 978 a Ft(CGI)58 b(Scr)s(ipt)f(Str)s(uct)0 1506 y Fg(B)n(.1)120 b(Intro)0 1739 y Fn(This)19 b(is)g(an)g(e)o (xample)e(of)h(a)h(simple)f(web)h(service)f(CGI)h(Script.)24 b(The)18 b(service)g(returns)g(and)g(e)o(xpects)g(SO)m(AP)h(Structs)g (\(p)o(ython)d Fl(dict)p Fn(\).)0 1839 y(A)21 b(sample)f(soap)g(trace)g (is)h(pro)o(vided)c(belo)n(w)-5 b(.)24 b(In)c(this)h(e)o(xample)e(the)h (CGI)h(script)f(is)h(dispatched)e(as)i(a)f Fk(rpc)h Fn(service.)0 2124 y Ff(B)n(.1.1)100 b(r)s(pc)28 b(wr)o(apper)0 2327 y Fn(The)f(wrapper)e(element)h(of)h(the)g(request)f(is)i(the)f (dispatch)g(k)o(e)o(y)f(to)h(the)g(callback)f(function,)h(the)g(child)f (elements)h(are)g(passes)g(as)h(a)0 2426 y Fl(list)e Fn(or)f Fl(dict)h Fn(of)g(v)n(alues)f(to)h(the)g(callback)f(function.) 40 b(The)26 b(callback)f(function)f(is)j(e)o(xpected)d(to)i(return)f(a) h Fl(list)g Fn(or)f Fl(dict)h Fn(of)0 2526 y(v)n(alues,)20 b(the)g(response)f(wrapper)g(is)i(by)f(def)o(ault)f(set)i(to)f(the)h (request)e(wrapper)g(name)g(appended)f Fk(Response)p Fn(.)0 2853 y Fg(B)n(.2)120 b(CGI)33 b(Scr)r(ipt)0 3178 y Fe(#!/usr/local/bin/python2.4)0 3269 y(#)45 b(SOAP)f(Struct)0 3451 y(def)g(hello\(\):)179 3543 y(return)g({"value":"Hello,)e(world"}) 0 3725 y(def)i(echo\()404 3738 y(**)494 3725 y(kw\):)179 3817 y(return)g(kw)0 3999 y(def)g(sum\()359 4012 y(**)449 3999 y(kw\):)179 4091 y(sum)h(=)f(0)179 4182 y(for)h(i)f(in)h (kw.values\(\):)e(sum)h(+=)g(i)0 4273 y(return)g({"value":sum})0 4456 y(def)g(average\()539 4469 y(**)629 4456 y(kw\):)0 4547 y(d)h(=)f(sum\()359 4560 y(**)449 4547 y(kw\))179 4639 y(return)g(d["value"])f(=)i(d["value"]/len\(kw\))0 4821 y(from)f(ZSI)g(import)g(dispatch)0 4913 y (dispatch.AsCGI\(rpc=True\))p 0 5549 3901 4 v 3808 5649 a Fi(53)p eop end %%Page: 54 60 TeXDict begin 54 59 bop 0 86 a Fg(B)n(.3)120 b(client)33 b(test)h(scr)r(ipt)0 502 y Fe(#!/usr/bin/env)42 b(python)0 593 y(import)i(sys,time)0 684 y(from)g(ZSI.client)f(import)h (NamedParamBinding)e(as)j(NPBinding)0 867 y(b)g(=)f (NPBinding\(url='http://127.0.0.1/cgi-bin/s)o(oapstr)o(uct',)38 b(tracefile=sys.stdout\))0 958 y(print)44 b("Hello:)g(",)g(b.hello\(\)) 0 1050 y(print)g("Echo:)g(",)g(b.echo\(name="josh",)e(year=2006,)h (pi=3.14,)h(time=time.gmtime\(\)\))0 1141 y(print)g("Sum:)g(",)g (b.sum\(one=1,)f(two=2,)h(three=3\))0 1232 y(print)g("Average:)f(",)i (b.average\(one=100,)d(two=200,)h(three=300,)g(four=400\))0 1773 y Fg(B)n(.4)120 b(SO)n(AP)32 b(T)-14 b(r)o(ace)0 2022 y Ff(B)n(.4.1)100 b(hello)p 0 5549 3901 4 v 0 5649 a Fi(54)2691 b(Appendix)24 b(B)n(.)47 b(CGI)22 b(Scr)q(ipt)i(Str)q(uct) p eop end %%Page: 55 61 TeXDict begin 55 60 bop 0 83 3901 9 v 3480 230 a Fi(APPENDIX)3814 427 y Fh(C)p 0 515 V 1182 978 a Ft(Complete)58 b(Lo)m(w)f(Le)-6 b(v)h(el)56 b(Example)0 1506 y Fg(C)l(.1)121 b(Intro)0 1739 y Fn(This)20 b(is)h(a)g(complete)e(e)o(xample)g(of)h(using)g(the)g (lo)n(w)g(le)n(v)o(el)g(soap)g(utilities)h(in)f Fl(ZSI)g Fn(to)h(implement)d(a)j(web)f(service.)0 2067 y Fg(C)l(.2)121 b(code)0 2316 y Ff(C)m(.2.1)100 b(httpser)s(v)n(er)28 b(scr)q(ipt)0 2519 y Fn(Minimal)20 b(http)g(serv)o(er)f(e)o(xample,)g (opens)g(up)h(a)g(ne)n(w)g(process)g(to)g(do)g(the)g(SO)m(AP)i (processing.)236 2757 y Fe(#!/usr/bin/env)43 b(python)236 2849 y(#)i(file:)f(httpserver.py)236 2940 y(import)g(os)236 3031 y(from)g(subprocess)g(import)f(Popen,)h(PIPE)236 3123 y(from)g(BaseHTTPServer)f(import)h(BaseHTTPRequestHandler,)d (HTTPServer)236 3305 y(class)j (RequestHandler\(BaseHTTPRequestHandler\):)416 3396 y(def)g (do_POST\(self\):)595 3488 y(length)g(=)g (int\(self.headers['content-length']\))595 3579 y(xml_in)g(=)g (self.rfile.read\(length\))595 3670 y(p)h(=)f (Popen\(os.path.join\(os.path.curdir,)39 b('player.py'\),)1043 3762 y(shell=True,)k(stdin=PIPE,)g(stdout=PIPE\))595 3944 y(\(stdout,)g(stderr\))h(=)h(p.communicate\(xml_in\))595 4036 y(code)f(=)h(200)595 4127 y(if)f(stdout.find\('Fault'\))e(>=)i(0:) h(code)f(=)h(500)595 4218 y(self.send_response\(code\))595 4310 y(self.send_header\('Content-type',)39 b('text/xml;)k (charset="utf-8"'\))595 4401 y(self.send_header\('Content-Length',)c (str\(len\(stdout\)\)\))595 4492 y(self.end_headers\(\))595 4584 y(self.wfile.write\(stdout\))595 4675 y(self.wfile.flush\(\))236 4858 y(if)45 b(__name__)e(==)i('__main__':)416 4949 y(server)e(=)i (HTTPServer\(\('localhost',)c(8080\),)j(RequestHandler\))416 5040 y(server.serve_forever\(\))p 0 5549 3901 4 v 3808 5649 a Fi(55)p eop end %%Page: 56 62 TeXDict begin 56 61 bop 0 83 a Ff(C)m(.2.2)100 b(typecode)29 b(module)0 377 y Fe(#)45 b(file:)f(typecode.py)0 469 y(#)h(CHECK)f(PYTHONPATH:)f(Must)h(be)g(able)g(to)h(import)0 560 y(class)f(Player:)179 651 y(def)h(__init__\(self,)1031 664 y(*)1076 651 y(args\):)359 743 y(if)f(not)g(len\(args\):)g(return) 359 834 y(self.Name)f(=)i(args[0])359 925 y(self.Scores)e(=)h(args[1:]) 0 1017 y(Player.typecode)e(=)j(TC.Struct\(Player,)d([)1435 1108 y(TC.String\('Name'\),)1435 1199 y(TC.Array\('Integer',)f (TC.Integer\(\),)i('Scores',)g(undeclared=True\),)1435 1290 y(],)h('GetAverage'\))0 1382 y(class)g(Average:)179 1473 y(def)h(__init__\(self,)d(average=None\):)359 1564 y(self.average)g(=)j(average)0 1656 y(Average.typecode)d(=)j (TC.Struct\(Average,)d([)1435 1747 y(TC.Integer\('average'\),)1435 1838 y(],)i('GetAverageResponse'\))p 0 5549 3901 4 v 0 5649 a Fi(56)2220 b(Appendix)24 b(C)n(.)46 b(Complete)24 b(Lo)o(w)f(Le)n(v)n(el)g(Example)p eop end %%Page: 57 63 TeXDict begin 57 62 bop 0 83 a Ff(C)m(.2.3)100 b(pla)m(y)n(er)29 b(scr)q(ipt)0 377 y Fe(#!/usr/bin/env)42 b(python)0 469 y(#)j(file:)f(player.py)0 560 y(from)g(ZSI)g(import)717 573 y(*)0 651 y(import)g(sys)0 743 y(IN,)g(OUT)h(=)f(sys.stdin,)f (sys.stdout)0 834 y(try:)179 925 y(ps)i(=)f(ParsedSoap\(IN\))0 1017 y(except)g(ParseException,)e(e:)179 1108 y (OUT.write\(FaultFromZSIException\(e\).AsSOAP)o(\(\)\))179 1199 y(sys.exit\(1\))0 1290 y(except)i(Exception,)f(e:)179 1382 y(#)i(Faulted)f(while)g(processing;)f(we)h(assume)g(it's)g(in)h (the)f(header.)179 1473 y(OUT.write\(FaultFromException\(e,)c (1\).AsSOAP\(\)\))179 1564 y(sys.exit\(1\))0 1747 y(#)45 b(We)f(are)g(not)h(prepared)e(to)i(handle)f(any)g(actors)g(or)g (mustUnderstand)f(elements,)0 1838 y(#)i(so)f(we'll)g(arbitrarily)f (fault)h(back)g(with)g(the)h(first)f(one)g(we)h(found.)0 1930 y(a)g(=)f(ps.WhatActorsArePresent\(\))0 2021 y(if)g(len\(a\):)179 2112 y(OUT.write\(FaultFromActor\(a[0]\).AsSOAP\(\)\))179 2204 y(sys.exit\(1\))0 2295 y(mu)g(=)h(ps.WhatMustIUnderstand\(\))0 2386 y(if)f(len\(mu\):)179 2478 y(uri,)g(localname)g(=)g(mu[0])179 2569 y(OUT.write\(FaultFromNotUnderstood\(uri,)39 b (localname\).AsSOAP\(\)\))179 2660 y(sys.exit\(1\))0 2843 y(from)44 b(typecode)g(import)f(Player,)h(Average)0 2934 y(try:)179 3026 y(player)g(=)h(ps.Parse\(Player.typecode\))0 3117 y(except)f(EvaluateException,)e(e:)179 3208 y (OUT.write\(FaultFromZSIException\(e\).AsSOAP)o(\(\)\))179 3300 y(sys.exit\(1\))0 3482 y(try:)179 3574 y(total)i(=)h(0)179 3665 y(for)g(value)f(in)g(player.Scores:)f(total)h(=)g(total)g(+)h (value)179 3756 y(result)f(=)h(Average\(total)d(/)j (len\(player.Scores\)\))179 3848 y(sw)g(=)f(SoapWriter\(\))179 3939 y(sw.serialize\(result,)e(Average.typecode\))179 4030 y(sw.close\(\))179 4122 y(OUT.write\(str\(sw\)\))0 4213 y(except)i(Exception,)f(e:)179 4304 y (OUT.write\(FaultFromException\(e,)d(0,)k (sys.exc_info\(\)[2]\).AsSOAP\(\)\))179 4396 y(sys.exit\(1\))p 0 5549 3901 4 v 0 5649 a Fi(C)n(.2.)51 b(code)3427 b(57)p eop end %%Page: 58 64 TeXDict begin 58 63 bop 0 83 a Ff(C)m(.2.4)100 b(client)28 b(test)f(scr)q(ipt)0 377 y Fe(#!/usr/bin/env)42 b(python2.4)0 469 y(#file:)i(client.py)0 560 y(from)g(ZSI)g(import)717 573 y(*)0 651 y(from)g(ZSI.wstools.Namespaces)d(import)j(SCHEMA)0 743 y(from)g(typecode)g(import)f(Player,)h(Average)0 925 y(if)g(__name__)g(==)g('__main__':)179 1017 y(import)g(sys)179 1108 y(from)g(ZSI.client)g(import)f(Binding)179 1199 y(b)i(=)g(Binding\(url='http://localhost:8080',)38 b (tracefile=sys.stdout\))179 1290 y(pyobj)44 b(=)h(b.RPC\(None,)e(None,) h(Player\("Josh",10,20,30\),)d(replytype=Average\))179 1382 y(print)j(pyobj)179 1473 y(print)g(pyobj.__dict__)p 0 5549 3901 4 v 0 5649 a Fi(58)2220 b(Appendix)24 b(C)n(.)46 b(Complete)24 b(Lo)o(w)f(Le)n(v)n(el)g(Example)p eop end %%Page: 59 65 TeXDict begin 59 64 bop 0 88 a Fg(C)l(.3)121 b(SO)n(AP)32 b(T)-14 b(r)o(ace)0 338 y Ff(C)m(.3.1)100 b(GetA)l(v)n(er)o(age)0 632 y Fe($./client.py)0 723 y(_________________________________)39 b(Thu)45 b(Oct)89 b(5)44 b(14:57:39)g(2006)g(REQUEST:)0 814 y() 0 1271 y()0 1362 y()0 1454 y()0 1545 y(Josh) 0 1636 y()0 1728 y(10)0 1819 y(20)0 1910 y(30)0 2002 y()0 2093 y()0 2184 y()0 2276 y()0 2367 y(_________________________________) 39 b(Thu)45 b(Oct)89 b(5)44 b(14:57:39)g(2006)g(RESPONSE:)0 2458 y(200)0 2550 y(OK)0 2641 y(-------)0 2732 y(Server:)g (BaseHTTP/0.3)e(Python/2.5)0 2824 y(Date:)i(Thu,)g(05)h(Oct)f(2006)g (21:57:39)g(GMT)0 2915 y(Content-type:)f(text/xml;)g(charset="utf-8")0 3006 y(Content-Length:)f(431)0 3189 y() 0 3645 y()0 3737 y()0 3828 y()0 3919 y(20)0 4011 y()0 4102 y()0 4193 y()0 4376 y(<__main__.Average)g(instance)h(at) i(0x5f9760>)0 4467 y({'average':)e(20})0 4892 y Ff(C)m(.3.2)100 b(f)m(ault)0 5095 y Fn(Purposely)19 b(send)h(a)g(incorrect)f Fk(Nae)i Fn(element)e(for)h(the)g Fk(Name)p Fn(.)p 0 5549 3901 4 v 0 5649 a Fi(C)n(.3.)51 b(SO)n(AP)25 b(T)-10 b(r)o(ace)3152 b(59)p eop end %%Page: 60 66 TeXDict begin 60 65 bop 236 174 a Fe($./client.py)236 266 y(_________________________________)40 b(Thu)k(Oct)89 b(5)45 b(14:33:25)e(2006)h(REQUEST:)236 357 y() 236 814 y()236 905 y()236 996 y()236 1088 y(Josh)236 1179 y()236 1270 y(10)236 1362 y(20)236 1453 y(30)236 1544 y()236 1636 y()236 1727 y()236 1818 y()236 2001 y (_________________________________)c(Thu)k(Oct)89 b(5)45 b(14:33:26)e(2006)h(RESPONSE:)236 2092 y(500)236 2183 y(Internal)g(Server)g(Error)236 2366 y() 236 2823 y()236 2914 y()236 3005 y()236 3097 y(SOAP-ENV:Client)236 3188 y (Unparseable)f(message)236 3279 y(<ZSI:ParseFaultDetail)o(>)236 3371 y(<ZSI:string>Element)g("Name")j(missing)f(from)h (complexType</ZSI:string>)236 3462 y (<ZSI:trace>/SOAP-ENV:Envelope/SOAP)o(-ENV:B)o(ody/Ge)o(tAvera)o (ge<)o(/ZSI:t)o(race&g)o(t;)236 3553 y (</ZSI:ParseFaultDetail>)236 3645 y()236 3736 y()236 3827 y()236 3919 y(Traceback)g(\(most)g(recent)f (call)i(last\):)326 4010 y(File)f("./player_client.py",)d(line)k(25,)f (in)g(?)416 4101 y(pyobj)g(=)g(b.RPC\(None,)f(None,)h (Player\("Josh",10,20,30\),)d(replytype=Average\))326 4193 y(File)j("/private/var/www/htdocs/guide/client.p)o(y",)39 b(line)44 b(176,)g(in)h(RPC)326 4375 y(File)f ("/private/var/www/htdocs/guide/client.p)o(y",)39 b(line)44 b(420,)g(in)h(Receive)236 4558 y(ZSI.FaultException:)d(Unparseable)h (message)236 4649 y()p 0 5549 3901 4 v 0 5649 a Fi(60)2220 b(Appendix)24 b(C)n(.)46 b(Complete)24 b(Lo)o(w)f(Le)n(v)n(el)g(Example)p eop end %%Page: 61 67 TeXDict begin 61 66 bop 0 83 3901 9 v 3480 230 a Fi(APPENDIX)3814 427 y Fh(D)p 0 515 V 2453 978 a Ft(Pic)l(kler)57 b(e)-6 b(xample)0 1506 y Fg(D)e(.1)120 b(Intro)0 1739 y Fn(This)20 b(is)h(an)g(e)o(xample)d(of)i(a)h(stateful)f(mod)p 1211 1739 25 4 v 29 w(p)o(ython)e(web)i(service.)0 2067 y Fg(D)-8 b(.2)120 b(code)0 2316 y Ff(D)-7 b(.2.1)100 b(typecode)29 b(module)0 2519 y Fn(Module)19 b(containing)f(comple)o(x)h(type)g (typecode.)236 2757 y Fe(#)45 b(Complex)f(type)g(definition)236 2849 y(from)g(ZSI)h(import)954 2862 y(*)236 2940 y(class)f(Person:)326 3031 y(def)g(__init__\(self,)f(name=None,)g(age=0\):)416 3123 y(self.name)g(=)i(name)416 3214 y(self.age)e(=)i(age)236 3396 y(Person.typecode)e(=)h(TC.Struct\(Person,)1492 3488 y([TC.String\('name'\),)1536 3579 y (TC.InonNegativeInteger\('age'\)],)1492 3670 y (pname=\('urn:MyApp','Person'\)\))0 4094 y Ff(D)-7 b(.2.2)100 b(pic)n(kler)28 b(scr)q(ipt)0 4297 y Fn(Con\002gure)19 b(appache)g(to)h(use)g(this)h(script)f(with)h(mod)p 1531 4297 V 28 w(p)o(ython)e(PythonHandler)-5 b(.)p 0 5549 3901 4 v 3808 5649 a Fi(61)p eop end %%Page: 62 68 TeXDict begin 62 67 bop 236 174 a Fe(#)45 b(pickler.py)236 266 y(import)f(pickle,)g(new)236 357 y(from)g(mod_python)g(import)f (apache)236 448 y(from)h(ZSI)h(import)f(dispatch)236 540 y(import)g(MyComplexTypes)236 722 y(#)h(my)f(web)h(service)e(that)i (returns)e(a)i(complex)e(structure)236 814 y(def)i (getPerson\(name=None\):)326 905 y(#fp)f(=)h (open\('/tmp/\045s.person.pickle'\045Person.na)o(me,)39 b('r'\))326 996 y(fp)44 b(=)h (open\('/tmp/\045s.person.pickle'\045name,)39 b('r'\))326 1088 y(#return)44 b(pickle.load\(fp\))326 1179 y(p)h(=)f (pickle.load\(fp\))326 1270 y(print)g("PERSON:)f(",)i(p)326 1362 y(print)f("typecode:)f(",)i(p.typecode)326 1453 y(return)f(p)236 1636 y(#)h(my)f(web)h(service)e(that)i(accepts)e(a)i (complex)e(structure)236 1727 y(def)i(savePerson\(Person\):)326 1818 y(print)f("PERSON:)f(",)i(Person)326 1910 y(fp)f(=)h (open\('/tmp/\045s.person.pickle'\045Person.nam)o(e,)39 b('w'\))326 2001 y(pickle.dump\(Person,)j(fp\))326 2092 y(fp.close\(\))326 2183 y(return)i({})236 2366 y(mod)h(=)f (__import__\('encodings.utf_8',)c(globals\(\),)j(locals\(\),)h(')2837 2379 y(*)2882 2366 y('\))236 2457 y(mod)h(=)f (__import__\('encodings.utf_16_be',)39 b(globals\(\),)44 b(locals\(\),)f(')3016 2470 y(*)3061 2457 y('\))236 2731 y(handles)h(=)h(new.module\('handles'\))236 2823 y(handles.getPerson)d (=)j(getPerson)236 2914 y(handles.savePerson)d(=)j(savePerson)236 3005 y(def)g(handler\(req\):)416 3097 y (dispatch.AsHandler\(modules=\(handles,)o(\),)39 b(request=req,)k (typesmodule=MyComplexTypes,)d(rpc=True\))416 3188 y(return)j (apache.OK)0 3703 y Ff(D)-7 b(.2.3)100 b(client:)34 b(in)n(v)n(ok)n(e) 28 b(sa)n(v)n(eP)-5 b(erson)0 3906 y Fi(scr)q(ipt)0 4200 y Fe(import)44 b(sys)0 4291 y(from)g(ZSI.client)f(import)h(Binding)0 4382 y(from)g(MyComplexTypes)f(import)g(Person)0 4565 y(b)i(=)f(Binding\(url='http://localhost/test3/pickl)o(er.py')o(,)39 b(tracefile=sys.stdout\))0 4656 y(person)44 b(=)g (Person\('christopher',)e(26\))0 4748 y(b.savePerson\(person\))p 0 5549 3901 4 v 0 5649 a Fi(62)2743 b(Appendix)24 b(D)-6 b(.)46 b(pic)n(kler)24 b(e)n(xample)p eop end %%Page: 63 69 TeXDict begin 63 68 bop 0 83 a Fi(SO)n(AP)24 b(T)-10 b(r)o(ace)0 377 y Fe(_________________________________)39 b(Wed)45 b(Oct)f(11)g(13:10:05)g(2006)g(REQUEST:)0 469 y()0 1017 y()0 1108 y()0 1199 y()0 1290 y(christopher) 0 1382 y(26)0 1473 y()0 1564 y()0 1656 y()0 1747 y()0 1930 y(_________________________________) 39 b(Wed)45 b(Oct)f(11)g(13:10:05)g(2006)g(RESPONSE:)0 2021 y(Server:)g(Apache/2.0.53-dev)e(\(Unix\))h(mod_ruby/1.2.4)g (Ruby/1.8.2\(2004-12-25\))0 2112 y(mod_python/3.1.4)f(Python/2.4.1)0 2204 y(Transfer-Encoding:)g(chunked)0 2295 y(Content-Type:)h(text/xml)0 2478 y() 0 2934 y()0 3026 y()0 3117 y()0 3208 y()0 3300 y()p 0 5549 3901 4 v 0 5649 a Fi(D)-6 b(.2.)52 b(code)3430 b(63)p eop end %%Page: 64 70 TeXDict begin 64 69 bop 0 83 a Ff(D)-7 b(.2.4)100 b(client:)34 b(in)n(v)n(ok)n(e)28 b(getP)-5 b(erson)30 b(3)e(diff)m(erent)h(w)o(a)m (ys)0 286 y Fi(scr)q(ipt)0 580 y Fe(import)44 b(sys)0 671 y(import)g(MyComplexTypes)0 763 y(from)g(ZSI.client)f(import)h (NamedParamBinding)e(as)j(NPBinding,)e(Binding)0 854 y(from)h(ZSI)g(import)g(TC)0 1037 y(kw)g(=)h ({'url':'http://localhost/test3/pickler.p)o(y',)39 b ('tracefile':sys.stdout})0 1128 y(b)45 b(=)f(NPBinding\()629 1141 y(**)719 1128 y(kw\))0 1219 y(rsp)g(=)h (b.getPerson\(name='christopher'\))0 1311 y(assert)f(type\(rsp\))f(is)i (dict,)f('expecting)f(a)h(dict')0 1402 y(assert)g (rsp['Person']['name'])d(==)k('christopher',)d('wrong)i(person')0 1585 y(b)h(=)f(NPBinding\(typesmodule=MyComplexTypes,)1883 1598 y(**)1973 1585 y(kw\))0 1676 y(rsp)g(=)h (b.getPerson\(name='christopher'\))0 1767 y(assert)f (isinstance\(rsp['Person'],)c(MyComplexTypes.Person\),)h(\()179 1859 y('expecting)i(instance)h(of)g(\045s')h (\045MyComplexTypes.Person\))0 2041 y(b)g(=)f (Binding\(typesmodule=MyComplexTypes,)1793 2054 y(**)1883 2041 y(kw\))0 2133 y(class)g(Name\(str\):)179 2224 y(typecode)g(=)g (TC.String\("name"\))0 2407 y(rsp)g(=)h (b.getPerson\(Name\('christopher'\)\))0 2498 y(assert)f (isinstance\(rsp['Person'],)c(MyComplexTypes.Person\),)h(\()179 2589 y('expecting)i(instance)h(of)g(\045s')h (\045MyComplexTypes.Person\))0 3002 y Fi(SO)n(AP)24 b(T)-10 b(r)o(ace)0 3205 y Fn(All)23 b(responses)f(are)g(e)o(xactly)f(the)i (same,)g(for)e(comparison)g(the)h(three)g(requests)g(are)g(presented)f (\002rst)i(and)f(only)g(the)g(last)h(response)f(is)0 3304 y(included.)p 0 5549 3901 4 v 0 5649 a Fi(64)2743 b(Appendix)24 b(D)-6 b(.)46 b(pic)n(kler)24 b(e)n(xample)p eop end %%Page: 65 71 TeXDict begin 65 70 bop 236 174 a Fe(_________________________________) 40 b(Wed)k(Oct)g(11)h(13:19:00)e(2006)h(REQUEST:)236 266 y()236 814 y() 236 905 y()236 996 y()236 1088 y(christopher)236 1179 y()236 1270 y()236 1362 y()236 1557 y(**)371 1544 y(OMIT)h(RESPONSE)998 1557 y(**)236 1727 y(_________________________________)c(Wed)k(Oct)g (11)h(13:19:00)e(2006)h(REQUEST:)236 1818 y()236 2366 y() 236 2457 y()236 2549 y()236 2640 y(christopher) 236 2731 y()236 2823 y()236 2914 y()236 3110 y(**)371 3097 y(OMIT)h(RESPONSE) 998 3110 y(**)236 3279 y(_________________________________)c(Wed)k(Oct) g(11)h(13:19:00)e(2006)h(REQUEST:)236 3371 y()236 3919 y() 236 4010 y()236 4101 y()236 4193 y(christopher)236 4284 y()236 4375 y()236 4467 y()236 4649 y(_________________________________)c (Wed)k(Oct)g(11)h(13:19:00)e(2006)h(RESPONSE:)236 4741 y(Server:)g(Apache/2.0.53-dev)e(\(Unix\))i(mod_ruby/1.2.4)e (Ruby/1.8.2\(2004-12-25\))236 4832 y(mod_python/3.1.4)g(Python/2.4.1) 236 4923 y(Transfer-Encoding:)g(chunked)236 5015 y(Content-Type:)h (text/xml)236 5197 y() 236 5654 y()236 5745 y()236 5836 y()236 5928 y()236 6019 y(christopher)236 6110 y(26)236 6202 y()236 6293 y()236 6384 y()236 6476 y()p 0 5549 3901 4 v 0 5649 a Fi(D)-6 b(.2.)52 b(code)3430 b(65)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF ZSI-2.1-a1/doc/modules.png0000644000175100017510000000112610437331051013436 0ustar zsizsi‰PNG  IHDR D¤ŠÆ`PLTEÿÿÿ™ÌÿÂõ†¹ì|¯âs¦ÙiœÏ_’ÅV‰¼L²Cv©:m 0c–&YŒPƒFy =p3f?0­bKGD{¼lêIDATxÚíÒÁrÄ àEÄ‘÷Ùb’ݦ›L{ÙcsøÎ7Âüæ|ðH¤EöXåæö¼˜hmõtâ…9’Zõ›̉gÖ0ì ÐM¶¬±IL»€â+n¹O»‚æüJ{®pëÀ™ŽsŽ^AòþÊâùðv7{ÝW˜uý}«fOñ5ÿþôá×Ì’aé šàœ9ǾªÌ}4Ò ZsEMB$G†XÕ¨c)”zé¢B ˆ¿æC3/OoÀ,;fìâ¨àK>úhF Ö ™¥Ø*eSü@Q_É ª¹ËÃLzTXtSoftwarexÚsÐPÖôÌMLOõMLÏLÎV0Ñ3Ò3R°´Ô70Õ70TH.Ê,.©tÈ­,.ÉLÖK-ÖK)-ÈÏ+ÑKÎÏôK€ôÝÄ^3zTXtSignaturexÚK²05K3K124H1266KJL3M5420¶4I´07µ0‹è.iê zTXtPagexÚ36ª06Ò6Ð6 šùGwÃIEND®B`‚ZSI-2.1-a1/doc/guide.html0000644000175100017510000017622510712455110013257 0ustar zsizsi ZSI: The Zolera Soap Infrastructure User's Guide

ZSI: The Zolera Soap Infrastructure
User's Guide

Joshua Boverhof,

Charles Moad

Release 2.1.0
November 01, 2007

COPYRIGHT

Copyright © 2001, Zolera Systems, Inc.
All Rights Reserved.

Copyright © 2002-2003, Rich Salz.
All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.

Copyright © (c) 2003, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

(1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such Enhancements or derivative works thereof, in binary and source code form.


1. Introduction

ZSI, the Zolera SOAP Infrastructure, is a Python package that provides an implementation of the SOAP specification, as described in SOAP 1.1 Specification.

This guide demonstrates how to use ZSI to develop Web Service applications from a Web Services Description Language document.

This document is primarily concerned with demonstrating and documenting how to use a Web Service by creating and accessing Python data for the purposes of sending and receiving SOAP messages. Typecodes are used to marshall Python datatypes into XML, which can be included in a SOAP Envelope. The typecodes are generated from information provided in the WSDL document, and generally describe SOAP and XML Schema data types. For a low-level treatment of typecodes, and a description of SOAP-based processing see the ZSI manual.

1.1 Acronyms and Terminology

SOAP
Usually refering to the content and format of a message ultimately sent and received by a Web Service, see SOAP 1.1 Specification WSDL
A document describing a Web Service's interface, see Web Services Description Language XMLSchema
Standard for modeling XML document structure. See XML Schema Specification schema document
a file containing a schema definition. schema (instance)
The set of rules or components contained in the assemblage of one or more schema documents. Element Declaration
A schema component that associates a name with a type definition. eg. <element name="age" type="xsd:int">, GED
Global Element Declaration, an element declared at the top-level of a schema. ComplexType
The parent of all type definitions that can specify attributes and children. SimpleType
A simple data type like a string or integer. The XML Schema Specification defines many built-in types. The XML Schema type library
The http://www.w3.org/2001/XMLSchema namespace, which contains definitions of various primitive types like string and integer, as well as a compound type complexType used to create aggregate types. Conventionally the xsd prefix is used to map to this schema. doc/literal
document style with literal encoding
rpc/enc
rpc style with specified encoding, not compatible with Basic Profile (WS-Interop)
rpc/literal
rpc style with literal encoding.

1.2 Overview

The ZSI Web Servicetools are for top-Down Web Servicedevelopment, using an existing WSDL Document to create client and server applications (see 1.3). A Web Service, in the context of this document, exposes a WSDL Document describing the service's interface, this document is typically available at a published URL (see Uniform Resource Locator). The WSDL document defines SOAP bindings for communicating with the service. These bindings will be used to exchange SOAP messages, the contents of these messages must adhere to the document structure specified by the schema. The schema is either included in the WSDL Document, imported by it, or represented by the available built-in types (such as xsd:int, xsd:string, etc).1.1

1.2.1 soap bindings

The two styles of SOAP bindings are rpc and document. The use of literal encoding is encouraged and the recommended way to develop new Web Service applications (see Basic Profile (WS-Interop)). The SOAP encoded support is maintained for use with older applications, and other SOAP toolkits restricted to rpc/encdevelopment. A doc/literalservice is typically described as an exchange of documents, while a rpc/encor rpc/literalservice is thought of in terms of remote procedure calls. Whether this distinction of purpose is meaningful or useful is debatable. ZSI supports all three types, but rpc/literaland doc/literalare the focus of ongoing development.

1.2.2 python tools

1.2.2.1 wsdl2py

The wsdl2py script generates python code representing the various components defined in a WSDL Document. Most of the remaining guide focuses on how to use this tool and understand its output.


1.3 Not Covered

  1. How to create a WSDL document
  2. How to write XML Schema
  3. Interoperability
  4. How to use Web Services without WSDL

1.4 References

  1. Web services development patterns http://www-128.ibm.com/developerworks/websphere/library/techarticles/0511_flurry/0511_flurry.html

2. wsdl2py basics

The wsdl2py script is used to generate all the code needed to access a Web Service through an exposed WSDL document, usually this description is available at a URL which is provided to the script.

wsdl2py will generate a client, types, and service module. From the the WSDL SOAP Bindings, the client and service modules are created. The types module contains typecodes for the schema defined by the WSDL.


2.1 Modules

2.1.1 client stub module

2.1.1.1 classes

The service item in the Web Services Description Language definition contains one or more port items.

2.1.1.1.1 locator

Defines a factory method for each port item, and stores the service's address. Use to grab a client(port) to the Web Service.

# Example Locator
class WhiteMesaSoapRpcLitTestSvcLocator:
    SoapTestPortTypeRpc_address = "http://www.whitemesa.net/test-rpc-lit"
    def getSoapTestPortTypeRpcAddress(self):
        return WhiteMesaSoapRpcLitTestSvcLocator.SoapTestPortTypeRpc_address
    def getSoapTestPortTypeRpc(self, url=None, **kw):
        return Soap11TestRpcLitBindingSOAP(url or WhiteMesaSoapRpcLitTestSvcLocator.SoapTestPortTypeRpc_address, **kw)
}

2.1.1.1.2 port

Each port item will be represented by a single class definition, grab a port through one of the locator's factory methods.

loc = WhiteMesaSoapRpcLitTestSvcLocator()
port = loc.getSoapTestPortTypeRpc(tracefile=sys.stdout)

2.1.1.1.3 message

classes that represent the SOAP and XML Schema data types. A Message instance is serialized as a XML instance. A Message passed as an argument to a port method is then serialized into a SOAP Envelope and transported to the Web Service, the client will then wait for an expected response, and finally the SOAP response is marshalled back into the Message returned to the user.

msg = echoBooleanRequest()
msg.InputBoolean = True
rsp = port.echoBoolean(msg)

2.1.2 types module

Defines typecodes for all components of all schema specified by the target WSDL Document (not including built-in types). Each schema component declared at the top-level, the immediate children of the schema tag, are global in scope and by importing the "types" module an application has access to the GEDs and global type definitions either directly or with the unique (namespace,name) combination thru convenience functions.

2.1.2.1 classes

2.1.2.1.1 Global Type Definition

class ns1:
    ..
    ..
    class HelpRequest_Def(ZSI.TCcompound.ComplexType, TypeDefinition):
        schema = "http://webservices.amazon.com/AWSECommerceService/2006-11-14"
        type = (schema, "HelpRequest")
        def __init__(self, pname, ofwhat=(), attributes=None, extend=False, restrict=False, **kw):
            ..

2.1.2.1.2 Global Element Declaration

class ns1:
    ..
    ..
    class Help_Dec(ZSI.TCcompound.ComplexType, ElementDeclaration):
        literal = "Help"
        schema = "http://webservices.amazon.com/AWSECommerceService/2006-11-14"
        def __init__(self, **kw):
            ..

2.1.2.2 helper functions

2.1.2.2.1 Global Type Definition

    klass = ZSI.schema.GTD(\
        "http://webservices.amazon.com/AWSECommerceService/2006-11-14", 
        "HelpRequest")
    typecode = klass("Help")

2.1.2.2.2 Global Element Declaration

    typecode = ZSI.schema.GED(\
        "http://webservices.amazon.com/AWSECommerceService/2006-11-14", 
        "Help")

Each module level class defintion represents a unique namespace, they're simply wrappers of individual namespaces. In the example above, the two inner classes of ns1 are the typecode representations of a global type definition HelpRequest_Def, and a global element declaration Help_Dec. In most cases a TypeCode instance represents either a global or local element declaration.

In the example GED returns a Help_Dec instance while GTD returns the class definition HelpRequest_Def. Why this asymmetry? The element name is serialized as the XML tag name, while the type definition describes the contents (children, text node).

In the generated code an element declaration either defines all its content in its contructor or it subclasses a global type definition, which is another generated class.

2.1.3 service module

skeleton class, normally subclassed and invoked by implementation code. The skeleton defines a callback method for each operation defined in the SOAP Binding. These methods marshal/unmarshall XML into python types.

2.1.3.1 example: DateService

2.1.3.1.1 server skeleton code

class simple_Date_Service(ServiceSOAPBinding):
    ..
    ..
    def soap_getCurrentDate(self, ps):
        self.request = ps.Parse(getCurrentDateRequest.typecode)
        return getCurrentDateResponse()

    soapAction['urn:DateService.wsdl#getCurrentDate'] = 'soap_getCurrentDate'
    root[(getCurrentDateRequest.typecode.nspname,getCurrentDateRequest.typecode.pname)] = 'soap_getCurrentDate'

2.1.3.1.2 server implementation code

DS = simple_Date_Service
class Service(DS):
    def soap_getCurrentDate(self, ps):
        response = DS.soap_getCurrentDate(self, ps)
        response.Today = today = response.new_today()
        self.request.Input
        dt = time.localtime(time.time())
        today.Year = dt[0]
        today.Month = dt[1]
        today.Day = dt[2]
        today.Hour = dt[3]
        today.Minute = dt[4]
        today.Second = dt[5]
        today.Weekday = dt[6]
        today.DayOfYear = dt[7]
        today.Dst = dt[8]
        return response

2.2 Generated TypeCodes

The generated inner typecode classes come in two flavors, as mentioned above. element declarations can be serialized into XML, generally type definitions cannot.2.1 Basically, the name attribute of an element declaration is serialized into an XML tag, but type definitions lack this information so they cannot be directly serialized into an XML instance.

Most element declarations declare a type attribute, this must reference a type definition. Considering the above scenario, a generated TypeCode class representing an element declaration will subclass the generated TypeCode class representing the type definition.

2.2.1 special handling of instance attributes

The attributes discussed below are common to all TypeCodes, for more information see the ZSI manual. I'm reintroducing them to point out certain conventions adhered to in the generated code, necessary for reliably dealing with WSDL and various messaging patterns and usages.

2.2.1.1 pyclass

All instances of generated TypeCode classes will have a pyclass attribute, instances of the pyclass can be created to store the data representing an element declaration.2.2. The pyclass itself has a typecode attribute, which is a reference to the TypeCode instance describing the data, thus making pyclass instances self-describing.

When parsing an XML instance the data will be marshalled into an instance of the class specified in the typecode's pyclass attribute.

    typecode = ZSI.schema.GED(\
        "http://webservices.amazon.com/AWSECommerceService/2006-11-14", 
        "Help")
    msg = typecode.pyclass()

2.2.1.2 aname

The aname is a TypeCode instance attribute, its value is a string representing the attribute name used to reference data representing an element declartion. The set of XMLSchema element names is NCName, this is a superset of ordinary identifiers in python. Keywords like return and class are legal NCNames.

Namespaces in XML

From Namespaces in XML
	NCName	 ::=	(Letter | '_') (NCNameChar)*
	NCNameChar	 ::=	Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender

From Python Reference Manual (2.3 Identifiers and keywords)
	identifier	::=	(letter|"_") (letter | digit | "_")*

Default set of anames
	ANAME	::=	("_") (letter | digit | "_")*

2.2.1.2.1 transform

NCName into an ANAME
  1. preprend "_"
  2. character not in set (letter | digit | "_") change to "_"

2.2.1.3 Attribute Declarations: attrs_aname

The attrs_aname is a TypeCode instance attribute, its value is a string representing the attribute name used to reference a dictionary, containing data representing attribute declarations. The keys of this dictionary are the (namespace,name) tuples, the value of each key represents the value of the attribute.

2.2.1.4 Mixed Text Content: mixed_aname

Its value represents the attribute name used to store text content that some ComplexType definitions allow.


2.2.2 Metaclass Magic: pyclass_type

The -complexType flag provides many conveniences to the programmer. This option is tested and reliable, and highly recommended by the authors.

When -complexType is enabled the __metaclass__ attribute will be set on all generated pyclasses. The metaclass will introspect the typecode attribute of pyclass, and create a set of helper methods for each element and attribute declared in the complexType definition. This option simply adds wrappers for dealing with content, it doesn't modify the generation scheme.

Use help in a python interpreter to view all the properties and methods of these typecodes. Looking at the generated code is not very helpful.

Getters/Setters
A getter and setter function is defined for each element of a complex type. The functions are named get_element_ANAME and set_element_ANAME respectively. In this example, variable msg has functions named get_element__Options and set_element__Options. In addition to elements, getters and setters are generated for the attributes of a complex type. For attributes, just the name of the attribute is used in determining the method names, so get_attribute_NAME and set_attribute_NAME are created.

Factory Methods
If an element of a complex type is a complex type itself, then a conveniece factory method is created to get an instance of that types holder class. The factory method is named, newANAME.

Properties
Python class properties are created for each element of the complex type. They are initialized with the corresponding getter and setter for that element. To avoid name collisions the properties are named, PNAME, where the first letter of the type's pname attribute is capitalized. In our running example, msg has class property, Options, which calls functions get_element__Options and set_element__Options under the hood.

2.2.2.1 example

2.2.2.1.1 schema

Taken from the WolframSearch WSDL.

<xsd:complexType name='WolframSearchOptions'>
  <xsd:sequence>
    <xsd:element name='Query' minOccurs='0' maxOccurs='1' type='xsd:string'/>
    <xsd:element name='Limit' minOccurs='0' maxOccurs='1' type='xsd:int'/>
  </xsd:sequence>
  <xsd:attribute name='timeout' type='xsd:double' />
</xsd:complexType>
<xsd:element name='WolframSearch'>
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name='Options' minOccurs='0' maxOccurs='1' type='ns1:WolframSearchOptions'/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

2.2.2.1.2 help

(WolframSearchRequest)
Help on WolframSearch_Holder in module WolframSearchService_types object:

class WolframSearch_Holder(__builtin__.object)
 |  Methods defined here:
 |  
 |  __init__(self)
 |  
 |  get_element_Options(self)
 |  
 |  new_Options(self)
 |      returns a mutable type
 |  
 |  set_element_Options(self, value)
 |  
 |  ----------------------------------------------------------------------
 |  Properties defined here:
 |  
 |  Options
 |      property for element (None,Options), minOccurs="0" maxOccurs="1" nillable="False"
 |  
 |      <get> = get_element_Options(self)
 |  
 |      <set> = set_element_Options(self, value)
 |

2.2.2.1.3 request

from WolframSearchService_client import *
msg = WolframSearchRequest()
# get an instance of a Options holder class using factory method
msg.Options = opts = msg.new_Options()

# assign values using the properties or methods
opts.Query = 'Newton'
opts.set_element_Limit(10)

# don't forget the attribute
opts.set_attribute_timeout(1.0)

2.2.2.1.4 invoke

port = WolframSearchServiceLocator().getWolframSearchmyPortType()
rsp = port.WolframSearch(msg)
print 'SearchTime:', rsp.Result.SearchTime

2.2.2.1.5 XML

XML approximation of our WolframSearchRequest instance.
 <WolframSearch>
   <Options timeout="1.0" xsi:type="tns:WolframSearchOptions">
     <Query xsi:type="xsd:string">Newton</Query>
     <Limit xsi:type="xsd:double">10.0</Limit>
   </Options>
 </WolframSearch>

3. Security

3.1 HTTP Basic Authorization

auth=dict(style=ZSI.AUTH.httpbasic, user=USERNAME, password=PASSWORD)

3.2 HTTP Digest Authorization

auth=dict(style=ZSI.AUTH.httpdigest, user=USERNAME„ password=PASSWORD)

3.3 Message Security

4. SOAP Headers

5. Type Substitution

A. wsdl2py scrpt

A.1 Command Line Flags

A.1.1 General Flags

-h, --help
Display the help message and available command line flags that can be passed to wsdl2py.
-f FILE, --file=FILE
Create bindings for the WSDL which is located at the local file path.
-u URL, --url=URL
Create bindings for the remote WSDL which is located at the provided URL.
-x, --schema
Just process a schema (xsd) file and generate the types mapping file.
-d, --debug
Output verbose debugging messages during code generation.
-o OUTPUT_DIR, --output-dir=OUTPUT_DIR
Write generated files to OUTPUT_DIR.

A.1.2 Typecode Extensions (Stable)

-b, --complexType (more in section )
Generate convenience functions for complexTypes. This includes getters, setters, factory methods, and properties. ** Do NOT use with -simple-naming **

A.1.3 Development Extensions (Unstable)

-a, --address
WS-Addressing support. The WS-Addressing schema must be included in the corresponding WSDL.
-w, --twisted
Generate a twisted.web client. Dependencies: python>=2.4, Twisted>=2.0.0, TwistedWeb>=0.5.0

A.1.4 Customizations (Unstable)

-e, --extended
Do extended code generation.
-z ANAME, --aname=ANAME
Use a custom function, ANAME, for attribute name creation.
-t TYPES, --types=TYPES
Dump the generated type mappings to a file named, ``TYPES.py''.
-s, --simple-naming
Simplify the generated naming.
-c CLIENTCLASSSUFFIX, --clientClassSuffix=CLIENTCLASSSUFFIX
The suffic to use for service client class. (default ``SOAP'')
-m PYCLASSMAPMODULE, --pyclassMapModule=PYCLASSMAPMODULE
Use the existing existing type mapping file to determine the ``pyclass'' objects to be used. The module should contain an attribute, ``mapping'', which is a dictionary of form, schemaTypeName: (moduleName.py, className).

B. Example: WolframSearch

B.1 Code Generation from WSDL and XML Schema

This section covers wsdl2py, the second way ZSI provides to access WSDL services. Given the path to a WSDL service, two files are generated, a 'service' file and a 'types' file, that one can then use to access the service. As an example, we will use the search service provided by Wolfram Research Inc.©, http://webservices.wolfram.com/wolframsearch/, which provides a service for searching the popular MathWorld site, http://mathworld.wolfram.com/, among others.

wsdl2py --complexType http://webservices.wolfram.com/services/SearchServices/WolframSearch2.wsdl

Run the above command to generate the service and type files. wsdl2py uses the name attribute of the wsdl:service element to name the resulting files. In this example, the service name is WolframSearchService. Therefore the files WolframSearchService_services.py and WolframSearchService_services_types.py should be generated.

The 'service' file contains locator, portType, and message classes. A locator instance is used to get an instance of a portType class, which is a remote proxy object. Message instances are sent and received through the methods of the portType instance.

The 'types' file contains class representations of the definitions and declarations defined by all schema instances imported by the WSDL definition. XML Schema attributes, wildcards, and derived types are not fully handled.

B.1.1 Example Use of Generated Code

The following shows how to call a proxy method for WolframSearch. It assumes wsdl2py has already been run as shown in the section above. The example will be explained in greater detail below.

# import the generated class stubs
from WolframSearchService_client import *

# get a port proxy instance
loc = WolframSearchServiceLocator()
port = loc.getWolframSearchmyPortType()

# create a new request
req = WolframSearchRequest()
req.Options = req.new_Options()
req.Options.Query = 'newton'

# call the remote method
resp = port.WolframSearch(req)

# print results
print 'Search Time:', resp.Result.SearchTime
print 'Total Matches:', resp.Result.TotalMatches
for hit in resp.Result.Matches.Item:
    print '--', hit.Title

Now each section of the code above will be explained.

from WolframSearchService_client import *

We are primarily interested in the service locator that is imported. The binding proxy and classes for all the messages are additionally imported. Look at the WolframSearchService_services.py file for more information.

loc = WolframSearchServiceLocator()
port = loc.getWolframSearchmyPortType()

Using an instance of the locator, we fetch an instance of the port proxy which is used for invoking the remote methods provided by the service. In this case the default location specified in the wsdlsoap:address element is used. You can optionally pass a url to the port getter method to specify an alternate location to be used. The portType - name attribute is used to determine the method name to fetch a port proxy instance. In this example, the port name is WolframSearchmyPortType, hence the method of the locator for fetching the proxy is getWolframSearchmyPortType.

The first step in calling WolframSearch is to create a request object corresponding to the input message of the method. In this case, the name of the message is WolframSearchRequest. A class representing this message was imported from the service module.

req = WolframSearchRequest()
req.Options = req.new_Options()
req.Options.Query = 'newton'

Once a request object is created we need to populate the instance with the information we want to use in our request. This is where the -complexType option we passed to wsdl2py will come in handy. This caused the creation of functions for getting and setting elements and attributes of the type, class properties for each element, and convenience functions for creating new instances of elements of complex types. This functionality is explained in detail in subsection A.1.2.

Once the request instance is populated, calling the remote service is easy. Using the port proxy we call the method we are interested in. An instance of the python class representing the return type is returned by this call. The resp object can be used to introspect the result of the remote call.

resp = port.WolframSearch(req)

Here we see that the response message, resp, represents type WolframSearchReturn. This object has one element, Result which contains the search results for our search of the keyword, newton.

print 'Search Time:', resp.Result.SearchTime
...

Refer to the wsdl for WolframSearchService for more details on the returned information.

About this document ...

ZSI: The Zolera Soap Infrastructure
User's Guide
, November 01, 2007, Release 2.1.0

This document was generated using the LaTeX2HTML translator.

LaTeX2HTML is Copyright © 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds, and Copyright © 1997, 1998, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The application of LaTeX2HTML to the Python documentation has been heavily tailored by Fred L. Drake, Jr. Original navigation icons were contributed by Christopher Petrilli.



Footnotes

... etc).1.1
The xsd prefix refers to namespace "http://www.w3.org/2001/XMLSchema"
... cannot.2.1
The pname can be set to None when a XML tag name is not needed (eg. attributes).
... declaration.2.2
Exceptions include the Union TypeCode, may need multiple pyclasses to make it work
ZSI-2.1-a1/doc/zsi.css0000644000175100017510000002306310712455106012607 0ustar zsizsi/* * The first part of this is the standard CSS generated by LaTeX2HTML, * with the "empty" declarations removed. */ /* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ .math { font-family: "Century Schoolbook", serif; } .math i { font-family: "Century Schoolbook", serif; font-weight: bold } .boldmath { font-family: "Century Schoolbook", serif; font-weight: bold } /* * Implement both fixed-size and relative sizes. * * I think these can be safely removed, as it doesn't appear that * LaTeX2HTML ever generates these, even though these are carried * over from the LaTeX2HTML stylesheet. */ small.xtiny { font-size : xx-small; } small.tiny { font-size : x-small; } small.scriptsize { font-size : smaller; } small.footnotesize { font-size : small; } big.xlarge { font-size : large; } big.xxlarge { font-size : x-large; } big.huge { font-size : larger; } big.xhuge { font-size : xx-large; } /* * Document-specific styles come next; * these are added for the Python documentation. * * Note that the size specifications for the H* elements are because * Netscape on Solaris otherwise doesn't get it right; they all end up * the normal text size. */ body { color: #000000; background-color: #ffffff; } a:link:active { color: #ff0000; } a:link:hover { background-color: #bbeeff; } a:visited:hover { background-color: #bbeeff; } a:visited { color: #551a8b; } a:link { color: #0000bb; } h1, h2, h3, h4, h5, h6 { font-family: avantgarde, sans-serif; font-weight: bold; } h1 { font-size: 180%; } h2 { font-size: 150%; } h3, h4 { font-size: 120%; } /* These are section titles used in navigation links, so make sure we * match the section header font here, even it not the weight. */ .sectref { font-family: avantgarde, sans-serif; } /* And the label before the titles in navigation: */ .navlabel { font-size: 85%; } /* LaTeX2HTML insists on inserting
elements into headers which * are marked with \label. This little bit of CSS magic ensures that * these elements don't cause spurious whitespace to be added. */ h1>br, h2>br, h3>br, h4>br, h5>br, h6>br { display: none; } code, tt { font-family: "lucida typewriter", lucidatypewriter, monospace; } var { font-family: times, serif; font-style: italic; font-weight: normal; } .Unix { font-variant: small-caps; } .typelabel { font-family: lucida, sans-serif; } .navigation td { background-color: #99ccff; font-weight: bold; font-family: avantgarde, sans-serif; font-size: 110%; } div.warning { background-color: #fffaf0; border: thin solid black; padding: 1em; margin-left: 2em; margin-right: 2em; } div.warning .label { font-family: sans-serif; font-size: 110%; margin-right: 0.5em; } div.note { background-color: #fffaf0; border: thin solid black; padding: 1em; margin-left: 2em; margin-right: 2em; } div.note .label { margin-right: 0.5em; font-family: sans-serif; } address { font-size: 80%; } .release-info { font-style: italic; font-size: 80%; } .titlegraphic { vertical-align: top; } .verbatim pre { color: #00008b; font-family: "lucida typewriter", lucidatypewriter, monospace; font-size: 90%; } .verbatim { margin-left: 2em; } .verbatim .footer { padding: 0.05in; font-size: 85%; background-color: #99ccff; margin-right: 0.5in; } .grammar { background-color: #99ccff; margin-right: 0.5in; padding: 0.05in; } .grammar-footer { padding: 0.05in; font-size: 85%; } .grammartoken { font-family: "lucida typewriter", lucidatypewriter, monospace; } .productions { background-color: #bbeeff; } .productions a:active { color: #ff0000; } .productions a:link:hover { background-color: #99ccff; } .productions a:visited:hover { background-color: #99ccff; } .productions a:visited { color: #551a8b; } .productions a:link { color: #0000bb; } .productions table { vertical-align: baseline; empty-cells: show; } .productions > table td, .productions > table th { padding: 2px; } .productions > table td:first-child, .productions > table td:last-child { font-family: "lucida typewriter", lucidatypewriter, monospace; } /* same as the second selector above, but expressed differently for Opera */ .productions > table td:first-child + td + td { font-family: "lucida typewriter", lucidatypewriter, monospace; vertical-align: baseline; } .productions > table td:first-child + td { padding-left: 1em; padding-right: 1em; } .productions > table tr { vertical-align: baseline; } .email { font-family: avantgarde, sans-serif; } .mailheader { font-family: avantgarde, sans-serif; } .mimetype { font-family: avantgarde, sans-serif; } .newsgroup { font-family: avantgarde, sans-serif; } .url { font-family: avantgarde, sans-serif; } .file { font-family: avantgarde, sans-serif; } .guilabel { font-family: avantgarde, sans-serif; } .realtable { border-collapse: collapse; border-color: black; border-style: solid; border-width: 0px 0px 2px 0px; empty-cells: show; margin-left: auto; margin-right: auto; padding-left: 0.4em; padding-right: 0.4em; } .realtable tbody { vertical-align: baseline; } .realtable tfoot { display: table-footer-group; } .realtable thead { background-color: #99ccff; border-width: 0px 0px 2px 1px; display: table-header-group; font-family: avantgarde, sans-serif; font-weight: bold; vertical-align: baseline; } .realtable thead :first-child { border-width: 0px 0px 2px 0px; } .realtable thead th { border-width: 0px 0px 2px 1px } .realtable td, .realtable th { border-color: black; border-style: solid; border-width: 0px 0px 1px 1px; padding-left: 0.4em; padding-right: 0.4em; } .realtable td:first-child, .realtable th:first-child { border-left-width: 0px; vertical-align: baseline; } .center { text-align: center; } .left { text-align: left; } .right { text-align: right; } .refcount-info { font-style: italic; } .refcount-info .value { font-weight: bold; color: #006600; } /* * Some decoration for the "See also:" blocks, in part inspired by some of * the styling on Lars Marius Garshol's XSA pages. * (The blue in the navigation bars is #99CCFF.) */ .seealso { background-color: #fffaf0; border: thin solid black; padding: 0pt 1em 4pt 1em; } .seealso > .heading { font-size: 110%; font-weight: bold; } /* * Class 'availability' is used for module availability statements at * the top of modules. */ .availability .platform { font-weight: bold; } /* * Additional styles for the distutils package. */ .du-command { font-family: monospace; } .du-option { font-family: avantgarde, sans-serif; } .du-filevar { font-family: avantgarde, sans-serif; font-style: italic; } .du-xxx:before { content: "** "; font-weight: bold; } .du-xxx:after { content: " **"; font-weight: bold; } /* * Some specialization for printed output. */ @media print { .online-navigation { display: none; } } ZSI-2.1-a1/doc/guide.pdf0000644000175100017510000053770710712455103013074 0ustar zsizsi%PDF-1.4 3 0 obj << /Length 381 /Filter /FlateDecode >> stream xÚ]‘MoÔ@ †ïó+æFFêÛ“ùℊ êJ Á†K«²Ýl·%%éÂßÇÉ„ ¡D‘gì×~^‡4ÊC:²¼¨ïO ×›ïŠÖµÍÇ9ýSÝÞ¡ÞKÙF!äœþ=k Î‰ôIÕ!ý=ôj«>¿t±2ÂFB@ÝÜé²Q¯?pÐ\CL‘tsÐ䨻¬Càåj[Ýl¯ßË1Uͱ+ÁÍÐw£!¬ÚrÞíS‰®Jbz%_ïŸÏcgîšÌ‰köÚr†”b^Úºñ•ñXM¥ÃÕùq¿Ô [ÔÉ×3›ó‚飨#ø…WÔ_º¾k§‹WiøWjYÜÔ²)K.…\Fo†éx^-\FhöU7‡ƒqX]lÎ'Ñ2A¦˜é»c[üõÝÊýqh÷ëì¬IJ½çe¥ õ í’à‹ùYýi&Ÿî´“UZ– ]”€ã‹$>,.!:ÌbBöG9’oãî?ô·ýÎ0V=<¬ i¥Þ7êãendstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 13 0 R >> endobj 1 0 obj << /Font << /F26 6 0 R /F27 9 0 R /F29 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 16 0 obj << /Length 3192 /Filter /FlateDecode >> stream xÚÍZKwë¶ÞçWxIc;$Ň˜¬d™¾f+K®(åæö± )Èb+‘*IÅq~}ç>$¦§‹,º"0 f`¾‘Öß}ÿ4¶o‚ûÀ³½›õîÆöÝ{{bº7¾eÞ›c|³Þþ͘-_¿­¢/ÏëÑ?ÖúþÉ:3îlsÌSî,ÿÞ³‡§§‘eŸeö¾¯qÚãÞ»ÞdrcÞM“å¦,Ïrzòî}/ðnî:|7-w`i˾wÜñøÆ$&Û4­ÛÑíšÆ_‹ƒ*nÇŸU­Ž•ŒDyzOÚܹ`¨k£ÖÖ}àº6ɘÌ·Bµ+i«J•¿Œ,×P[žlþØjƒãÍñ­V7Ý‹¹Éá·?ÞÂWU³ªÊŠ|t7¬âï^•êí“Ûïe’×j ]ÇØ•J!Ý1Чû¤Yã] K]ð@’ãÊ"å¤ÊJ¯R¼ÕI–gù»ð±¼T¼-<"½ÞkªbW GR*½À–§&UU¤YZòÀ¶HÏw½/U^'5™k{>ì‰i:Ëó ãšõ^Ɉm;qgAì¢o‘‰È¶UÉgg"²‘÷ÔEÊGVï‹sÍü¥ªê2KQ‘™åéá¼%¯\pûÆ!;f­â^»J©w—.ú&[dò¹¢}±ìÖÁžkÉ2ŽÅ6ÛµÔÙKèŸÎo‡¬Ú û6C¥ßF¶iœkÍ»ð}Q‚ A`TŠÂZ°X†ž…ø§½Dk ®oZ)ÂTð¤jb€ÙMâ§jyðû±/Ž<Œ¢ö»¿ cÛç‡ïî\æ`EŒíóªö"‡ûUz9žq* Œâ_²múOjÝR<+yc&:i<–öî"åE¥ ìÂPb"Ç0 Óªº‡²™'ì§“‚ãF«f2ž€Ïlov`ìÊirEã±wé’Ãäjû õVÔ{f—yî•¥@º´H×–¶ xÍ‘vû–6ó„][ m²fVçÓ©(k<#‘ާ¾9à×Këç£Í5âåÓúëÈ‚8ž®ˆäQÌC¯«‘cË\Ÿ?Eá#SñüOc͉=Œ±e|ÖÏËÍšG´ÈÕt±þÆ—Oü.¾1ÏŸ£Åã-ÓŸ_Wa,ë.W"ýåu…À2°¥Ñb6ß`/ó%’Óß&o™Â‹òŠÂ¸â¯œTˆÆX&|}aG%)€8Õ_äž­£å¢»žƒŽY¯dpä;:Èá—yô%\ÌÂfÕÇóÆÒš“ÉQ㨌–›˜©íÊ·BXE1bìÐíA'ùŠ0Š#ø‚‚‹PÇ>^9ØóiFÒ&ûs_ÃÔËÕRû‰D QÌ/»7â`®þšª^ð¼ÖÓ"ÇTŽžFgÌ÷4冇ßèèRO¿>À—'GÅãô0¡@-¯ÿ–ï¾8lUÉÃÕß:-˜o"òœ-S´É–Ÿ)x0*N6qAO›*?²Jf_æNì&xüE­ØCœ½@£JJòós%4J€ð‹b¹‰¹!,+©8å‡$%ÊE‚”6åƒÎ©Ì´Ð2«k%’30•Ùo:t%¿êjxáF$‰]×øß¡ŽçÁ u\Ö3…É5SÎlÏ24èñàâäÖø‚û÷OzÅ2Ô³uúk›<Ù:)«¬þì2ZÆ ¶`W@¦—ˆìz_ç÷=Μ÷Qª<yªüúA”`¤.Èלé㬷¢Lê¢ülà˜ã;~?r(÷9¿ýS¥èÿ‰É)+|K•ªì$DR¾ RbŽŸ³ƒ™†N:EC“CÅä]‰™/ &_@cso¶áœBÓ1ÛÂ\ûOt¹ 2fÄ%5Š å»˜‘øVª—øsÜ‘ÚÛßA0.×~«â\¦Bã<oYž”h2FØ"FòŽK‡€9(üa´=@DÄ‚°-M4t‚9|‚€•Êšp 2÷“w¤prË-ÑhW:÷ƒ±àZÛf(¿¥K5Œ&ë†n¾%‰¯ã ¸¯â¾üœÆ?ØN‹­\IÇsU3­TxÉr[îPç*wœëÛÓéÞ¿ Ä2`ºº¯C×dOÙzwÁ¾ŸÜV¦‡$;êkæÎ' }aË1üa_؃dhÂhLe_ ­T°©Û3…S ávpÁty ~ÇVs¾¸ç0Tõû€â/CMf瘗Î’Ûu±Ðšn;§‡W˜¤±4òÉS‚äcR«2£Ã#˜øÐ`K¤»Æ¥Ÿq?|Þ±Ä&°/T¦—q¯A4Ÿg~­ñœ‘wWŸwøþ…l[3öï_¸¸reàÊjçÊ…^çÊåRŠ’ûZrßaö©nï;îç|™4ª{dUÕ˜5°·¿:JrO¥T[ŽÉ'¿)þr‚-®M •o‘Ý2„ƒt€o›VpÂY¯otÇ£[^J.{”Ì! ­ê¢¼4Á€¥tÍ8N*å«R/”itB1”ò4|0Oà„ѱìKí@’®‡®!4Ž>|ãQJZ‘ÐAYHoŽD*eç‘Fº”] ‹†äÈÅœÛ8uÀ0†2´¨ÛÔ DAÝܹÀÆ’½6àû–¹ZôíuÑ7Œ´è³RZd0üî¯×bñAÌÜt;09o¬A€N ä7l4Ù[â0ºàYCräk 9ñ®¤ñÅEÃÇ{f`2à`DÚ¶ok¤MAÚXÝd¨âÛ=l Ýåh X€ò¿ø¿·í8BØ6ØhOzcghf8‡Ń%á•_3Yñì\ˆ¯¥þÂî¡û\£­‹À—pÜA¨ Ã×Úâªs/²€ÖFttd „FgV´q™´>³ÍJª(ÈÁƒßxó¯£õfrÿËrùó<´€X`?&xzgaü#“¨k9ÈÌ@)W@]è´-­:ˆÔ„£T;Äp€Æ|>M¬¬¬ÃÍÞ¼"Ö/W×EŽ.<ÆlŠi(õÈ}.)Aƒ?¾qbq)»Ç OüÅ껀¨k ƒå8<ƒ$ÇÁX…±Á#W¢‘O¥Ó«0¥LêÖ#P¢žÜV Àú¯QêdËé” syh­Î­8öõÀn—5ÇR~ûr{AƒÊ ý*ŸB«÷,Ü2 onEÂ?¥ˆù)âÍZî¡8Ò7[—#ÞÌž‡6£º/p>ÄWqæl‡+ߦgœó­Î€òBr¯·Cö>šyÆ ‡ªPtG’¦â*)ùÍÏ_0›³É ñQþ•dTtâã”Ôé¾éqŠÞËd«ªþB’áyÆN%õ¹lfíÎyÊI¦aârB€O> endobj 14 0 obj << /Font << /F32 19 0 R /F29 12 0 R /F14 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 25 0 obj << /Length 116 /Filter /FlateDecode >> stream xÚM± Â` „÷{ŠŒ:4&ñïo³tè&f+,BÁN¾~#(È 7ÜwJ’Q:µ…¥&ï+^'¡B„ÞµôÎ"¬îF+Jí~剮Я¦É}ó'ꇋUröšˆÇ稫šRÌãnYöS 86`©0endstream endobj 24 0 obj << /Type /Page /Contents 25 0 R /Resources 23 0 R /MediaBox [0 0 612 792] /Parent 13 0 R >> endobj 23 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 28 0 obj << /Length 1321 /Filter /FlateDecode >> stream xÚíšËrÛ6†÷z .É…PÜ/ÙÙŽÓ4ÛmÄ™t&“#Ñ6§º¸”Ç}úðf@C.ÜMGã…nß?Àÿœú<ýòŽÊˆr¤´"QzqÌT”D’aʤQºú_Ü\§—×é"ùš~˜]¦3aø#‘¢‘ )¢X´ÜÌ02<ÂHðêç¿:lÜÜÏíÀŒF ãøî•ìˆ$™ŒqüÛöP&DÇ»ÕãòPì¶Ç ',}ÍŽ‚ŽÑ!˜N«c5GÃj Så‘ ) «õ³É7ìÜ…«©q>¾b5,²ËÀŽÏ–%̈øy³Oæ¾É¶«úMš(ç妨îÖ»»çc¥n®6Ò—Ú_ŸQIA̸—³:Q2p¯N/ö…(*‡ ƒa™±šæ—vØ. S»…6n¹ùn­’—ß‹<¡"~ê H1¬=9˜i±ŸK!B"©‰§åd…×{áÆ4¾R1ð7iAô$c¹ð ³:¨¶k¬u½;Ôiçbg=Ö-_õ,&xG_YÀc-7¢Š(‚$åÚ×u2Èk%¬Acil÷9ÍXM¯ÃäÜîBõÛ³ÇÃý®,þÉB”bD #¾ÆPßp#ú(eÈP¥}…§¨Äµüe˜6ˆrÌ&YÆ…-ÓAµehÏ2o‹»|˜äްÖÒ>ô©¸Ý©'ñä’éfQ Q-è4³8ð°YZ¨6KÛž_åû}v—×L¶š!ˆþ#YdÛr#’hvïõD|ñšF‚ • {ìic[³ ·æ°÷‰·[óMÂ!¯4¹æ}ž­òr:9„ŠžøbÂG‡7"¦Û§=ID„¦ÏÀ܈ñé;`xú-P÷dõôÓDq[¶6¡óøm(ÁGjIÐS:Új¸E/kàê"*´„ ÁÈxuæ‚á5h;ÖY2WJû]ò~Y&LJ~³(2p!OL¨Yl¸1/Ów%3J©1H¨‰R.<˜J;¨ZŠªT#Tǻͦ{Èò±Ø6Îx·Îîúa— †R_]`MZnDY×ÖxÚN rZò4È¡°5I1áäɃ‘Óö–œ'sÍX|ù#Û<¬ó7 xÇŸ%âÝú¶Ì6‹<«_.ïû–шPI|e!Ë4܈².Œ<}tèA•xâ‘“ ‡Q UëR‡‘f±=¨#§9'°µú|[î6õ»Ï‹·žjþyÕ|³XÞç›ìx Dq¬ýyôW¯ãFæÀ Mÿ‹pè[À>k‡Â_ªªžû{öå+ŽV°zÀ Ì@÷d—•¡ÑfÆ¥n?¬g‹ÙGOõ_.tÞü7ëI¨L¥ˆ8ERëgÅEQ´zþá­p—endstream endobj 27 0 obj << /Type /Page /Contents 28 0 R /Resources 26 0 R /MediaBox [0 0 612 792] /Parent 13 0 R /Annots [ 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R ] >> endobj 29 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 528.5779 141.0106 535.5815] /Subtype /Link /A << /S /GoTo /D (page001) >> >> endobj 30 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 514.6053 224.896 523.5565] /Subtype /Link /A << /S /GoTo /D (page001) >> >> endobj 31 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 504.6676 151.7308 511.6014] /Subtype /Link /A << /S /GoTo /D (page002) >> >> endobj 32 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 492.7124 163.7359 499.6462] /Subtype /Link /A << /S /GoTo /D (page002) >> >> endobj 33 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 480.7572 157.1004 487.691] /Subtype /Link /A << /S /GoTo /D (page003) >> >> endobj 34 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 456.9216 146.998 465.843] /Subtype /Link /A << /S /GoTo /D (page005) >> >> endobj 38 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 446.8843 147.7157 453.818] /Subtype /Link /A << /S /GoTo /D (page005) >> >> endobj 39 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 432.9116 200.8562 441.8629] /Subtype /Link /A << /S /GoTo /D (page008) >> >> endobj 40 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 411.1234 122.3607 420.0149] /Subtype /Link /A << /S /GoTo /D (page013) >> >> endobj 41 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 401.0561 220.2131 407.9899] /Subtype /Link /A << /S /GoTo /D (page013) >> >> endobj 42 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 387.0835 224.0886 396.0347] /Subtype /Link /A << /S /GoTo /D (page013) >> >> endobj 43 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 375.1283 183.4014 384.0796] /Subtype /Link /A << /S /GoTo /D (page013) >> >> endobj 44 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 355.1831 151.0231 362.2316] /Subtype /Link /A << /S /GoTo /D (page015) >> >> endobj 45 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 331.4222 162.3303 340.3138] /Subtype /Link /A << /S /GoTo /D (page017) >> >> endobj 46 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 309.5044 145.7926 318.396] /Subtype /Link /A << /S /GoTo /D (page019) >> >> endobj 47 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 297.4197 199.1922 306.371] /Subtype /Link /A << /S /GoTo /D (page019) >> >> endobj 48 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 275.6315 198.1261 284.523] /Subtype /Link /A << /S /GoTo /D (page021) >> >> endobj 49 0 obj << /Type /Annot /Border [0 0 0] /Rect [86.944 265.5642 308.7408 272.498] /Subtype /Link /A << /S /GoTo /D (page021) >> >> endobj 26 0 obj << /Font << /F26 6 0 R /F32 19 0 R /F29 12 0 R /F36 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 62 0 obj << /Length 117 /Filter /FlateDecode >> stream xÚ3T0BCs#S=3 œËUÈk Âe àÅe gliaªPäèZZ)är™˜YÀ89\Á\\†Pctúu‘ r áÒw32S°Ô³4R!i ‹LŒô BR¢52Ë4cC¼¸\C¸a=endstream endobj 61 0 obj << /Type /Page /Contents 62 0 R /Resources 60 0 R /MediaBox [0 0 612 792] /Parent 13 0 R >> endobj 60 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 65 0 obj << /Length 2031 /Filter /FlateDecode >> stream xÚ­XYä¶~ï_¡·¨-^:äaãuÖXÇkOìñGÍ™VGGRïzþ}Š,R­kÆ $`šG±XÇWEƒþh² ¥1‰yʃ¢Þýg÷ÛïqpÜÅÁ÷»˜äyƒ/0‰‰È3Ô;‘d~Ríîv?í¨ã£hÊéï‡Ý7ïXä$OàçðˆœžgyÀ@P–‡ãoá·ÿxóñpûóþ÷Ã÷ß¼, ‚p‘0s€&DR|'IÌ,ùÿ¼5¤»ÛÃx5ܜȌÐ$þ?¨0åäU`‚¤YJ­ ¡Èr€<$IÓÌ õ¾ºöx)†²mœ"|¢xÄy†§"™‘J{è×»÷H †¸ÒҔ䜄–æf1–„ÃI›AþÚVºS¸x÷ãžËðÍGÜyß©'Çv8©Á-wížÊðsyÔ=î)w ¬Ï•®u3(«¥]kýy½%SÖEyǬ°gnŒºAä5Œ(%¹”èVen“q×]ù 8-›¥³),äiH0‘&ÆQàf>•Â}ºzt¤Ž¦äÖ¯| Í5W#h#6 %wsµ–‚æy6—ÐmNdéֲͱægd#ΘR8&`Ö„ a7'ëù\†Oð¤ 0mÝ6€5h·yj÷L†_p2´Hvé5.|Nv$00äŸ >tÕž¼332ˆŽ„QéÐûË>g¡~ÀÓwºû\zòpñå©ó¹*ѲNÌÇ®­Q6µ´µ ²˜D a+^CÃHMÉ×hXs}I›åzkQ{vÛT¡ƒ¸àîÎ)ÜŸ.jOãðÉüÓK¥òŒ$"¦Œ”¬¶áã©¢ Ù-zG\)Ýz ¿Ü½ý€#YМ3á|{*–Ì2œM¼³ñ Ðí']+wÁ£ºÆµ"KÃwFB &Ã* –¨š&æ-o×.ˆÁ>¶lÃïhÎç“æxuÎXŒ}Z›ôêDª÷F#Žñ`æ½Öî–“`AA­š‹ªˆ ËdÚòà<',çè#[siÇᛢ)@ÃçÚx?õI‡=eF;Ã<¬Ë¦­Ú§ç˜z>nƒÌîK<:ÆX-“|n»õô*$ÈGÝ¡ŠÉþZ aip@+SÅf`!è­Í&þ¸øÅÉ¥ÊR%Ùßׯ¹]s‚õ·[}xö|·2$%ÊØ*CýËRd„ÑLLQtê¢ZIèÒiž³€'1I¡ë|µÔÑ”|]‚×\g ¦ejÂ¥õkÛ4š@a¦ÐÕsÐ4M ÷Û®³#]4%\WÚ4AxAk ¥…a—fÓÆ‹ÐzãÂìZa¯ðG[¥ðøà)pYzÔ¨ýšG%TJwè/Æ”½o³Ý=šfDúæ¿ “q+|¿P³T¼êiOM©×Ž^ñ|I!'êÛeN‚VëÕnJH£v’Î¥^ûy¤[ ¼ég–'f = ‰Ü¥ð}7@«Î—¨¶s¹òo5:Û„5&Æw+ˆw[¾a$M¡´±L’8NÿÄ7Ž8šPoùfÁÓ©êüR˜„uë+âÍDkž11pà žl%Ú¶ Ê(ŠÖWiF¾èGh$®\…2ù[•Í$öÐüS¾ÚhJ£¢ƒÜ퀭d¹e\ÂÓKA“ cú²L_+{½¨ÕÝ¥ò!à¡S´õ¹m@Ç~&ýäí<¯¿ªïuýPa½™°sÆuÛé ÍEûmµ¹Uà¿øX-*Õhx9 ÒäzM¯Šá–û:#Р-J÷€B…˪5ŽÜÃãºeZͯ´rø‰l=d3Jx"¨Ë•÷LP=jænüÛ=cb’xÌï6—ÚÝ?úã_!·šá=KÓ›¤ %,ƒ@Áç»Û·[yË€ßU탪Ðâæ7:ºÏ/®ÉÃ_=%=")OC5,Ð3´gÓhš>YWsaâÙRt/ß¶æ³’9÷‡¼|Etœ¡ó_6³æ!3vµëXí½:^±ÂÂ~¥z|öjP|÷Ðê\oc[\œÊê7¿÷wö;ÙŸëâjoɸ¶ñŸ«P•Ÿ°ªÍ =tcŠò1kJ¸…3ôÁPØ'/§åç)H«”gYsh¬µPŒÄÑ„z](V<ÿ—BÁÍgb‘Й€ëB1’­D›ÁŽç‚d<™‹æ€á ïû²Àz¿¬†hÌ ø[v–‚ÄIÊÖ_yžI÷ÕÙv±þ«³l|už0Z7—\‘ÄY ¡”¹—‘ç¿M§äaendstream endobj 64 0 obj << /Type /Page /Contents 65 0 R /Resources 63 0 R /MediaBox [0 0 612 792] /Parent 13 0 R /Annots [ 72 0 R 73 0 R 74 0 R 75 0 R 76 0 R 77 0 R 78 0 R 79 0 R ] >> endobj 72 0 obj << /Type /Annot /Border [0 0 0] /Rect [133.6979 531.1904 226.3998 540.0669] /Subtype/Link/A<> >> endobj 73 0 obj << /Type /Annot /Border [0 0 0] /Rect [415.3476 513.4663 540 522.4425] /Subtype/Link/A<> >> endobj 74 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 501.6108 98.6401 510.4624] /Subtype/Link/A<> >> endobj 75 0 obj << /Type /Annot /Border [0 0 0] /Rect [516.1992 358.5662 540 367.5424] /Subtype/Link/A<> >> endobj 76 0 obj << /Type /Annot /Border [0 0 0] /Rect [96.9066 346.7107 163.3171 355.5872] /Subtype/Link/A<> >> endobj 77 0 obj << /Type /Annot /Border [0 0 0] /Rect [311.958 314.7306 458.5967 323.7068] /Subtype/Link/A<> >> endobj 78 0 obj << /Type /Annot /Border [0 0 0] /Rect [312.7751 282.8502 419.9824 291.8263] /Subtype/Link/A<> >> endobj 79 0 obj << /Type /Annot /Border [0 0 0] /Rect [285.1388 91.5675 392.3461 100.5436] /Subtype/Link/A<> >> endobj 50 0 obj << /D [64 0 R /XYZ 72 744.9066 null] >> endobj 63 0 obj << /Font << /F26 6 0 R /F42 68 0 R /F43 71 0 R /F29 12 0 R /F36 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 82 0 obj << /Length 2594 /Filter /FlateDecode >> stream xÚYY“ã¶~Ÿ_¡·PU+ ðý¶G\±k}Ä3®MÅö‡äŒXK‘ ÑοO7ºÁCâl¶ò"âh4>¾†ÞÝßÜ~¯’]"’HE»ûÇ]‰ÄH½‹¥/|ëÝ}þ‡w,öúÞ¿~úH»ìXœRj/-OWåC—v/û¿îÜIà©B½;H)’0”#˜¼ý>Ћ=e,"? v¾¥9CûÝííù|g-šîéVù¾¼…­ySË`%´L´ÐI¤™CžŠ¾M³â ˆ¥|ï|,³#4¥ò²¦Ҳú¾ªË¡lÜPóHßç½ ½´+›‘'Ú®<!?ïeèÙƒì`J /vçTVT ®‹èäó^ú^A½~èÊú‰ÚiS£¬‡½ à S¶åu{x(x)³:UÅKy$¥OÖœÚftìì}X%éh¡$¥ŒˆŒaᒪ؃v¾ÜïãÀ£;„Õc_8> sYb¯H‡Âm çy²?4³ ÉÓ’Î.öDÞû¦ÆÉç¢>°ºXˆµ¶@ýiU½°99Y]q€6â',ý—>ß8¡Œ„V&bš–„ÃþBœËž¾|DÜ«¡ï)m×ÃÑ÷Þ ž #-LଅÓò&»­Ê¡è8­¶<`"O\81^*ös9Í|ì@QgMŽfc÷ŸÙrÙvmv d¯ï _Ù²o‹¬DM9ÅL[Â-¿¡¡ºa¡ÑtÒ¡|X±oþ~#AùþNî´Ô"0Jî"ˆ#„‹ËN7¾HÀÉ…õt÷y">LÔ‡%ù»«àtÍö.íK>ܯ]ƒ§p’ýé‡þ§»Ã5(´i¡'/å ”/Œ6z-'O.$œè®%\™  ŸaT&Œ§Ëù&ãøú%½n0&Øg¢ ¸žBi*‰E áD¨DS–BA”ñ}ßûÅF9`zÐथ ç çóS,šE:Hïßw?l¸¡Ž0»pþiŸ(¯x wE÷\f›þßÄ.‚MSõ´$íx³ÇÆÊ ¾ á±iþ\oH„BÁqÿ /Ê‹9ÒWM‹. ~ ¥„èa#8J’ÖÄÔ†î/e?Pl‡‘Ow>RëÃìðгñ¾Ygã)ÇÄD°ÚuªÌª’VÅ.S@£é­HO´mUf©Ë_0‚&ßu¤ÐhôŒãÈ{»2c_è0¹Ò,þЦŒ02 y†‡8†$Fˆ#oŽ©–ç°©ÕR”,¬ †–…a5¶M_ð|JV&´&erîM„ŒÃð"Â}Ö•tI=­@Øèé@Û‡¡×ãPˆ™·è1ÈZЉgçXËi4Àü*·é »): ¡…²JmP´ÃñH©ÛŽUÙ1¼b÷÷ß>RÃ]×eXŠBt\ ªŽÁ™  |-|NÔ‡%ùupºæŠúú½.ÁµN$ÏoEߌ6qfl°1_*ùcVy!·ôµ†âP:’¯„Ó‰î°$¼ø×üpóɦcE+YdØx‚x΢î~ÙëÐ{û+ö´F‚ñ“çl€!Ë=ÆÚú•õgâ(<Û·væÄ΂ô,Ê’«†•´á¸Ó¨ä³/ʘ$à8oÈŽiýTÐÌBxèÆíÓ§¢Ãˬ\°Îú]=ô4lަ{&p ™ÍØÔJócÑ1 1qM–Z…i€±c6ŒO®á

Yÿ6Œ@p’¨Fè(ò†3§ÁNLЧ§ 4^üΆ½Ù¿ñÁF^ áüñ”£Xm”  •¸z“ì#epè™/òÏ%65"ÖÛl; “ùˆc_¸p¤ëMÂXøqèYá<\<á<Ë¡ìçё覂ŒòKD€‰'C™+à àÁP&kÿ„°WÔì`òRkÿÚÆÈmDzF8DµØŒʼ8’33¾ÅÈf…+Öj€ çëé>VØW¾’,µR"AÀ©#€pñÿ(5ñaA½Qi\ò\(Ê¢Ð@M|C¡Q_'Pœ.…ܨ3Ù•xëL~Ém‘ƒ(v1U£ç„ì9 µ5$º_È_cËÖ7]2 š@i YœT‘–½k|¢@ ž–µåe6R²shPÂĹ¦Ê ž]^)D¯@i¶T˜k8ÐCs!´1¶ø\=õÈŽ1fƒÛÝ(ÎQ¼°SôUPI !ûíV°¾(Û9¥c Kèµ¾ ¼§ÀŒ^ÚL³)SÙR ÆRŸTèÍ ¥8]ÐB‚¿s&µ‰ÛÄø:Uñ–)}øG’ËòñZHƒïÍøt¶².î@ˆÆtøpuEwêiÈM‘RO >á IÛíƒÐk²"G,ˆPÄ£ðe<Ûût,èÂp=Aflå¶Êð†iÛ¢;ö,JO“'|éJÑžjkYOcÅ˘3ØÍ«òâ!lúëÞð"Ï,/y»J•XÐ*÷΀öÎi:­*÷ Dª)™œÓ.åy~¹¸"ª×`ü¾R~/›Þ¹lã ‚7¶6‚ßú©!ì‰L.íy3EóqZ “@.qÚÕúíjü°“šò4•ØŽÕe’V2 ç>¯­ÝPâñô¼«Õåó®q™‘n1lÚÑ¡—µ¨^gäF5«q §Uãµî8@‚FIÇüú‡xŽ\9"Éóô°kW>¬1ä«rš¶(†Sêr-‡2±ˆ´÷SÓsY†B†jmƒîb§Kg—ƒ:ÝóÓXæK“p ±aylÎëGJlׯ•x«lÃÎÇã¯ÄG¥i¬t–ÞŒC;›Gp·€iN.oØ~¶ï€`Aïk—ô„Tl‚'%‚Pkûz«„!&(,>ÿ¸<ÎêO@Ö8yÓ\ýûëPõ×sW×ÿ^¸7Ý5+º+ͬl6·°eË{(Á™_¶¶^Û~º£ùm ÞÏO| %ö¸à!w‚*\›áÀnþøËßå~œ‰;ÜK™²>ÝH¨îeK7RÝÜÝüs†Àì°àæ°OWSé „ ½6*–fU$;ˆ3±/­¿ŠÀD!ðÞú"| · ¨©/ð]ñXtýZCÓ¿5“Í[H©ÔhÒÕ1JóßCø·ýE„v³ü›ÈÝ.Òoè2 „Á÷tDæ+j\0"5®ž‚Õ.€I*JÃÊš D ¡ôT˜½?¦í@yÆ:F¤Ú]×ä#%Q–þ¿ î®endstream endobj 81 0 obj << /Type /Page /Contents 82 0 R /Resources 80 0 R /MediaBox [0 0 612 792] /Parent 91 0 R /Annots [ 83 0 R 84 0 R 85 0 R 86 0 R ] >> endobj 83 0 obj << /Type /Annot /Border [0 0 0] /Rect [313.4821 608.2541 420.8383 617.2303] /Subtype/Link/A<> >> endobj 84 0 obj << /Type /Annot /Border [0 0 0] /Rect [465.9063 485.2344 540 494.2106] /Subtype/Link/A<> >> endobj 85 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 473.2793 103.5513 482.2305] /Subtype/Link/A<> >> endobj 86 0 obj << /Type /Annot /Border [0 0 0] /Rect [322.9964 366.9221 431.3986 375.8983] /Subtype/Link/A<> >> endobj 51 0 obj << /D [81 0 R /XYZ 72 744.9066 null] >> endobj 90 0 obj << /D [81 0 R /XYZ 72 177.6577 null] >> endobj 80 0 obj << /Font << /F29 12 0 R /F43 71 0 R /F36 37 0 R /F26 6 0 R /F59 89 0 R /F32 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 94 0 obj << /Length 402 /Filter /FlateDecode >> stream xÚ­“?oÛ0Åw~ ŽÔ ÓÝñÄŽ’![[‚ ¶LÃF$Û•Õýö=Ù²ãÚ¡“x"ßï½“Ž³¹*9hr`]`=_ë’u‰<£”«gCಜÑ|IëÌ¢I]ÚÕ阽̟ŠGt„!RbpÞZstž&}–{QË"›´”"–昺·í‘*˜UÊÈ›·ÔìmÚõç#‡Eß§n7ùøxëJY{¯ñä°éûç¢Èrg†aÈG;C\ÁvÙB½oO«t§nØw¯ÇóÙ´<6ÒM1Z蜼O̲"ˆÞŸÛo¶ËnÑý<)úTo]¿­›tF 'Åêa®HÒ &Í®dëu(Ix1êºUßÕó ê•Bý¤l¬¼¤@}Ö­bˆUU]êF}UŸ¯ÀüJÌo‘³ñ×ýöYØ# ±}wX7?º)ÿ½¸–8´öÿŽÿ×R4Ó½¸°éÛæÏ¨2™ÞyþCF> (úü4›îÀ{2yïˆø2ÁNf80ß¹Zn ¸€Õ4‹öú,.ÈWendstream endobj 93 0 obj << /Type /Page /Contents 94 0 R /Resources 92 0 R /MediaBox [0 0 612 792] /Parent 91 0 R >> endobj 52 0 obj << /D [93 0 R /XYZ 72 744.9066 null] >> endobj 92 0 obj << /Font << /F26 6 0 R /F36 37 0 R /F59 89 0 R >> /ProcSet [ /PDF /Text ] >> endobj 97 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶û÷³Zs„ºej j(^Ÿ’Œ„œørâ¾S’ŒÒÙ¨+,59oxaœ„ n½ïèEXÝ6”ÚÿÊŠîÐ]Óä¾ù]§›Uröšˆç÷¨«šR,ã¡§p |A%’endstream endobj 96 0 obj << /Type /Page /Contents 97 0 R /Resources 95 0 R /MediaBox [0 0 612 792] /Parent 91 0 R >> endobj 98 0 obj << /D [96 0 R /XYZ 72 744.9066 null] >> endobj 95 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 101 0 obj << /Length 1634 /Filter /FlateDecode >> stream xÚ­X[oÛ6~÷¯º‡IEÌð¦[>¤kŠ¡HÖ¬q‘m1(c •%×¢ãfÀþûy(YŠÕ˰ÁÉÃs¾sûH‹y~Ì‹¹3J¨ˆ…—¯gŸgï?R¯˜QïõŒ’4„·‡%2M˜·žÉ(éÕìzöûŒ9=sP4jz±˜¾â‘—’4‚ÇâΓ)'"MR/‚Éxê-Š÷þ/¿ž]-Î߯O_Iî1I„Œ¸Ù¯’%‘7ç‚D”[ñÅMÀ©ÿƈÏνy°… aýÜjêÜà’ÄIÌ ,KBã(ô‰â8±ÀömQñM ¨ÿÌyœø·Y[æ-ú%†q˜ ØgÌÁP”È=[)'ÌÂ,!I,íÀÈÄRr4íäÚ|[nt0iè—­yJתgtƒ3Ë€Q_Õj°ÐÏ´ÂÕ¬ªpY¯ÜLÞ §j¥Š±ÏsÕ:NÝ)÷Õ-Î]«í}™;Uzµ dè7»åÊí¨qA™´~Ù4=È›ë—ÆORl‚eÀIÃë hòÝZÕú‚Rpn¸p WÆgóV(ŒDÙÔ8Ñ-d÷YYe·•rCížøx÷ö_ö«27ÁYwoÐ ¾ûÒÄšm:óN+Ú&Y¥à xÅ¥ü^Zc"b&»ô—&7FõqêzøÌÏ«"0ÿÇúa£Z¨¬vhÛ.-f°nŠÄtˆ>cþ« }ôrýÈ«þÅfȸ~cÄÏ®pþEYe½ì,öòÖëaØLwÞŽ2غ¼mûB€û……Mm¡QãòÈ7ÜÑÔ:+ëö djÛ ïšíQmòÕ:ëÊ饼î~û0—nHß€É ßРiŒ”Ç æŒRê_:ßú-ßv OIÌY¿§ßÕX¦Õ»[|s~vªFÅìÅ´Ñ”WYÛª)bz$ØsT*¥V®"Êúàþ#:f‘$QÊ8ÐRHO¤¡R b(dJ+ôéÀ¹½ô|(ŽÌ›¹ðH«y$Ô’ÁâÈÆeôåãö¿Èêå.[á â›Dñ¯[ í厑ŽÛöHŸå,,Ÿò€g\MíbÜ⺖û¦ÙêCZ2‘jÈíB)QÁ¬áªÉ3 º&ø%%‰9Z‘_^ºú6xâÐÒ <î²6?à`­ôª)܂Š/*ëYFgYœ†æV[íœrF°y̦îç@BÅ9Eád[ÓàIè¿k´%[x.¡'|dÁÛjl’4¤âÝÁ㺃²‹ú3xªÞ&"R"»M.YRx@  ï”s eÅ&BXÉŸ‚y=~þ%[o m™ÁÅ!öè€N “ôÐÍ(u³‚x_ª6»n²ÍÛM~Qê…jõõ}îö?³ 8#!KÅXÙb„¯ V  EØþ§‰¾ê”?ÇÇ“•Ö›g§§ûýžì½5Ø#µÒ§vÏ·›|^•úÉÒBÝ¡Ž¥ÒæÎКIX«ª;“°oàÝ*½ÛÖ?è7ù–w¶&m|p‡ô…vÛêùoÐÁ'ÚOnÊ‹„ÀYVáÓ§v lÄa{ƒ•Oûƒ¿sÎ$c}Ýcƒ†1ƒÝu'îõ›³+ƒ   œéÏÿ!t(îMö¯üAw"¸ÂFñãàþ=É^‰91áü—æ^¢®ñ8AO4IÈ£îzt~ ¡Pöt)ú#Kö(áß*œA~Ù8šÆÀÃ]ºÃ]àJú-Ä·r{\Ï™Õ!¥Ûû0ÒÛ;0r|6Žõ¥ßÜu Wm÷Œkc¡8ïÇ×%KÐíáôáò uøwkÅTXŸÝG=Žn´vòõöÑÛ,Wwe¥ž·-iuÑìt§ú‡jاuÇù$ývœÝÝyà|„ëðÊ^÷%?N~' p}p¯•Ý/\^¸õáýŠLg¸bïŸæÌ¢±†‹—«¹¶ãÝåàì×YmïV R:„p–YUþek¤27ï”ûøÏÈ99*€^¥»ÍSiˆ)0¹1‘)ðÝÚÜþ)³c™¥ý£…3ö؈]YÃD/Î aãèÆí‘¢Ñ?צäïUÕlJŒ=ìÔØ]ukLƒºãï!ü;àyô@¤Iè>°4åýg;˜ø 0Ptü1#’Èb/á¦Ç8–cØÁù#]‡ôendstream endobj 100 0 obj << /Type /Page /Contents 101 0 R /Resources 99 0 R /MediaBox [0 0 612 792] /Parent 91 0 R /Annots [ 103 0 R ] >> endobj 103 0 obj << /Type /Annot /Border [0 0 0] /Rect [164.6912 383.1716 312.1867 392.1477] /Subtype/Link/A<> >> endobj 53 0 obj << /D [100 0 R /XYZ 72 744.9066 null] >> endobj 102 0 obj << /D [100 0 R /XYZ 72 453.138 null] >> endobj 99 0 obj << /Font << /F26 6 0 R /F42 68 0 R /F36 37 0 R /F32 19 0 R /F29 12 0 R /F43 71 0 R >> /ProcSet [ /PDF /Text ] >> endobj 106 0 obj << /Length 1330 /Filter /FlateDecode >> stream xÚ½WYoÛ8~÷¯ò$CR”dÈC[§ÝÝ3l[´DÇDuUGÝì¯ß!‡Jl¯R»‹>$ çžoFÔ‹õâüU”xÉžxë­—r/e”Ð(¼uñÞš Œhâ;|\¿=ųižÊ)󨕽–ÔWT¸RÝ;¥#1%Y”&Né)ˆsjí[½¼ÔªÞë²tîæïTíØR;mÓ!!Ý‘ ÀÖ×Våƒ*ÓQ꫾mê^ŒNþdíÎ?PÊkY–wyûW¿qì?ÿmÆŠåè+Ù³ýl€OH× Ó„dqšz!c@ÄÌ&º‘¹ îSò˜úº6•5”õhˆŸUßKcëÖüsLt<Œ]m²ò§zc¯ Æ|‚Å‘·„b'ÂvhI"dD¼Œ„ ¥êoƒ0¡Ô¿À•ïšMS*Yÿ¡>ª>И³ùPHz/³I›¼©Ûqp*G¦Öݨ攺¾=’k›n ~C0<ùœ%V›4Âû<=1œœ0Âð‡»VAKxºô«¦Ë9äAL\ÎDbÕWÊ6ߨE<²ò¦ÀGá°|iADÞT@§“h¶GÂïó€Å€ÓJâAµñaÁŒÍ "ÊŒOiŒw}µz‡b«&+œà›Õ{Ðu^Ž…®oQrc 5êru}_þðÙê˜â’ Œæ_J ´£è8îH<$ŠÇ…ÊKŒÓæÒ`Àš6„’ƒ•/ª4#‹‡C]UªÐrP¨„ÎtY É…l1MeJu?ÖA컘ðø¶l6²tOjÀm ú¼iÍÈ$§ß¦!<‰!DH[NÃÆÙâçk²ºœT—m[ê\º©ñ`'{'‘ç0ÖÎjsd=ö__®ú“€¦4¬Ü]ë Dª6œ†Ò`¦›Ë³ÐX—|0KÍlƒdó»ÓåQkx¤-ÀdkNæ¸+Í“I{°ØèzÊÒZéÆé¨…æ×°½sgo;Ö¹˜ÜôÑ,F4 €°¾‡ÑsùŽéë©$Œûë€б.ð¸:¨ËÌòc4&"†p´Š¬+ÜBuÏžY—œ‘˜eѱ !s›lž{`ô'U¶nÞ¬ÔÖTõÏ«7dýÒŽÕXä%¥úº†<žºµ $ÈjLÅ”üqõ9NÅÁ:=Û Cûìü|¯6=¾x{"+ùWSðzþüúêœVªË•{1ŸsJÀMÈÄÙ\B¾&ôìb>;Hôì±—E¡¶(}sc’»¹±fT¹uFZ1G7ÛýNÓ»Çqå0tz3ª¿ø–’㪯ƒª‹‹W²ì'Vqt:&¦‰FÄcb A‘8ÉkOžØ333xÍ<œ|Ú?”>‚&`¨fÚæ¥pgb ÞO"#œ.ù?{Y*\åˆ[»Q™ÉîèòŒ,)[þxèfóï¬Ës‘ßÛRª3õ8®q9 À‚òoÀ!Âa%É¿OÆ`÷$Ùw¡'$Š³Ô¢‡ wKÛAeT‡WšûUú?/H¸Àg)? òÓ \á °äõze”EâñNÿ·F=ëÔü¶ gÝO7¹£lV&t„Üdbq¹^˜ê1óñ BøÍ«ÅçÅûÔ+Ô{» $Ê–±·‡JX–q¯Zˆd9=”‹«Åï÷fBÐ ½0_Yüä+KÀå•qÄMbs+ ápÉuF/w²¦þs2÷!ÅIÊXää÷}QòÖ½ñ7²×y?å÷7ô³oendstream endobj 105 0 obj << /Type /Page /Contents 106 0 R /Resources 104 0 R /MediaBox [0 0 612 792] /Parent 91 0 R >> endobj 107 0 obj << /D [105 0 R /XYZ 72 744.9066 null] >> endobj 104 0 obj << /Font << /F36 37 0 R /F29 12 0 R /F43 71 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 110 0 obj << /Length 1605 /Filter /FlateDecode >> stream xÚ­XYoÛF~ׯ ÒS€µÞ‹—¢°cçBƒ¤µ€uƒ&׊dHÊ®òë;»³¼dŠ>qµÇÌ7ßÌÎÌê|½8yÅ}'"‘Ÿõp'`”Pg^»¯óò6Η+θ{™«­*Züq¡’<®—Œºq›•ÅòËúÝÉ+)œDùR‹b#‚3æ¬@`ä…‘Øî+•”©Z®|JÝ_ñó÷Õ[Ò$µÉëË‹ÏÔ£Ÿ™Z¦ÃñX$¦B^lÚ¶:=9yT·ª²D5$ÞÆßË‚$åöäìÓÕåËr»Uu¢®pý„Sê¯[1ùâØ¦"ߨ¼zªš"Ƭ¬XÀI(©tVBIµpæ2N–Ìs7Àˆ¸Û2Ýå Çð……•ãO ªiô0tSõ™R^ÎÌZ½«*ü4Àoƒó1~vEömg¥ñV5Uœ(Mû±ž‹Üv£–‚ºû£%÷¬,ÜÜdÛ*ßãø±ÖpâªRÆcVCy‡²"ͲtçjÒ3Å€)«ßjàa`4à …œºÿÄ NáJ|[j5=Îh´»},qWVÇ ?ªÁ ËxÀ‹F`!V$B£1Íœ›8%DŸÝ÷lŒÁñ§§Ÿo‚y‚æàÏûî*hq GÖŸÙp üp IÀX†Òb‚ [NWRF$aØqËÌzõ§o7­Þ³¸\/œ£s„*>s|B ŠÈI¶‹o‹ë/ÔIÔy· DD¡ç<ÂJXqg»à$ Aý/®ôW½ÄÕXä¹N„s š5Î u7Ã?“$°mÕŽ êŠT˜¡1 0V}FõÔfoœQ¦X$%¡Ïù@fuH#âIüDõŸ!ŠGœxÆD%sDùa£ÀÚA–+ö›{¤lËÆ2’Äx)`2ž¹%¾[PÊBò¥ì§ê< 9´ Á¬hÚ¸HÊÍ> Zepcê‘nÈ|^@.Ãi6èÝéQ·¬ñ›—I75x~xxÈ.ñ¹”CváÝ…åÁ$»<åÀ‡(®ù´À"ÞíASÛ]m®9f©‰XÉ:Ðnæ= ÔÒzO¹Á›l³Á„è0¯ÿæž®²p&M3(  û Ó6Ùds3›!î}¿Ï¸:H)w?mö]þ’lÁi“hh7™F#¹7{(Àm½ÿM ܵA,Ù("`—.58ÂsÌ…zžÅyö]¥ü¶Ýù¿Þÿngb]^îG‚lµ‘ÂR?=hs6LM˜2k©j’:»USeÜMÊ¢5—bR1Wë6ë–§è¡â½Å µa_”Z!tCÓx÷†x|« å½6CéÒhî‰áÖmÍ‚Q\àÆÈÈ’<Íd‰£>:Œ…p8ÎsœÏÌ7 Œ©¸œ3«õ.i͇ eÝmÀo³»ЏiÁì0ÓEXo˜¬0xÃòî:+б߸(­Aå ¦ ‚á qÜ«¼Ó„ aäù'О.¡„þ³ÑB¡‹Ò¢Îya×Ì=½ …K™D)ÍW#W­!Ý€©}<_oé=æÑž£wbe„°-Ay‰²RÜ}»·‹:óm»ÖÄêÐÁfëKé‡önÁüš€NÜ®UÚóêšWÒ¯8WuSZÍwàÜ©x쓲R“pÙy"³ÓÙ0¸ú°ô<÷ì#þ:×mgq¯MÌ`Bc·!ëò-¾1šMœŸìŠÑ/[_0mm‰£jç;Ýe£h˜¸Q€mTà]6=4™S$¥{!u5 ËÈÄùݺî½M\ÂÃ|ÀG>`½5ó>¢”Hp&ï›Ðõ«ÈtðêF#¹±ÏsìðêÃÙGË¡N.§?~-2÷à™ŸM¡ ò2®nîUûrW×|„VÞ¨üîwTÍ3zõ^RÛ†vüÜ«ò1®#pªÂV$ÒuéÝ{ìfmŠ!J;”ÐTÐÁÙýéU BÄ&ž%:~¯@Ú©u¹&—<6iþËTòÑ—‰G3 Íb-ËöúySIÑTºŠ?³ÍlÒ–ý$œqw ¯{OêÃ÷'Úbéÿ¨'†ó«‘ ó¹¿$$XÆYŸk&çî{“W±žJŸéÓ®Ã:´ÿ]Zi endstream endobj 109 0 obj << /Type /Page /Contents 110 0 R /Resources 108 0 R /MediaBox [0 0 612 792] /Parent 91 0 R >> endobj 111 0 obj << /D [109 0 R /XYZ 72 744.9066 null] >> endobj 108 0 obj << /Font << /F26 6 0 R /F43 71 0 R /F36 37 0 R /F59 89 0 R /F68 114 0 R >> /ProcSet [ /PDF /Text ] >> endobj 117 0 obj << /Length 1975 /Filter /FlateDecode >> stream xÚXÝÛ6÷_!ä¥2°æŠÔw>4»i›¢¹â`r×4¸w-D–\Q^Ÿû×w†CZ’WëöÅ&‡óÅá̽Ý,n‰—³<¿Í£— /å Â4ô6å'_«n¹ ÿy)bÇ‚ ¿ÚíkµSM/ûªmˆV´¥Z~Þü|ûCzèK"ÔÇC΂´®@kg¹Ñz¿^®’ ð¿£?m~¹—½ú²VÝsUU^0•*j©5IX®ßƒ8¸_Ã/ÿÖÎbž‡S±R=Z3­ÜyRýÝ¡ëÀy4‡ ´ªoˆc¯/u]8Þ)½o­&î߯Ù?U=·-§“mÚRž&šû”3s£Ž_Ì2ÚyM5Úgúã tÏÞ7ûC?ÇUöS£ÕN±º-d#To(n‚¶^³gbÿS²›h,ûOÁç×ù?´M¿½àWî/‚ìâ ûOíá…?á5ªæÐ«K‰èŠÄZmS^JÄW$>*õµ|¹äú®}œ‹mzMH÷—ìÙçù,ì]3M2ªg±0JôЧ ò8õVqÈb‡‚‰%èáU8ÁjB"ÒÌß,¹üÓ^ÝHhÒŽQ|)KENÊ6[ˆ¾‘ÿ„zH_ìô¹jE0ìA«˜Å„`Á,íN9~Ë|lið{„ò¹5nê¤å¾Ô¤q PÍÙ’-r=+t!r_úC©ÀªuäœqÙºëi%ëêOÐë¢Ï!ú±0;®š] sÿ¿~A‡Âìbóu}"Ü11”Ph*gÁlÓöÌ\î%,OÃÌ1[p/d #c”ÏœD ÐÇÞjÄöVêª0öãØGß"î÷[ëC#MÁ´ìû®zXÂA›âÁÅöÑ.5ô?ÄÍx?‰qTšGÑ":Æã¶â„-LâiüŒ…8ÀèÑ —=¢X×ì2F—AR- äýjY·•¥WÍcÛ휷1^(ŽE-áŽ<ÑŒÎÀuVªn¦¾*úÚrMvh”÷VÛ‹½TîeSØ tÙ“²DDtBZ¬ò0‡ãäefލè $ýQH ar’Á(6ȱ;8ƒ¤èQÑ?:9¯sf¨¢4Jü;p©*! Kî7OÈ–P^ç²›©]¨FvU‹~ aŒeÙX„Y à“F{ˆÑ¾#p‘ÜÞÓŸÆÊ7žžr Ífr9ŽU]Ó²><œugv/À0ëX6ul²K>~î`Ì»éRïJF³Â]ü Ú†!ËÃ-t3nÁ[šBZloeSÖd)µÅ ÿçl43Ìýs¼†ï¹^“_$¥ù†4Àé¬ã úgoË“1œþ]tÞý¿PûQ÷S5E}pðt ÿ4ç®g³ÌÎÍüC¢Ó°K:Ô}µ¯­ø£qnÈQ4ÅÌ k­Û¸‘Öv_g’.ŽXÀÿ?Hº(É®äÛHÑÛ¹¡¼‹¹ (ÏLAkÌD¹¬¹ÛÊ}¯ì³R°™ë+,å<´üG]ÖboCõ€mµvûû „À˜endstream endobj 116 0 obj << /Type /Page /Contents 117 0 R /Resources 115 0 R /MediaBox [0 0 612 792] /Parent 118 0 R >> endobj 54 0 obj << /D [116 0 R /XYZ 72 744.9066 null] >> endobj 115 0 obj << /Font << /F26 6 0 R /F43 71 0 R /F36 37 0 R /F29 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 121 0 obj << /Length 2680 /Filter /FlateDecode >> stream xÚ­ÛnÛ8ö=_aÌKíEÅò.©À>´v0³m÷Ò,vé Pl%ÖÖ–=‘œ4@?~Ï…”%Yi 4È)òððÜ/t^žŸ={£ý,¹‡áüj–êYª¤&5³óÕïó¢.¶åâóßž½1}89K´ZYO`çër‘h•xšVMXâá|‘Úùý¾|µ[E€ºi‹zO¶íMu¹Ðr~hË…’󧰮ݼjžÛbs˜FÝÀÉúšç7 “ÎË=MY·ÝN»ž¼‰–ŽTšràw}ŒW%½«¢-P0( ¥Dîœ"Q<@€÷ ËM¹…uüpóU¹Ü7mµ«Å"1. ¢°¦ly²»bÐÿ¾{ûa¹Pn¾.·Å *OL4<­ÂøþÕ{XDI¦ÀË®ÛXšÃ¸‘®„‘ØXUuqs?dV³Õ ü(¥à˜“ Y÷÷횃½¿-Œ›— #ç÷woßTŸðpÉ_,¹öpõŠ' ¨&œ((/Vί‹ 2Ï@zÏ^ŸŸ) ZΚ¶·`³Y6[nϤÈíL gi÷S•XÒƒ{I.’]$î£è²}±,G¼ƒ¶Æ(ç…÷Êè{= :°:¬™e@‡·H‡’R s¯œHeðÄ77»í"ñRÃo$ Ç@©¤à²œù ±-¥æùó¿2ðGéäÛ²mA½ôý…‡'O`Gaøô«uqCëˆ_Ë\dÊÀ-Âùœã/´“t[¹0YžõîG c&îÿ¹º®Ú!EâÉð;y2¦xðýj·½¬jðM¾±·óús[Ö+¸0Iƒ½«4I÷dÚ<ÿFŽ øù®¨hŒQ6Zþø•¼åª*o‚JÈ´qò©DŸX5ðFÊ©º“ ?Ðφäóå§‹Ÿ†:ÙœÊmu"·xŠ4æÁºr5©±¸¥Ñè²”ö~.¯ŠÃ&à£ØŒÌÅ£ n^¼ñîõ#À´Â£OYå¹D-Ò4'³©0©fý¶ÅŠº¹Â8Q \y¾ÈN‰,³9pÖ÷öJ¸x|ñ~¡Ó9²L¢49ˆÞ Ôg’E¢ H:`f?H1ò}ÔÚž«„QÀ€uÀ³’£ÄŸg¿ÿ!g+ˆ*¿A„3yæfwb„Ês=Ûži‘gOÂ÷æìÃÙ?{q'bLú()ð xW•ŒÔriœ%œD¢€SŸYÚÖAN`àr0KÒ.rXïÚaøäTäv@j€Ø#®ÐV¹ ‡/šÊØzNñ€U§^eßBcÀ”>4Ø‘33k,d­~X_ÒGxª p t`‘>ö$Ê›,r(CŽI6Úè'¢³v ³Gã¥Ãø nŒÒ ÎTr3éÂV24”¥PÝA"§Wâ¥+,´È½±ÚjžCUb-ƒÍ‰oåè5 M +íûVĘôQ¾<©¿Áý`ïÀ¾V…C¢´ ~Z[ã‰9.ËÆ bïr33i.$¨æÇŒ“>ʉࡌL¡;2H4cmj!øü9l k"‹ã¶Áf†Ûm¢¬ÂR@ÛœOWí¸Ó®ÃéQÛ€{Gª¹m øGA¦Äç ^žè%¬e‚,ôÕMkm爑ÜÍ—»º-¨R @ØwЩh˜1©¼ æï‚ùC8ÎrLöCŽÕyÃ+˜Ç· „ãH_«pÜD9ÖQs„Á¼ŽuéSœÅÔ=2“<ÊĨÝö›²y"×:„°Ø:.9p, ŽuüÕc©ßYôÖ|e·7247S1)Ð=ˆHïªÏHõ•ˆÎPÞ2]Ÿ[^z:rBHÚvðc¯ÍrámjgFH¼æ¼6bLú(§Â’Þx}¼ùaI2ø ,ýåÝó7U2nÖ±Vèj­Ð¬÷òYÓîú­!ÑA̘YÌñ†"Ìš]ÄMX‰q‡7V%ö¸uE®Ûlvwt´ƒÎÓÉîrX¨~ಒÄö l‹ØÊ‚îß×Õ2h~OÆÊ›å…V&Þ ÷}Õž.óþ+õ!Lz£æ{œ`…‘æyÚ]L‰’™R|š1ðÄë§jÃ/'eŒ›Rš]öš¿Á( ÆìpåúŸ†W·E}Ï3Ð&öý·e]a$%µ„W hˆæšãßv‹JÍña0œ‡wpú=*˜çq­-›–¬ÌwOñMhS—›î­Ê›°€ëêz½™|1á“ „-6™Áz/ïÇV€î’S·è°¤ÂkËÁÖ%’iÕWD ›ÄŒe„®øc:Pcñï‰ÍÅÅ6šéÅÅT9 F%³X0n¹«6ž]†®èa² ¤ Ç@]—!=EB÷ì ø”dÌ6:ÒBo zêu:4`ŒÅŽŒm Ù—Ë–×HÒ4a-©¶À¯#¸„‰Ç@ÍS|¥s¬i\^²B‹^ð@Ìö¯Ë >²Ñè_ïðñ ?®vaõ˜¼è+¾ìÒxÛ¾‰×Çæ‘$J7–ª4pŒ“ik A¡b š×|ÄgÉLG'°ÎI`ÞT€ëžçÅj îX‘ûýñQV¯áQcË—¸®ØðÛ(©Úu$‚4zT^ØÚveS?Áð¶»Uu5éaÌŠ‰ÆxQi|ì_ÿnH&žÔÆ3–££7SøÜ‡÷Þ‚î4ä0îhSÏÆÛŠ®¹ §ÉæSÕác|Yµ±Ô‡8“ÎRð,•$|4’­—\$Kçow»OA¦X®:õ³ ñ±3P+ÞŒzóÛò&*ËÕaR<Ã_¼€ò°ýB{óì‘ÄgÂc¥Ä‘äRšJÛ Ì, $E¿ê¯õ2š"÷8†T«-r/\ïÕ†°||8‡-lʪÍúÂë”íÈT“›‡`=n>>J,RVqz( œ ýºl/Iü:v*(%­ÈT÷Ö"™ãX¦±pn¾­ GB%†‘²º-7Ô‰àÓÖó_AÒFÇߌ†¼BB*H\œÉ ¼»áÄHÐÛæš×EÃ+(¶$†îB·I#Ê4óŠÑA¶²:Ê¢/¾‹¿ïùü«Z h©Í×%åÞMHðk˜U. G+Y•“À ˆŒU0TðQ Y÷Û õ5ÐçõL>vìØF(¨ëÜ0Æs63pˆÅ…Î̦²*Âp¾ §@¤¤Áùr¿µ0+Þ¡ä%É1p8î÷ÃfjþntsÆŸ såM0‚ÿšvt=—ó¸¯ ['-7BWÍTÐ:6ñýp…‘xúæAmÅ1õØJÄÆ²ÙõÓF{R€§¹°™4øûÏ¿íE\ #›x×ËÀTñ;ÕÖøÁlVeÙ£Öáz4pa¡Rü¡˜Ië^·‡¿Ö5§"4Ðx•úG¡3âz˜Î b„OþZå…Ñ.} Ò:\’ÁAeÝ"ìw°Çúr5õ‹¦³Búï£Ùú‡ÆŸ<{ˆ^NýW€ÕB©ð ‹Ýì"ñ~áø"cÕÞ=o„;vVëјeìòÈÇÿ³cendstream endobj 120 0 obj << /Type /Page /Contents 121 0 R /Resources 119 0 R /MediaBox [0 0 612 792] /Parent 118 0 R /Annots [ 123 0 R ] >> endobj 123 0 obj << /Type /Annot /Border [0 0 0] /Rect [72 642.1311 156.6616 651.0824] /Subtype/Link/A<> >> endobj 122 0 obj << /D [120 0 R /XYZ 72 744.9066 null] >> endobj 124 0 obj << /D [120 0 R /XYZ 72 256.2549 null] >> endobj 119 0 obj << /Font << /F26 6 0 R /F36 37 0 R /F29 12 0 R /F43 71 0 R /F32 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 127 0 obj << /Length 1231 /Filter /FlateDecode >> stream xÚ¥W[oœ8~Ÿ_ÁÛ€”qlc.®6‘ÚÝVjÕëf¤>´UDÀP¹v‰Ý¦,„.‘ÕË튀 쇰ñˆ'ŒbD‚;iµÂˆƒE(`šéûȼ¹7Söª`)Ÿ˜r,U[r€È¨ðGÌÄÑ,Ûî!ã¨щüxnœ=œ˜5ò›5‹!e…˜Ý3+1ÅdíšT–&ìšÎ,D’z$ps»;'²_™RfÙŽ€Ûªrb_WŽÝƒ9œPÔ…,’²øg0হ)r y UNM•k¥8¥Ô·Mõµ!Ûê—º‚aŸÔ™Yô¢ñ¶`e=‹)Ü­Ç©ÛX ?›ÂÊP…=h/Ë¢/šºÙƒ¶óXpWFÂ豕±Ø 0/"l¯tå(Ž#n¹NL¬ÃjÍá&£fB­°øŠ1íTœziåX\œp«d®hõfßÚ(À2‘²+®Tâ÷Ò’ Ë•&m!MbuLc÷umì­¦n_×&o°1å“èBðÐ¥·Çy2ȵ¤ ¹ õÁ w)¨x^=Z©s¶8ÅÌ'cX7 ÇÀbè?‚¤'eÙ›ån_§Q3ë-áÒ“TÂô؈YŠå⯷hŒb *að(HðrCcľ™ÜöÙ3d·[=ÐCl&ÙÙú³Rd”¤¹ôú\û©z6àªï`Š1¿“Õ‹{wÊ.ðÐz§ïÓ^t‡µ¡TEý!M÷]¶Æ)¹HÄ’Tž­µZèÈúz}z>¤áW¾-ªBþ¦Â¢–ƒ¶Í²—§ÇáX²Ë€‰’;ËdQ‰f/´fÍþª–> endobj 129 0 obj << /Type /Annot /Border [0 0 0] /Rect [145.9721 676.0001 238.8738 685.0211] /Subtype/Link/A<> >> endobj 128 0 obj << /D [126 0 R /XYZ 72 744.9066 null] >> endobj 125 0 obj << /Font << /F32 19 0 R /F36 37 0 R /F43 71 0 R /F29 12 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 132 0 obj << /Length 924 /Filter /FlateDecode >> stream xÚ­V[oÛ6~ׯ²‡ÈCÅ’Ô½XöÐaYQ¤×h¶‰N¸I¢JQMìÇïP¤+µÝ¦‹_h~çþQO×ÎãÓ0pS”Åqè®7.Á!ü³ á$aõÁ{ÆênåÇ{¢5ë;QodÑœ³B–Wù3QWLšn5Q 5Û¡}Îä^²\Ýt¬·¨³R=Y}Z?w±ëS‚2’¤£é².ú~¿Í8Ây~1ðZñ6Ï‘A)Á"$Yæú£,J³ñß•O(À½`êJT»bÞ²Êl®˜d³3Ë«;…/ÏyËUžk—zVof'îrÉTÎjÖ°Vå¯:ÅEÛÿ/¼–]ÿ8Žèè%Sƒlm^ [ÌAS5uáîíH¿?°GöKQì§‚ôäwÈÂk):&g×.6 ‡*Ñ«7ÆÌFØ ³i4Ä—¢en“JlBÞ¾*ËAö'GøÈŠŠ¯“ˆXQËëZ×öäè´¨{vtŸ@F/ƒžýÝ`˜å›ØXèïZxˆnz|Jc7惘ϔÐ8pý0EQ€“QS²Ïë•Ñ_0e ’&ñx#Es€òʚυãM'äìR!’ѰPgd„úu<òoÏ2¤™!Ŧ¿\¤caì­qYçc_ü¿Ìu²SÞNÜÝ«¢-휋͂¦†5=¿Åø[=ô¼µ®mŠR i{·¹v—+ Z ÛD§–­x‡Í¶ÃÛ~3lxà¿l·Úá['Õ•µ»3àÓ¬5ö‘Øá¹ö½Ø£õóø%»V¢=Þ{e»wÏxÃÇJ‘ïS¤š‰`®Ü@¡”äƒbíÎZ¹â ƒ±fãwgbnò#LµÐà…§Ñ<ñþËvŒG"3´pclø½}k‡äL”4ÎT_¡.Ôš›×³†7èP‡Ë¾[XÒ¦ÑG߆žÚÐI>Mê±¹°†Œ=9¶ôøè-ë‡Z¡ÛÓ¬bóÂçTRyÿą̂ÛªFaÅàȤãÓ ÛurBª¿ò¦Ð­oÄz8ÇuæÏ»UF=àŠDž r$^©·'ÍyÊáiGœ?×»Ø%nBÝ(Wa-ç³óáv+»Ïø0ÌÒȽ† JʨÛ8aœN›Ú9wÞÌ0>Ü÷·€žê/ÍEf@RD5tGEZJ½¿X ÌBtKë–&©·^Á“éAÉÿ3ÙB%‰M!S ÿtÓï>endstream endobj 131 0 obj << /Type /Page /Contents 132 0 R /Resources 130 0 R /MediaBox [0 0 612 792] /Parent 118 0 R >> endobj 133 0 obj << /D [131 0 R /XYZ 72 744.9066 null] >> endobj 130 0 obj << /Font << /F43 71 0 R /F26 6 0 R /F36 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 136 0 obj << /Length 329 /Filter /FlateDecode >> stream xÚ}‘;oÂ0…wÿ +Sâø;q Te@U+D¤ˆ!S"åÕØø÷5 T”"¦kûéØg’0!)D“-$˜£ …”‡‘³¥;ü¬‹m›– •¶›Ýx°JfÖ‰B.ôìAòHöÆÆäu¥žÀØ5y©ê½9a§—Ž:Í©Q#ÇT:þƒ½¬:Ïðó½jO÷¤£ÎbmÚ¼úrÆïê`êjèwÆž„ïoy™›GŒ¬Þ¯ 匭ýÎÖ¼ÇaüKâç¦ÿ_^@l, )äÂÂÎM ¾Ár…a0œŒ˜Œ8<Ø FDJ Kˆèz)ÀÌ1žÝ÷n@“s±T@i‹µÃkõ€"B(érÚ…fœ#Êa!gõe—6Fµ†‘KÑÙâOÙ-†SÂ.þƒÎ ÚØB(Çî:ÕùF_øÛÞtendstream endobj 135 0 obj << /Type /Page /Contents 136 0 R /Resources 134 0 R /MediaBox [0 0 612 792] /Parent 118 0 R >> endobj 137 0 obj << /D [135 0 R /XYZ 72 744.9066 null] >> endobj 134 0 obj << /Font << /F43 71 0 R /F26 6 0 R /F36 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 140 0 obj << /Length 445 /Filter /FlateDecode >> stream xÚµ“MOÜ0†ïù>:RcflLJ=„´E¢ÝnŒJ9¤›t‰…’¬ýõ|,Šºp£òÁËóÎûŒÆÈ€2+™E ¬b›»èwtu ¬Š€E ¼7Š=QB{‡ì.ÒÆíƒÛ¨ˆ¾F8é$$”Ì•ŽCtt* óÂÚÂO¦½Ê;Ï 4JÏBuÅ?.³UÈ×ñu8;:Õ’¡JÙ'$(­c‰T€ž‡å:ÏûÇQ^ŠSm“:Þb®´‡ZXgq H‰Ñ;ÃÈ‘0–ìõ¶Šz³{ŒLyÓ=,”6gQÖy‰QB§}K(O ¤,àËVq"­ãÇeÛlÆc+à»îæ~ÒþSvÍý¯Q_Í{ Ô$+¬ôz-)gQ5›î;¤ÐvÏ·õâ[ñIdq ü",ÅM×=üèË| :t·këÇÅE‘¯?ÇÒòì<Ÿîʶ}¢âÊòj±Š=ð¬(.c™ò/ëÒÆ×PÉ‹rÂ[?Ê“f[·ÝÿG¬šmŒÀ©Ö›œï ª&ÐóºmËm=òLÆ?ƒ›j†öƒ¹¥¯’Ns‹ÞË—¹‚Wæv&tø÷RIF%Z¦¥@”88Fµ÷óæÊõµendstream endobj 139 0 obj << /Type /Page /Contents 140 0 R /Resources 138 0 R /MediaBox [0 0 612 792] /Parent 118 0 R >> endobj 55 0 obj << /D [139 0 R /XYZ 72 744.9066 null] >> endobj 138 0 obj << /Font << /F26 6 0 R /F42 68 0 R /F36 37 0 R >> /ProcSet [ /PDF /Text ] >> endobj 143 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶û÷³Zs„ºej j(^Ÿ’Œ„œørâ¾S’ŒÒÙ¨+,59oxaœ„ n½ïèEXÝ6”ÚÿÊŠîÐ]Óä¾ù]§›Uröšˆç÷¨«šR,ãAËqŠ×À\œÃendstream endobj 142 0 obj << /Type /Page /Contents 143 0 R /Resources 141 0 R /MediaBox [0 0 612 792] /Parent 145 0 R >> endobj 144 0 obj << /D [142 0 R /XYZ 72 744.9066 null] >> endobj 141 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 148 0 obj << /Length 247 /Filter /FlateDecode >> stream xÚ­1o1 …÷ü ÜpÆv'iÅ ±@K:!Ô£SÚýû 'c•Áy’ýÞg3P} I 1!ùäáýì¾Üþ@Ð;‚µ#4S¿UË g4âÓíÜ‹ã«O[Ú©ÓSqóN Mk)LÐ[6Ðú ,¥ßÏžW‹mY¾6‡²žwA€ú rP´˜Zñ¨$Cw·yZݲܢk²ÆŒ¬ô+LÆ$`ʉ/H>1Rô5‘5¥> endobj 56 0 obj << /D [147 0 R /XYZ 72 744.9066 null] >> endobj 146 0 obj << /Font << /F26 6 0 R /F42 68 0 R >> /ProcSet [ /PDF /Text ] >> endobj 151 0 obj << /Length 114 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶ü+«%1G¨[¦XPL x}J 9ñåÄ}§$¥ƒQßX¼x[ñÄ4 -!¼¡§Wa0ZÑ|ø•®¸@¿š®öÝŸè˜ØÍ)8¼÷ÏQ3V5¥\¦úvΧÄ\®Åendstream endobj 150 0 obj << /Type /Page /Contents 151 0 R /Resources 149 0 R /MediaBox [0 0 612 792] /Parent 145 0 R >> endobj 152 0 obj << /D [150 0 R /XYZ 72 744.9066 null] >> endobj 149 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 155 0 obj << /Length 253 /Filter /FlateDecode >> stream xÚ­MKA †ïó+rl›N2ÙÉ䨲‹ö¤vðRz©U(X?p‹øï]º¥Ð%‡ä…äÍ“øÊ äÑ ð¼s_n¹ò°qæÎ£Y ðS„G±D°sÓ(ÞÜÂ=8:øTŨ:uºÎnÖrC‹%åWc – b)„Ø o–“›Û«ûÜk…ƒDî¨FõfPqÀèyhoïžš¾×5ù¸»¬ŽuBŠþn8uo`AMJ=STFU¡aTMUþý|™V¬i²Ø¯¿»m·ï¶ï8kAK>Ã,©˜dÆGÌA\À<1:ÿtÍ IA‰˜FÒ‘ç¥êk‰endstream endobj 154 0 obj << /Type /Page /Contents 155 0 R /Resources 153 0 R /MediaBox [0 0 612 792] /Parent 145 0 R >> endobj 57 0 obj << /D [154 0 R /XYZ 72 744.9066 null] >> endobj 153 0 obj << /Font << /F26 6 0 R /F42 68 0 R >> /ProcSet [ /PDF /Text ] >> endobj 158 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM!ÂP „ýýŠJ+my{¼Z’!æuË Љ)þ>%„œørâ¾S’ŒÒɨ/,5y_±aš…>zëé•EXÝV”Ú~剮Я¦Ë}÷':«äì5ÏQ1V5¥X¦¶ý#†À\ÀÇendstream endobj 157 0 obj << /Type /Page /Contents 158 0 R /Resources 156 0 R /MediaBox [0 0 612 792] /Parent 145 0 R >> endobj 159 0 obj << /D [157 0 R /XYZ 72 744.9066 null] >> endobj 156 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 162 0 obj << /Length 1885 /Filter /FlateDecode >> stream xÚ­X[oã¶~÷¯ð£TD,/ºH4—"‹ÜNí -Ú>ȽV!Kª)%qýÞdÉV°‹v &)r8ßpæ›!ÉÙGtŒ0‹Ø<ÛÎþžýþ'žç3<ÿ4Ã(IB6ƒF~“ùv懱픳Åì3bäx ÈJúi9ûþ††ó%!ü,×s?NPH’`&ù„&óeþ»sñôtýpuû«ûçòÓ÷7>1?¤jˆ£°Ø£ …˜êùrâìzÙï ‡AŒHˆ¿‚¡$‹€ú(Š#"b1(2€€) £(V*½ˆ¼¤Ë°³w=ÅŽÈv®ݦը@È•ÇÕR¼!?Ö‘Àq=‚1v.ëí6­r-뮨¸nÝ”égqHPJ %(¢$±‚zQ?óŠï\‚´<Âèàp¤ ‚_Ið6g0;ÀΔF^6fÁè4#„&'W\¢)Ó½^Õn¸n¨¥ªµåB¤RÏòŸù¬1ÊÆkZ”éª4ãY:¥Æ/•Á˜iÂî“¶fEZéÆÊÌmR!¸‘ÐÖú÷MÓÞ MXÀ³ˆ<¡Ä÷)ÖzñÍíÝõÀ(  -ù¹°M FÆ6—;—EO[£Ûª¨ò¢² ÖõîÈj/‹«;£ñ¦È\8Ý-Ì’²Î@˜µ]{´\~-{‹Ñ²·H»™„m•Ãîôªç_]y#Sˆ Šü€ýKÄzú¶n¿šëN-]åµÈí4P|¿Q}Œÿ}[d¾M'PuaÔŸ\8hGJdàøFMý#4)МQ€ßE?äôÐú(Ða£b9pz»öˆÛ}ÃÍ6Û´iÀÖ#Yä·ú膞 ç|åRìtŸ§Ðû@Ê~bÐ?vmÓì¯|·ª…Ñí B†n¯Ú#íón×ÏÈêœO¢/êjŽQh|’&úŸ—OÏËãäA€ÜLèœ%1¢”NS| L !IB!…P”ÄqlûGY¤—è Eª\2Ò–ÐÅÉa_Å¢·¿ l_+‹zy±;ŸVž ’UB¾ò½Ä/(Oƒ‘ :UÂM wSŸZ2|Ùíô©Ú8Õ>+ÆÜ=m²*e°Û73@/q£ì.F)õO €¦´Çü@O÷“% é55‰zécãõª¯ß[^ pv¡û’)mª¢©äŠ0¾”ÇWw‚¬Ú”ü}éF¾ÜçÀ>[àcÛ¤\˜L*x&­ŸF&Ž–„DZËRÀÏGE!„+×—|P¼ÊÔ qÖ]¥D =Ǥ9Y*(ÑõJ u\n —8fAQee—sÓÓ^Ô¶ºÌgzTðÖ“ C<²1I~W¢M?š))ÍÚz··ÌÔnêÜ~ê)ØzÃwmaÃÎwßéWÆO%Þ¥ît–ߊvÓD( ‰Ó«ÒmOu fÊm•„¡õÚ{ 3^sÅeÕùêÒÀáeÝlyÕ~ì;Ï•øJïa‰®$½tà?ižk?bÂBŒ"L¬'¼,¼ 9]¦u!z˜¢kšz×Û-Ïôì£L¹ísëª÷Uå ùØsû¬˜Õ;#´©Ur¨.&ó‡Å0Îo²`Ø¡}+„$«I0‡¢¡¯Œô‰QëYBtX«\ñ†W9D 8Ùz¨ÙƒCVæ‚ĆÔJ€[å}FmøãùTˆwÒSàÞe¨" †R8Â8ü²`Ò †«Ú©è7¡À<Ý!’Ë“ðëUÇ(@x2J|¸üF‰oïSà8õ¶ø'mÿs@ð#pcù´'(¨- -9hn3‹þ]‰c]ô-ãâAnpq?¼¨¤@3ü¼ÿ2ef£„ľQöYŒ½5SÆ34i˜ûì°_4د/ìӶݺ곾/Õ0íåà#Œ½Bã²ÔÄþò·§ëÅ0eš8W£SààôpÜD·mŽ8âƒ"¤í3¤©§ê‘ô´V—¥3S*¡fm§Ñm|–bxñeЉ[†ªÛÒj!gëý×!4B?ºXÑcå2½öòîöúayyw±X,žonn–ŠÌ.K¸€/ºµ4ÐûùÉü ,Œ$PH%–ÌTr0$ýn-³Ž”éyòW¥WÙP~§æòÝk‘™Q­ˆ.h"Ÿ_¡×ì‘I% íJ>Èù:íÊöp„‹GÉýOò? ˆCŽÊÌÓo ôýÅÓýãÕóè¡Ù«íïÓæ¾Î»’Ÿϲ‘£ ÀlªÌ'ú¬eC3 P¯Jv̧'#D»¶² “Ïj>‹ÆV9\ q|pph+߇ߜCõ´ÕÏ2rX9ޔŠ*i0ýµ^ý…¤KX™¥p‚9ØŸ&¡)`l«¬¡ÛbSwe®ÛPJ¶©JñÐQÏ=°å˜hॉVÅજ)¼xŒóƒ§Ùy¡˜.µEa½î9n{v\ŸØrõ(à‡ƒ?i(rP…™~z:³9Ì$?I¿Bošp™ÅaôU7ý¤9u‘OšA§o²®‹Í} 9ÔÜKHbõù?%€ˆendstream endobj 161 0 obj << /Type /Page /Contents 162 0 R /Resources 160 0 R /MediaBox [0 0 612 792] /Parent 145 0 R >> endobj 58 0 obj << /D [161 0 R /XYZ 72 744.9066 null] >> endobj 163 0 obj << /D [161 0 R /XYZ 224.9351 343.6791 null] >> endobj 160 0 obj << /Font << /F26 6 0 R /F42 68 0 R /F32 19 0 R /F36 37 0 R /F43 71 0 R >> /ProcSet [ /PDF /Text ] >> endobj 166 0 obj << /Length 115 /Filter /FlateDecode >> stream xÚM¡Â` „ý=E%ˆ•¶û÷³Zs„ºej j(^Ÿ’Œ„œørâ¾S’ŒÒÙ¨+,59oxaœ„ n½ïèEXÝ6”ÚÿÊŠîÐ]Óä¾ù]§›Uröšˆç÷¨«šR,ãÁä8Å€kà\‚Àendstream endobj 165 0 obj << /Type /Page /Contents 166 0 R /Resources 164 0 R /MediaBox [0 0 612 792] /Parent 168 0 R >> endobj 167 0 obj << /D [165 0 R /XYZ 72 744.9066 null] >> endobj 164 0 obj << /Font << /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 171 0 obj << /Length 1762 /Filter /FlateDecode >> stream xÚ­XKÛ6¾ûWèVXqùÒ+·¤IŠ š"]lÐ$­¤]¹Ðõä8ûï;Ã!eY«6Aø r8üæÁ™áÐÂãð^,½XpÆU¬¼¼Yý½úø™{ÅŠ{oVœ¥i¤¼L8Ói"¼f¥£ÄMêÕfõûJXœ€‚)Ò‹íêúµŒ¼”¥|¶÷žNR‰4ô¢T2-dêm‹þówï^ýöòæÃúóöÍõk-=¡™Ò‘4;NÂæ@*qiø_ ãêÕv” ‚£0a"â?À‚)’³@j'±@…$,«h  ‹â81*½úš5ûº|¶”ÖþíZq¿«ïkÁý¬Ù”Ù!¯È:Ø8±.IDhA¤˜ÑKÆ@É}&Öàœû?wE¹dœø¿”mI˜Ã®k‰vèÝn^þJ£¬-hðá­¥lòªl2RAMO„ƒgcËTÉÛj×áý¾Ì­¡ü¼C©_H¸e8õE-÷ë0ô¯€"…?T%±ÃÞΨ€lÙ#ÿÜÜeXëÐ'Ä]QZ¸¡#¶,ÏËÞÒ¬Eñðe ¦)8b÷¥lí>'tŸ ÕJû-8íPPòú­‚¥a(Œõà w&ÒÿŬf0Ékû(%þn¦cáÊmO¹‘¼?­5wb~šbÑn:Ätì(Ãã¾ì/™‚w¨²övmI¸+%Ý®¨_Ü̸dÔHRêS[ºšn°;íÅýõ‘¦ÝÝ_Ћ£2òß>qâY=ì¹aÅ+½,™šÏÄÊËKh¢ Z*y|¨ÁnoÊ¡ê l<`WJõÌN£MË鶘ÒçRIxÙ +¸e\üà"Å™¡c‰‰,ÙÛÚ–š‡‘å3W |'£(´Ý<‘½ìÌZމú3„ÝaúSà6ý)3Óù §Sŧ•a8Ä‚{v :¨tg³<…ž)0šêɰÍåö!k›‰DSG§WloÛhÍ‹œ¢ p´±àåÁ|h=nƨIÛ 4¸?ÖµÕ´ˆÚVzÈ:ãÌ3R)–¤áÅv|ÂÚç1½EÿèíÀ„Óå³¶´Wóæ]~­jO¹h= õ}W×݉.~˜Be;õ4„ Lë€ Œ2úL² §ðö@ƒÿ¼¤ð†…3Xؾ?6¦)Rø=T=×.Á¼Ê¬^YMîÎ +÷®ÄÇŽÇÖ!-…׺ôšÅÐùÑŽ:6†ôàÃ8Ú:Îiïãb¦¾¼ ˆe_Cæ¹pq¬òCypA :À2Àþ§ 5ã|¿ã"¤¿i–nAü›fôô&è¸X*EìiÉ„T¢¥púüÊjÛ;endstream endobj 170 0 obj << /Type /Page /Contents 171 0 R /Resources 169 0 R /MediaBox [0 0 612 792] /Parent 168 0 R >> endobj 59 0 obj << /D [170 0 R /XYZ 72 744.9066 null] >> endobj 169 0 obj << /Font << /F26 6 0 R /F42 68 0 R /F36 37 0 R /F29 12 0 R /F14 22 0 R /F59 89 0 R /F43 71 0 R >> /ProcSet [ /PDF /Text ] >> endobj 174 0 obj << /Length 1858 /Filter /FlateDecode >> stream xÚÕX[ÓF~ϯˆÔœ ¾_úH Z ¤B ä8“‹oØaÿ}ÏÍ·¬wÙJ•ª>ìzæÌÌw.sn“§Ûգ瞻ŽTÞz{XÛ–¥\ÆA++Œ€¸ÿ`ü´1Ë2²¢®šŽÇÝQóàJ—ºI:½çiš'mËö;íÚͧí˵µ6mKÅ~Ü¡© Þò¾ÊMR¼ÓI“ßéæ[–êÏižé²›±DÇö•;`)?ˆm‚ú™–ÌqÍAù£p*ö•°„?£uS}¿FeÛ%eª—äÍ«”7ýr»Ô¯ª4éªæ£å[ðg/ÁŒ|p7ƒ+®‡mÛëZ_B9¶Ší0šj–6,?S®Ôg4úëI·Ý’ °t»>oùÜ]ŠÀyõºî²ªlg8HþŸeížêÍI7×3 €ÒU僻TOòüÂ]T½5 Ý«ý2ç¶ž1ÃkQ3 à àŒ_7Y鹿yÊ»E_ŸìzÀè<Ùf…~üàáp¾Vo Dñ&\þܶê±Á¯I—u»HÛdÃb4V :f}Е7Q@½ètñXâQùvìÞ.Ÿiöâ²Úf]N*=zîë2Ž`Æ1½XE®M×SžpÆù­7v|ËÐIº±}ãȳV§è3<©ü%ÀAZíe”ìªmßdzÎÐYp´ŠÞ8–ñ½Î“¬Ô{ÅbÍ¡q4aàG®ûï%.gL\—¦pÃÄ‚‹†ë+VŽŠ£(êçùêÝêÍhˆæò)ã™?¸PÌ #g4†Ü`«jQÿ£e9¹(Ȇ†AQMm–•°P$h¶%g7à乑3w÷ÿ¾îÝ>*§¹âVœ1ïÃoLÕ|cÓÔÆÛ刉9eÀ>ñ¾hˆÛ¶‡¼ç,KÝ ©çš¢Þdeqã,0"ã|̦pc‘qj9Tã>F"ŒYrWõePk@ç;å2‡g¸Ì]ÄŒ#™˜ØSÌöÄ$¶J÷„>€d>žk/J^éŽ$#ŒÒ¤ÕÇöú@Y`*‘Ó2"Ö:ÍÐ'{žØÀ”óçvŸ·UR?†h–œÕ2˜ÎuAY”Ž ­Dâ9ÆŸ§^²rI÷ªdQ£¦žÔ ì’pjržwH0$ðý!‰óQ‡9•V¤¥àíÓH׃pA!9œ)©1Còh)ÃðÍ‚Pò+‰‹‘° =¢w™¼P&“®`š»®ÉvXÒNÄ5ˆÉrnh‰!…8Ãw¯A¼êo`̓xÔÆÄˆ—åÔ$œ0U¬ׇ̼(a¿ ‚ˆüŠä ¿Âᤨ!{­!þŠ“-úúi2Ë&‚na´éCNŠGÍa<-½û‹±\N3í`×éi ð-öf¿¯tÝ?”Z š‡*p<Î}\“]ŸŠ@ƒ¸-†ŽÀW×¼D=P°efx's9×ò9tœ§¨äØHO˜ÌT~l¡Úýmšð¬ ïºê›ØÂXŠd¬Orü¢!àtxð(¾(µä /ÊþzƒScïÇëýjñ®oJ1¹À;'(iFžˆü,F¦lZÌ©nâ7=ƒEîç¤÷;âìdÅ’)uƶzƒý)—мgçû¿z2Þ«kx-Á’ÃgîÇ@üÆ|1Á$ö¼pR÷òmøÖU}Ê9Xz”Á¤ÀãYwœm¦½ÚœÅ9)»9‹S;€ŠÈ§æ†2‹1²å$l\(l@?ê¾cD2ŠÓûÆhÊÐQ~è„€† ¦™V˜¼¿cÛ¶`øÈ‚—Õïæ¢ÌègÍL±0S}²9Í Ð8ØÛÒFz¹áXÉ¡L@ŽðÖ¸ÞøT`|+t‚@LN#ìQ4®N¤1èé×#Ûw¡ûu½¹‰§2‡u=ó=ú¾€Â ôäÁA;¥JC§ýqϬT 4&ü²¨8@{r¾r¡rJòÀ©(µnºL_J6¾•'Æ @Zq{©Í¥N¢Ì¤(Bs51€ùŽ 6]ƒ!)qÁRIÉä,=›8¸£Ì äÑS*;õ¼€ª·Ôêyr¡SQ’<ë®yc¿4{ÉËRÙ7©]’åm! ÚÓnö“Âe+G]¾Cgí{Ê à{§ŸÜöîƒóæˆ|N0 ¯µç(Ûvø2¤Š|(ÿOêZCùDA£øUF§‡lñŒû§Ç|¹ï7®%…É2úôÜ«ó7zÇîendstream endobj 173 0 obj << /Type /Page /Contents 174 0 R /Resources 172 0 R /MediaBox [0 0 612 792] /Parent 168 0 R >> endobj 175 0 obj << /D [173 0 R /XYZ 72 744.9066 null] >> endobj 172 0 obj << /Font << /F43 71 0 R /F36 37 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 176 0 obj << /S /GoTo /D (page001) >> endobj 178 0 obj (1 Introduction) endobj 179 0 obj << /S /GoTo /D (page001) >> endobj 181 0 obj (1.1 Acronyms and Terminology) endobj 182 0 obj << /S /GoTo /D (page002) >> endobj 184 0 obj (1.2 Overview) endobj 185 0 obj << /S /GoTo /D (page002) >> endobj 187 0 obj (1.2.1 soap bindings) endobj 188 0 obj << /S /GoTo /D (page002) >> endobj 190 0 obj (1.2.2 python tools) endobj 191 0 obj << /S /GoTo /D (page002) >> endobj 193 0 obj (wsdl2py) endobj 194 0 obj << /S /GoTo /D (page002) >> endobj 196 0 obj (1.3 Not Covered) endobj 197 0 obj << /S /GoTo /D (page003) >> endobj 199 0 obj (1.4 References) endobj 200 0 obj << /S /GoTo /D (page005) >> endobj 202 0 obj (2 wsdl2py basics) endobj 203 0 obj << /S /GoTo /D (page005) >> endobj 205 0 obj (2.1 Modules) endobj 206 0 obj << /S /GoTo /D (page005) >> endobj 208 0 obj (2.1.1 client stub module) endobj 209 0 obj << /S /GoTo /D (page005) >> endobj 211 0 obj (classes) endobj 212 0 obj << /S /GoTo /D (page006) >> endobj 214 0 obj (2.1.2 types module) endobj 215 0 obj << /S /GoTo /D (page006) >> endobj 217 0 obj (classes) endobj 218 0 obj << /S /GoTo /D (page006) >> endobj 220 0 obj (helper functions) endobj 221 0 obj << /S /GoTo /D (page007) >> endobj 223 0 obj (2.1.3 service module) endobj 224 0 obj << /S /GoTo /D (page007) >> endobj 226 0 obj (example: DateService) endobj 227 0 obj << /S /GoTo /D (page008) >> endobj 229 0 obj (2.2 Generated TypeCodes) endobj 230 0 obj << /S /GoTo /D (page008) >> endobj 232 0 obj (2.2.1 special handling of instance attributes) endobj 233 0 obj << /S /GoTo /D (page008) >> endobj 235 0 obj (pyclass) endobj 236 0 obj << /S /GoTo /D (page009) >> endobj 238 0 obj (aname) endobj 239 0 obj << /S /GoTo /D (page009) >> endobj 241 0 obj (Attribute Declarations: attrs\unhbox \voidb@x \penalty \@M \hskip \z@skip \unhbox \voidb@x \kern .06em\vbox {\hrule width.3em}\discretionary {-}{}{}\penalty \@M \hskip \z@skip aname) endobj 242 0 obj << /S /GoTo /D (page009) >> endobj 244 0 obj (Mixed Text Content: mixed\unhbox \voidb@x \penalty \@M \hskip \z@skip \unhbox \voidb@x \kern .06em\vbox {\hrule width.3em}\discretionary {-}{}{}\penalty \@M \hskip \z@skip aname) endobj 245 0 obj << /S /GoTo /D (page009) >> endobj 247 0 obj (2.2.2 Metaclass Magic: pyclass\unhbox \voidb@x \penalty \@M \hskip \z@skip \unhbox \voidb@x \kern .06em\vbox {\hrule width.3em}\discretionary {-}{}{}\penalty \@M \hskip \z@skip type) endobj 248 0 obj << /S /GoTo /D (page010) >> endobj 250 0 obj (example) endobj 251 0 obj << /S /GoTo /D (page013) >> endobj 253 0 obj (3 Security) endobj 254 0 obj << /S /GoTo /D (page013) >> endobj 256 0 obj (3.1 HTTP Basic Authorization) endobj 257 0 obj << /S /GoTo /D (page013) >> endobj 259 0 obj (3.2 HTTP Digest Authorization) endobj 260 0 obj << /S /GoTo /D (page013) >> endobj 262 0 obj (3.3 Message Security) endobj 263 0 obj << /S /GoTo /D (page015) >> endobj 265 0 obj (4 SOAP Headers) endobj 266 0 obj << /S /GoTo /D (page017) >> endobj 268 0 obj (5 Type Substitution) endobj 269 0 obj << /S /GoTo /D (page019) >> endobj 271 0 obj (A wsdl2py scrpt) endobj 272 0 obj << /S /GoTo /D (page019) >> endobj 274 0 obj (A.1 Command Line Flags) endobj 275 0 obj << /S /GoTo /D (page019) >> endobj 277 0 obj (A.1.1 General Flags) endobj 278 0 obj << /S /GoTo /D (page019) >> endobj 280 0 obj (A.1.2 Typecode Extensions (Stable) ) endobj 281 0 obj << /S /GoTo /D (page019) >> endobj 283 0 obj (A.1.3 Development Extensions (Unstable) ) endobj 284 0 obj << /S /GoTo /D (page019) >> endobj 286 0 obj (A.1.4 Customizations (Unstable) ) endobj 287 0 obj << /S /GoTo /D (page021) >> endobj 289 0 obj (B Example: WolframSearch) endobj 290 0 obj << /S /GoTo /D (page021) >> endobj 292 0 obj (B.1 Code Generation from WSDL and XML Schema) endobj 293 0 obj << /S /GoTo /D (page021) >> endobj 295 0 obj (B.1.1 Example Use of Generated Code) endobj 298 0 obj << /Length 813 /Filter /FlateDecode >> stream xÚ}UKä4¾çWä¶Ž4ñúçÄ´!¶ Ò²OâÞòš8MÓÿž²Ëi¦{f¹ÄUåòW¯ÏÎý>zûNæqE«\äñþ".8£L2Þ7É/cm’TdŒ¬­8YYót4vÅn´«~œt­ó4{½šæÎé’Ôºï»ñó«`ô†(Ö,w·PFÛs¢¡I*YA~³/qæi ÙÌK’)2ýsÆSváÑÎ02˜µš‹Û§ýû˜Å)ç´RŠûê5¦.¹€2Wƒº…ª6›Ë â}3n†K/@›¸bHæ3„ ®u¯­Ea瀞pbÆk|~·×ãÖó¼¥fo=¶ÏúpߟtNö×ÈvY?þiêõºÂ÷£Ö.´bäÑàz´>Hë„+t `g‚{mpqŽ}Øðýyéè XH2yû.“q 4Í3GSQR( ‹ST)‘«‹¯ gŒ|‹#}˜úâ‡ÑKÝþÁ[Ì,Q¯ÈŸ^`eF3–+û£ÙX òÉ­ÖamõºIÁ´µsm° ÆZpF>»q¸²(.¾^Ío˜4°ÛÏÚII#‚š®Öåœk§¶üða¼9—0Þ.œYVoÆ1 šÞ éîµðáÙ´Nm‡QÂl¦qÕÀ÷›Ú«„nç¼Óp\¾|ì=þÂîIFΧɻ7wvü7GQJª¤, WÃhN+\º—ó–Š–¹RÁí5ž¥¢â”)QlL˼ë¼Í‘coX¨ì»Á|õæGGŠý£èä¶/MfÐä²ÂÈ”~™jccr>¦\òÌß9\ƒ¼t²MDßcäÿSf·½¸W‡22Lí½ÚvoƒæÞ°›È×o7u#À :}í)Y»iôUGßï#»,æîï£2ÊrXë!zŠ>~bq±ø}Ĩ¬JŸ@a”W•ˆ‡(ËËMé£]ôë&…óé3 {÷›7¿¹LPβü>ŒPîîäÛ©q|+Jòƒ¡ÙÀ9íÒEÛa™”vßý„’~ÿ9Xvuk ²ðÇr«ô_i]ð8endstream endobj 297 0 obj << /Type /Page /Contents 298 0 R /Resources 296 0 R /MediaBox [0 0 612 792] /Parent 168 0 R >> endobj 299 0 obj << /D [297 0 R /XYZ 72 744.9066 null] >> endobj 296 0 obj << /Font << /F36 37 0 R /F43 71 0 R /F26 6 0 R >> /ProcSet [ /PDF /Text ] >> endobj 300 0 obj << /Type /Encoding /Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/notequal/infinity/lessequal/greaterequal/partialdiff/summation/product/pi/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro/integral/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/Omega/radical/approxequal 144/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/Delta/lozenge/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 113 0 obj << /Length1 1642 /Length2 6327 /Length3 532 /Length 7176 /Filter /FlateDecode >> stream xÚíwgT“í²6½w‘Ž„*½w¤#½I/RBI AŠt¤7éUªt¤* Ò¤ÒA¤H/R)ÒNôýöÞg½ß9ÎÙ¿¾õe­d=÷\3×ÌÜ×<³V8Y ”á`u8 % "(, Ї¸;x!àîúp]=°#D „И'§ª'ˆ‚Àaj@X`v¨AQQ€ˆŒŒ '@Žðõ„8» Ü¦Fæ<||üÿ²üv8øþAG"!Î0úÁ …#ÜÁ0šâh P.`€ ¨Zjék¸5ôM`ØÝ„¡—èB@`Ìp‚{  8Ìò»5¤ šK 0‚û€Àˆß?öt‡ ‘èg pöÂPè;@Áêåø»´Ý þ§ „'íáŽÆÐd†p$ ò„ PtVC5õ¿êD¹Q¿s#!hwB{:ÂA^¿[úƒ¡iÐ( !(°êw.0À‚D@¾èÜh2„'äO^HÌù_ð<ÁÎ@OG(‰DÓ ¹ßοúü§îÔ÷O4ü×?k€ `¨“ ‘ˆ(:'…Îí  ýž-˜ "ü—ÝÑ ñÌìù炸Ï º #õ8‚ˆ„ôá(tJ÷ÿLeÁŸÈÿ‰ÿ-ÿ[äý߉ûwþÓKü¿}ŸÿN­î…êÝÑðמ  @ï€.à÷²ñrüÞ7Ðÿ t‡@}ÿ»Ø¿{›ƒÿ*Zuü;ö¿2Ì­Ž€ˆ„ Ø_fRâv4„ @.' }qì¦0G°'£þs·è aá¿a&.ì·A`˜ãß@kö§|!sUK-C¾ÿfÓþq6DOÊÄüŸLæzpÇ~S©¨À}~¢èRÄDÅ22’Iñ€ÿ"ë‘õ€(OˆÀZXPXX€þýÇ÷_'›¿Ñ<„àŽ¿GÈ„9¢§îŸ†ß0ÈËÓ-öŸE€nüç?óû€ADsÓp\˜kFv&ªŽ6¿oXͺ»K»/QÖ`R\Tï|–ñ|Y¦Òþª6\°ñ“ìM«ïÔâzM›w} ‹z¿3 ¼ÿ’)€ç}!åW®v)¾õ!Û2ÒÌ]óX¿ƒIÝ%+Ia³õ•áGF¶¥WxÌŸÚÅ< Îx‚ؽ ƒ¨9Nd ôú„»o)1¨êŠvv¹R¶ÎNï÷|ìïëí<Â}¿ÆÈ——@È)çCÊä‘ǨheZéÏlƒäÿ5a¼Z?Û½›JoIÏ¥«Î¶Ê@?ÇPuÕa©éHÿñ= X¤gƺ—.nËyž%ø`Á1U9Áo£?ÛKkã¯D £y‡e­d.y^ü.N ñ"Þ˜¯9BUyº€¿ È Ê†¾ØcPªÙm„Èž '‹]‹ýq¡á´”ú ?Áõ¤l ŒLî˜!ç|Ñ<¦ï#?ôÞmÍKö± c³g"+Ó›ún>L×BÅ‘ØyÁºê–FE‡µ]eºÉÞƒä\Ç{›df¸O]¿ž¶6Mœêô€$Î+y`D†¼Œ‘AF" àŒàÏIl>‘¤Ý.I·’ú^3œiP@è{/Ï˜Æø) ¼î´QšoØ^™ýPhý–6Éi2MÓì–ÿ§ž Sd?}@AÀ"¿¿ºûŽ¢e³ñumS=¥S† —×9ÚÿOxéed×gøçç&„¤¯AM6é‹äLxËLÂÜ2FBç[i’ ÷8óŸî¯7ü0‘ †Å¯¸Ùªï=sXoä‰s,˜†$‰&ÎdôŒ¾ÑÊMÃP¥lDœêžHqpµD?ïýöFžÇû*7JþJÀJ%¨'Shš¤Ïó—¡ „N‡µO™) $³9çøvÊ‚’ä#”QËþ,aç—yWØ@‰Æ1ieî/%ÚX…íL¶Úâ󤙤û ¦/.ËÈÛGË$ÀÏu¿É”4Fèk5í¿ß™-Jëáhœ kÛ‹®ÊY¤‰ùgtSd%uäÙW”k[ü¾ï3Ü9"øì¶ÿèD ~·-"–(1Aá"…À >;(ï+z‚Å ÅË=XÁl¨Õ½Ò¶“÷û`)†$Œ”û~3N½Ž¬¸Võ¨~àßZ}Âóªð¾Z·Ø!öh6 ÑÇ#½§t~‘.‹+Æé÷$v^‚k±äœ¥@ I¥A¡²$Ï®ñ<ˆDaQ·œ7õ⣰1v¢1d¥¢kÏ™dZYÙ}¸°¡ë†DÔÞ¾F‡k¹­[ˆ* Ö‰ uªMƾšùæ¾éÑȵÊÜR•v?îÈ=ÿæë÷†¿À ;’|³_|‹}Ç;ñƒñ‰ãÎe†þœ±í®!Ú÷½4UOÃyQ6¾¢Ä/9pÝ+™õ÷*pƒ3^”Nü÷¯6e5|– ’ºÇDU¤ðYM(¶ÞYÌ\MV=M‡n7Æ¥©íêý~ºë/”¼ÔJ{´ÌË}²³]º–e¯ÜŽÞQŒ_cPß0$3‘s¯%òÜæû:4&”Ø!/Ó4›\4w¶rN]Æ–_.ùuÒ ý¢0}ÙÉbÜÕ„¸® 6Œ2!&Ö Ð?¹E•ùsýœÐóŒÞó*næ÷¢ë É‚Ê'ñl{ªø Í÷®PJõÁ{B"³üà…™aïJQñ¦_•æ¤Ô7¸OW÷ø¿Lh÷¦À5ÛÒj$JÛˆ-ù&ž4¹nåܸrÛß5Æ Ç<ί©+_èËhµ½FªåÙ x3:Ûg,VãßyÜŽha–ŸíðÿU &h$ÝEœqQ¤œ¿Z竸çþåK»´ f£Bv(Û'ŒÌŸ 9*Ò'ô.¯Þg#ü„8ujC“õi&iýdq"fðlŸ4ÜbfZ]" o#„î6¬¬[}àwƒ_š×¶R§~ÈwâïÆðÀ‹ ´múîMå63ºÌ-LU|²ëÉ4ÔŒrÞœ\´ûÈÿɼcòå(K—iÖËណwgý CA3?Œ×úê/ƒèT³ |^Ð[àWלºÀô6M´Rÿì{‘þ´Bl£"øc‚!Ö¡€‚Ÿhü`ÎQIÎ3—Û¤/é ‹¦g˜¥ò¡½g$‚Fw4ó )¼ŠÚ{žK„à u¹¿ØÀÒ¤1Y—Š»(yßxx6û£Z´]Í&æ¦j¸lv"CõÇ6{$]ÿ ImN}¿Ç­t±™ÆsoM2}àn¥‘ºJ³(®è^¿I8™ÙÑ£äÒQÛ’ÇT¬9ч9Ïvà3»Ÿs;œ˜ý½ÍÅ+·ÈF…l`w>‘<"ô(E^‘S׿ç²Et¼,+‡µßð¼Oiûøù*Oqp½×~òêñ)taÂNèóŽýݹ9«M¶À²õK¡'ßÂ4vUH©FΔ¯î‡p>¬©’>büñ•ÛAR2@qà~Tߌ`lQ~è¸Þì4ªÜ'yÙÓŸÕd¥  ŸÁ¤«âTGŠBoè·²´ºc@VÜ †1ãÃÛѽ‹êÑçÂŒ<¹„Iø.¶Ôôv™?‡“WIÁO«Z£”a®å¿RÝÌ9‰lêzAÛøQß²I[™)æ‹$0Ö‹ØCc••| êó4)äšÊJX}¹^Ms™&d|Æã<ãŸkjbên,é<·0aŽ‹Ç¸Köeå/2){ nwµìðC/¾y‹E§‹õŸ\l} ñ…k ¨¯AÛÚ¼09 (EÝSuñ Œ¿ƒ/'|%†Œ¾UC2º·`<ÑúÜ„{œ®,áî¤#Y1öÞàÝcÂÚ°WÛ½ø¬FPkáeqö . uÏâÐ[ÖÒÏò›(}‚3½~F³f½HWÍ© ÚìÖúÐ>qÎkb²G§/²=Ä ®•Ö8Jóõê‹÷ÌWš¥«O¯µ6JäNb¡¼H|gÆ´Ã_g¢&båhW)Hç³ÞǧcHÄž&™t|v†œîjË) >On?žäÝr-d«úA|Y'diÒÓ¹wP­B-“ùÕey~ÅÊ·™ž„…D¯¸4WÂû—ƒëbx!‹¾åfÔ¢÷Âw}Ë®›Äòþ©Ôɺ~ jŽ Ï3y}^Žêó4U“ò*ƒíI =[…p·¦w(¿xz}:)@L‡ÃæÇBKOl¶;îÿ½íã»4'ˆ„Nq“ ‹¥1—'4¼ñ‹5ËUûË•âfªãäÇuw9ùi%1éq´“&ÂöÒÚé5ŸçÀ¤É¡ /µMûS’«½­ —‡-Ø`¦E>½!M¸Þ=¯§œ“†‘¯ó”žÄÇ_”lj 7ÈÌÛ*-±?wX³…d±‘ªûEÈöo OŒ{ö±2Š•çö®¸|/œ föI$G¨ßæðæ–Õ¬œŠSp ‰? 4ùÈ ) YU|ìŽYö]ÅãÕ¸(ÐÛø€ÂÉ<î-&!p·32³Ú «C5Hë«…GJrWjÊà(g~‘È«à¹=ã‚âÔ}¯—.…Ìò¦2+&A·%Oi™ï|glaÖ±3Z©ò.3e§3Ö~»¶vjŸÊJŸV0iy¾vÔ|I[—~ë¢h­ùôsÞ©{ÉfРðQÐùRݧð]®ŽX}¡GÏKU Ü…™[À 9faVSš^â5ÚŽfŠè'‹³Öté=æêE[àöïñŒ#ÂVV£”*Ò>Îfu$$ûâp ß¼¹×ö±é w<œjîˆC%{Û ØâWN}~´vìŠ<={÷°öf­P˜L¿ß|ÜÂcõ6¦hU™üúVËÜ6ýj[:B^ƒ®bœm]_=3œqd8¢·4d%0Lžý‡„ïê—(-Ì=_¹½ªy`H;ðü®aGßöw=a'ýãLvþ>ß䉑Ø T®ýÐ|ÛÅÝû€0)\…ÀüÙþ¯°¶øÑH•rÞê·²Ó b2¶ÍȯU7›‘± À»®yÄ5cmáèb4À 8sîx;)ª–ÿX&CÌ ‘Éw^jñ[≠µj§À,€àž4ë®ÙIë<¢ô‡¨@LðQ…•Ω5yÙXçjD2áùÂä–Æüê„wöGŸX(µwí£H–~#ë|./¿QŸÓ¸M9üid“r‡Úä[FPðƒ3&•Q—ì³_ü¯Z´oIs¾‰Àw^WW;ìKýSÍ[›|ÑN*ˆ(˜if}ÄŸqWº„Õ?]Ô¬OLØv $¡l+`qS»¡rz|—cq½ÃõÛ vòýì4²¢iáÐFtE²ÕÊOÚñÉ}-L5Ù½ñ¶Ó×·Î) ‡gXüúq—G3OA¨ô@èô<Á=R£•Wcï•æ"IL›3=ðoäë¶XE?o'w‹™RŒûÓöM¨5[\%>.LÄÊR￳ʙABk ÈT Ù©½¡õî>í².™¬šM]þcY±*W\æA¼ôÓòß|óÊÃÇØžp#'u×€7¨&³¾¾MùF†)Îyd‚Ή5ë‡È}þO"º—̬3¥v®­ë¶YÏÎ2œ¾³>¾âð"oNgl@ªFB™f† “Ö\B“öîn(ôHkÑ<äôêo8›Ž1ûú¨æÃ„²§êƒ>£ØKGjI’ŽïoËê^}Έ=»ÂµáFnúU×JÄûÌØúnð߈Zû?ΊÌ_ýåt¨A%×JDoñ%DìpA.GwéË!t±`ãšp qÐLÉ^^<5Ù¹|}”|ôå4:)nuçÉsÑ@gʅʳ9Úsþ >âêÉ|\ ÂôÄVËÅ‚=¿rên‚÷Äöˆv§žQmÕI]1'»ÄozÌeOÜ™p˜¢û<Lu‹$>NuOòÙ|ô|9½j‡£„>‚o{1¢LÀ?tª–£jKñ¨Ì€Å1äëcµ_2)âçÞéHÉ ùÚ%-s‡*sÿ ,R¡2Ï´ ¾IÊËìâ>Ö¤§{¼!ÎÚE/D«»Í·Ÿ‘¢\^„ié¿ÇÎ586&à|edcWÆÌ²=5úa6v™®¼F Ç·“Œ™á:œ3Ì0£ÛG®«–Þ¬éQÊN$ ø¡–E™ž—³Å–®ØÞ`ùšùÑy?©C*ÛË&™[ÒÈöù¼HDÀP+¼óþ³ý§óÉ[úô>#ý<ûo±·šÍJo[bd4¬™\îš< n¹]2~§SÈG«ºÔô¤ß½y70úXoÊý̈ÍM!¢—Ná’^¤'ÇÄ{h1é?`vJè1k3ð^OÂõY˜¬Ô!=Vt;ùBE{‘fœë›ÃÂWøÂ9'§»8At°z>¢Yç ö’ˆ0'âzRVJ¿“âNì sÆé[·‚˜ÏÉÚîò®Òlõ8Ð?µ2T—ì>¡ZV·e¨¡ÝÔ!®±áд!Q´Ú Ozù!ƒE.úiMH³#îÑ –^ÔŠù Óá8X6¬¨œWÛN·Ññ”T•É~jwÕðK뜱´žõWã­ûÁ®BÎú'I§CÓÍËÌ„¦Ýš¡ Øñ¥÷¿;‚C;˜Š¼•±·Ùh豫ùËtljËH¤³_ùÆæw¦ê±‰3p†ýLU–¨Õá'« .[GÕº.÷S䎫íRRršÕ`Æ2ˆ¦ËÈbìD1‹*q›I]:õÕÖ+‘ùiàÆÏ™ÑË–Ÿ]–îƒ[=ÿ†¢µ1`¯•ZXÑ„HÝ„«1lwÅc—Bx ËUñ¢ìnë%Mê"½Sâ®ä?´WÁÇðDöÃÍE¿ ¸~ee«âóÁ~Ì5!SÜâ.µHØwB•ŸGìSÔj§ÓË:Uç¿úo{¾ÅçIv´Lí¼hI)«–§½È‡ô]ÖÍ“KˆÚÒaþôŒ—¸?¾émØë¸•ØŒ1ý_ ÙcY2ÒTË×Ì÷ˆØïŸÍ½gôZz  ÓFͱµ’`M-+»-¯Å6Yïöºpf¿àßQ;™¥&k›™ÙI £à>»*HíNžlÚÓ¯môWiÏ=¹ëü`aÛÊÙeÒ_ØÖ¤e¦>YûP/’ óÍ}ü9ßdÉfOâЙ‘–{r:Ïi8ÕÙý™)Iµ) I¨Žïö,ÛÇÜØ'>I صZx •Y+â¿_¢Ä~VRzI+ð–AϘq·"ÈÏØôô-,¿¦õÒjW5ZªÛÆî«‹kÏÈOá÷ö¸©0hO’’Pž²[Ñuû^kÞ¾TÀ›;¿J’×ß[¾²­EÓ½kÉQãŸ&® UDŽÆ[&x³Èw÷dPÒÝ$¼`žI§ÛJˆÅ³L§¾¡ÙôÑl¬óÁíæWsò·^ÒVþB²q©–X­³Í5s#v³!˜D¡¡Ô×S À_ñ ‡Â‡¢¦:æ¢T]g“ø¸ï-ìÊà{¢–æí‚ÜÆkƒ->ÂYC"ªR~øË3|•ÿüÚyKC¸xª*ì„x”4e:Ò2…É¿ \¹»QyÞy_9»wù"ôÍ+Ü"—LÒÚ½Ó7ÂÖF-<½ØÆŽÇT9Aw:T›ï’?Ê©Y' 9ÖAr‹B¤¯îÒ]µv¿&›u¬)Žß:GH“žß}Tù>ïy›UZÆéÛ¯ ÖÜGu9P‰Œ†ÖÛŸæVX’¸! ÉÙíE.é“’óï/Þ“d¡%±çŸœ­ª¼UO‰ÀŒí¿nìg `ñ5Ãcê@XÒÑÝàs:³<’b øN„“q‘Ø8–¢è\;|2òa›gX]´ûaˆ«{³k?fGøÒVìÅÍ“"yA3ŧYÙ{B#O+ÔÍl‚tyÞ¬¿PiW?‹"” y€qÑòsáQ–˜® ï­ÂF“šp5™Hòy-åÛ‡ÙÆá©×a}8”®˜Û2- X­\ÇYRø 8Ë!r?–óæ1X24(¿Ò@n[×]}4UÜ‚RŠ£mÄÈJ¾f(iH}Û·L±¥¢¿>ž 4˜¦"ܪngîKÌàz¯™pMGëÕb[>%{NÆáÁ(P™–hNââK²|¬‰ÇWaçð©¹ÿ-V0%ÆO‚:>jÒÝVÑï6öb×abÈ*|Ã$LMq ®èu'öôC-s¹ù>ÍüóŸÝ:f¢ÂúÒÁÅL/ýŽ?å¼bqð®˜Ò‹5”ÁcVÅIXáPeõ\{cP¹÷©áÛîçó~;WkDtœy×Þ‹®™©¯Evöj‰Ux¥ß)„mB­z"û5ºgQŸÇT¾˜”¨Åjˆ9ò…œU=1Ó)Ä<:«4¡m"xù"½àškÂWÅÇ:'/ø6å–q–Cø£®Š˜>[’ïYF‚ï^á¯X Øõ?è¤<õ} Џpá¢ËW³N+7šñb¼ŸÊ.ü¿üý‚ÿ'@P0ÐwzºýÝÙ`endstream endobj 114 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 45 /LastChar 117 /Widths 301 0 R /BaseFont /BWCYIP+NimbusRomNo9L-MediItal /FontDescriptor 112 0 R >> endobj 112 0 obj << /Ascent 688 /CapHeight 688 /Descent -209 /FontName /BWCYIP+NimbusRomNo9L-MediItal /ItalicAngle -15.3 /StemV 120 /XHeight 462 /FontBBox [-200 -324 996 964] /Flags 4 /CharSet (/hyphen/D/H/R/c/e/f/l/p/q/s/t/u) /FontFile 113 0 R >> endobj 301 0 obj [333 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 722 0 0 0 778 0 0 0 0 0 0 0 0 0 667 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 0 444 333 0 0 0 0 0 278 0 0 0 500 500 0 389 278 556 ] endobj 88 0 obj << /Length1 1630 /Length2 10401 /Length3 532 /Length 11263 /Filter /FlateDecode >> stream xÚíveP\í–.œ Á4Ü]‚;ÁݵFh\B°àîÒw·Ü=hÐ Áà—|ßœ9Sçί™óëÖÝU½k¿Kž%ÏzW5 …Š:³˜…£PÚÑÂÌÎÂ&PÙ›¹º(::|`VZ¹*›Ù/ nT g )äè i  ´I 9€ƒÀÎÏÏJp{:ƒ¬¬!:M5mzFF¦Jþ˜Ì<ÿ¡yñtY9Þ½|¸íÁö@È ÄÿØQ@¬K ¡¬¢+§$ “QÒȀΦv×—RÌ@æ@ =ÀÒÑ`÷÷`îè`úSš Ë –˜ Ààšƒ^Ü€æ@ð t¶¹¸¼|@.+gSÈK Žƒ¹«ÅŸ^ä–Ž%vv|±°ѽ€©8º@\ÌA`à%ªŠ¤ôßyB¬M!b»€^ÔGËK Gs×?%ý¥{yÑBLA.Ðò'–`rÛ™z¾Ä~;ƒþJÃÕä`õÏ ˜Î@+Sg ; ‹Ë Ì öŸîü³NÀ©Þ ¶óüËÛñ/«ÿÌqÚY² ²s¼Ä4‡¼Ä¶9 ²þ9KG;Ûßr Wð?tn@ç¿D÷gfè_’0µpt°óX-QY•!/!tÿ3–Yþ}$ÿ(þ·üo¡÷Gî¿rô_.ñÿö>ÿ+´´«’©ýËü½d/[ÆððgÏØ™:þì'Wàÿåfj²óüoÿÕPøw²ÿ÷¯j9ˆéKSĬ^ˆafç`aû[ r‘y-T@sk€¥©ÝKÏþ’k:Xí@Ànÿjë‹Û¿è4¬Aæ¶Hàþ[t°ø×ô_èú+yV5q- 1 ÆÿnÃþe©ò2  O0ða´-þóðG\ÜÑàÍÌÃ`æàäðòrøØÙ}ÿ›ˆÁ°ÿó¬h qyôÙXØØØ/ïüþy2ü)sG‹?“£1u°x¶ÿüQ›»:;¿pü×ý)úç¿Æôš£.Ì:š Ù¤f¤Aª ²ûG%õ»;ÙáûƒÁEuù¹þ•ŽSC×øËLª‚Yê¿ <5{þØ?nÊ3l v¾±£íHç¼õ¥¢ïÊÅ^~×Â˸ÀjT„‘v é}2óaA‡MkëרªšQáÃ+Òï-œÎÈ'×ôþTn¹þxÔW`L?ó”ÚüV¬zœê¼ýƒw »×W´½Cý}§ˆ]›$ŒÐA7ŒwþNP=Í2ï0Æ ¸š-òè®ølSËcéÛ¤ 7cŸRgJ¿¨ÚkjœñøµB}2xá “ÚÔv .³lð[2ÅÎë¼z×i¾x¿µÁûÝhÇ»Ë(ºõ½DQªäY„Þ7åYy}‘à2«îò1ãѪÒײaG¸!Y’àO@¢ êúwx‡ÛÌÅ›axºNcýƒ¶ihW/aÀº?¨&Âz…ö¢{¿—,bÎq{EÛ³ZŠfWÔŒ3ÔNàßùØò•ê)G"å¡0±•â*Ê!lQªk¼ñÃye?•;i´àY¼z ¼MÚ©™À‚ô=©æ/IjÑ–’¬Ìk,2‘½±œ×㦫’²7—\ܧŒiø‚øè/êʆpp±ÅÐ̃ãä«5©çÜ~«´¬’„ÕtxrŠÐ¿MÝOû˜Z§MqE¿iÙûíÀ~0ûQÜAÑ~ UCì|e—I” ]"yêz{ÏOSö€)oR¸Š6$®¦Ësg© 4ójã<·^û÷Ü ây î8Ï-ùÕªÏmøÁ+é@ö¤æ¬ë±ç¦·6Âf`dZlþ!§*=î3kž‰E*ãVÅ*9$ÑnÆã€ :—zŽÍºÐ (’gG¾»3HãÚî½ï<ÒONKÓü'róckEÚ÷SüÄÿÉÞ‰£Y€cP(dN´R“•TQ¾™±­R ´A7Ì÷õ¬p¦lßßVã¿[˜#†ƇcÁ3hýì.âB8³°#ÂâætÆßó¥Øû˜¤K5JŒƒ• Úºî¢l£”óó×Ë4虩–Ä xl“ü…i`CzÜ Qj¨Î%óåU¦7aIQü˜²‡Ýö z¿n Lîuí£¶Â­†˜.½ÆLÄm€?ÉÑ”óÿ%ÈûÔóþ¼Vd ã(o¯‹?}f¤ìrfoÅཎæøÍ·ŸDÔC“+ÍZ“J,\ÇÒ°SíÝ#|mpUÏ|Ñ Iàï•Å©ó£ ²î#N0 SJG ‰àîįÓt>·Ññ:›}.6éæË4åЧÚ5&ÓØú³Æw¯s}Üŧ®F½"&ÞbÛä”DRóYÍß½}̉ p)kª?4JE¬šŒºtd¯U÷GQ³Å+Ù ¡õûhÄ óœŸt¤Ñ«8¥Ášà0°Ȯm_IJ¹sš] àb§ó¯†…Thûþô“‹NEoý–àšÕÜéSþ>xš* ÍÛÔƒžC­á©NK*Ð]T£ÖÚ˜´¿¢àµ—-.…“˜1 èù¡é¼*ü¤mô…ŸQͽÇTí̆<#RÝ¿õô0³'G„ÐÇ»cFÙ;Í7ÂS+ÉPª½‹ ÿf½ATë}gºÙY14(YÑÚ„9~ïä7Âê1laòTT>ÐÆ?ÝÈdª0ÔfAP?&Ã’fLšÀtqöÎQãÓˆý˜úÅÞ†mâ} £Ô_xטjkoóÈŒ¡lS4Ûáf¬užSi@ Sñµçrœ@ ÁèðgLÉÜ¢N˸›)¨5áK寖g=çåJ„òb)ƺ)9¼/jñê;Ç‚9ÚkM´"«Ù¼¢2Žº¢ût¢Œ ,8l¼ÏÉF÷}eÉ¡ˆÒ¹Ò4\'x=G‡ÑU¿³¥«?6ÜÒCýQ|7ÉM ÃÑ”ŒŠ†®1‚“3.°=(ËNÝQÒ¶Â÷Ö¶G>z7ň/EÎïë1-âÖÈr;¢tÇ:‡A»o.3×ãu>O6ÔÓÖ~Lžçd¥ô⣣æ»r½¾+¾c‰G™§v¦G—á:2§RÉ™M'žÖ:Ò6¨ÿÕª1RGϽÏÅÈB£¡Hù0n¯ÈN$Ô? þQÔhkXF»¼þ$Vùé–;Iþ>c G¬¦5˜hw%×FÐáûòû„¢?D{%®£9Ùj¤>Oñø1!l†~…zˈ‹ñµ É_IQ$È”©é×þäçKúu€–ÝGæ³|c<µÁ°€fM3 ¡×z¯ŽÁ¡:~Ié\nÒÈaK¬|晨6ÐÞû¸§+Ëê¾Pxé2ÐÄÌÚ›h™¿õ»ct%hµà¼h;ôœ†š9Ûˆ½­ÿqZ¢Þ\«*Dw¬'1XàG懭4]MSè¦0=žR¯Ÿµèzû©š>F-8»Fû§‰áj!ð{ÂT%fsÂ~çùQU·É<Ç;‚é ¦N™û ×'¸¹ú ”_¿«­ÅÓÂçíå4)VôÒ™²ž1ñ‘7ÿ°¼f¹hŽëÉl 6>Â9äúYe‰Cá79BuåYd¦¼4^šY¤0,p u«Ê›{ò ÿcªñ¡5 ¢6qL¦0è9^2BüPîïZ Àß³Ô°²yûúÍü`)…†q›¨^ÄÔWûƒìýrP?¸|ù™÷ˆŸº­•nèü¾H"ÚÈ´tT\'kza>ÆŒB‰L+ÇqGÊ"Eä¢P7ØsWng6:m{+npÐjÔê*ÞÊh€l©²pôºR@&hB¹ò¿ƒv4ÃÝðåÄË¿O¸ÏGó AêºîⲩrÏÆ½Þ|#\åt/)̧Xö $?šÕï…¯š(É!¾šaF#D ô&' BÓ:˜ò9ú6ÔB[]Éþ$ouse¨î„¼·Uw OÜsRÚDU4øfÆ+CdµD82þšFÍÏám£L¸l¸ó÷.iû•’Jë/iØ5`&9cû= ðãî¬s#uVüýäY4b¡s(([6-&÷† zª7fó8Êvƒ\ÎLóeì€ü;mÖR¸ÀÀùÇÃy&¦ÁuHÁ¦¼bøJŽQŠc§´«ß3ùé%ë ¢`&õ€¦fWSŸõ%ÃÑæð×Üã¯úÛR˜{Ÿ¯ ^Vìeet`Ë(ðGšÎÄÏûŠîYvzð‘ì·šÕUõƒ÷Ƴ;§A>úÄÅ /ôD¥¤ Á§:1]ÆÉ)$úôÛ]km9q‡ì"7gXlªÞ±Ç1=%ì "y¦µœ­, ‚œÞDTç€'p{]ïØ5Ÿæ¦é<™ó=^oIDyŸllâ[Ýp‡÷Oôy|‚Š•&³ˆ_®ßB¢¦òo×”ú×O…yœâ4X ¡íâ0BØð>¾Ôjßõx6\pΓgñï\ù7‡¬õ=±©Hé`°™ÓLêXdp¤ÅÝ;?:vš¯<%¿@îÑW«Ã„KèˆûÔ¿’x¦îŸ¥yŸCû] Î4&Ÿ.D£âw$j?ÂQQè`ƒ-FŸí ý˜>¦z“dÛçfŒÖO*Y%eƒA,8bGq9ßÈai4öG/żg†`çuì³®˜\,Ãõeg?8=&ëè¯Òh NMÐHí‡eµvëöÛ°±ÞˆŒQáÌTÔ$±ô^ Ø ÕŠK»Õ™ï8Š•qóBB7ΪV $jñ»ÉJ3-óaŸÂ$C‡Èí?.ëÕJú¼·ŠˆbØ×¿Ò1¹Ä´3š‚È XÙQˆè?5ë=ØÌà@èMN›ö_/áÐõçxÈ­÷Hô¥¦˜¤Mê«F±ÛL\vöEÈ/‡t¨sÓÞ® Þ¼ lFñÁ´Ñ*z£ô¶³?ñ':Q«ÊjyK¯ØØ“™u­Å7î´=³ß[{Gà«$­Ã“÷uœ „åÛïž=á•Jyz¨%¯<ì„Þ ½_H>宦Þ9P7Dù]ÏÔP†¸44£¨¥­Ø‚*>t•I'>6P+r°Ý8¹Íè¦ïžq  ˜G³Pˆ«6Q3A¹NZZ‘4„¢ôYÀ8ɪ&®i|>÷ç—ûÊñL}ÜÕq›ÚVyS”ì—8RvséYª.=·KZ­0ÐÏ&VŽ*¡ k#RKò+IH¸ µ 9|ÐU³­7±7½¨cç²HaJÝÒØìhaÐ ñ “ h$¬ ‰×˜c1Œ¢xLhÇŸkÈ„¾šÔ’Ìï©z­‘=B ª|Aóá@Ë‘8wÌ1à íP½;ÇióM,}ÂÒŸã«m™ ” ® Ý”gÚ¿à…{©>§*¬z2öVO$«6<`Â*!AÁ¨4# R*¤ÇŒçÇ&×ÊÌÞæþà‰ ,k³+r)¸|æäQ³}<×y†qûçé[Éè²r2ßÇy®lŒ&ûoUÊÌ$nË‚¸=¾Ì).¯’aÖa:¾Wüê9}'*¼Éí%Žï HíÏͼäàRÀë20b[ÕÁqC<‡ aiiß5fÚ0·¢¬ãñ!âÈÁš)¶ï¿8¼‹EzŒ¸@e@»æ{MqöJÒmû!E— ðĉ¨»·¬8|ºcÀÌÉVñèÌ. zw2ømaQo¡Ð†c^%[`ÓŠØ-kÐ8–IfY¯!,٣صÆg:+,!ðÉÃäIüKyp¶º|NH*«Ì¢Lú¡Õ9uÎJ8ýÉ–¥•®0x(+Ôžï·] 9bÄDKu­úÞDµ'Qä`—$¶ž+dh7äyü Ko¥ŠîÆ:T!¦ždê(OÓX‰@ªÏ•šÂÕLdIÈy¬Ç—°Zš±7U†¨P$á„"pØ¥: n$Awß2ZZð||áâUı:Bݱ;äb9ÂÛ\‘Ò˾½[—¼ &ô{TG×—ð£ÝÚäFæyõ (ñ›XÜÊ€Mô†=NN7šAV€AŒ;?¸õ|鹫 ¼ýSÿ¦P¹mg¤KmÃÇÀr!Š‹ã"ë„L CKØ)éBbÿÆ]n²ñƒš_l­ T¨.uØ"6´ß×Xn4éü a+ìð›í»áKÛ?ÿ$è¸so¥ñªto$y×>Áš-›‘âñ¦äŠ÷ XDÆ9?rçjTÀÏÒ…ê&÷Õ¨‰¹€È†íÊ Ôõá`à¿é¬·f‡cÂ6ký‰”þ´ßzX^Œ ÷7ŠæK´*:›ˆ'jä„ÝšVûå;Xâ±\£,k<˜Å½¡°Ú@4*æ¹m·ŒkÊÜÎn¯S}P9Ú ×š/‚i”ò„w”â·¸G‰O§ ëC.âxóís’Þ|G!Ñ“ÂhØ–ˆßö~öŒ¸žîH+îó/]­^J’ Vj3xË3ÄZk²  _‹Ô/¿{4=[CÓnj½Þlí›.ÿÈüÐÎbQ¸¨Ù¸Ò x•Ðà&I bÞ}vì[¶s T£¿fþÀ.ûæÑäaq«¸÷öL—pþ1;FAOg*­ëv(-Ú,Ï/½„ À.&±/l|~ 9^O ›ÒSDÒrBggeçô·w Ó ¼$…^ô„¡ ¯±_£ñì É7é5>ê[87;„æ~)˜ œ)N|¹ç#À7,¶¿¡hº)dºäœ·§vsâÔ—ý¬wwMÂüÖÖ(» QB¾V ÑjRül#ûcš £¹6z-z¥KÆŸµ¢l HÓí;–ÕM¯1Ÿnkº?s’IÚM^޲ÖE @Øc."õ6¶~"zàÓçž© «".®iÑ9’]Œ2—nðîcÄ:z¿¯-¯$c?ñÄ„>˜ Cô$h‘)O ‘bD¾!Ø+ǽ¾Ñgú¼w¨Ê¥õÂ,öO‹ÿL—ÿ™)WW#Rˆó3iÈh-àHu€Ý"É¢,!ò›}R—ÂIE3üÇ‹-L#(p°Az^ïkèGm‡,ƒlS£A¶rù*O1TqÆTö ‰Þ¨‰­êÚ^ÆvµKÞŒ3@r:ÉñUë§XÚ øƒ¢z¦æcôÙ gxWbqÎvŠîüº!— A8¡…ÿ¹:óÜ“nMAýÊUSÌì4-4ûîîª*aân,†[ðôÁ¢mž¼ÄG'âÂÆv5OHdì³êïu‹pWš3zž’:)ÕçÂì°M¤~%wc´ö·J††^IçOìŠþ*³ñú¥²ó¤duÔÁàÄÂHãò®Xïo‘í{÷‘n/ÓÅOýó~ÜiažOØÚÐ)b;‚Fûd¦Mϳâ‹&µ¦wÇ¿‰ˆprÍÒéñüD’75L·9/oˆöFtCrÈó3ø>NsJ ^-5Ø<ªB+·òÇ@ Ü`•OotÚ˜_QNÌ7æ©æ]hÇ"ÿ|ÌŽÊb©`Ó’…hßWÊô,V‡Ì ›‚ÌzqüÙméCö 3 pZBÛBª°¡ä‘Â-êÇG ã€C¶C™b¨Ïå½ìåw äŒôM·æåC:šI./8i›]Ï%ÔÆ©VÔ¸YS[ýbÚŽ†ðóAbASæ–>z>²þ+)îàwÛ–YûE²y!;"´›˜¼Òöc›Šè,ñé'Bþõü£nÓ„qNŒ#3s–ú¥šo÷öâ˜ζ4—¦ ÑW}òŸØì[rí¶ ·nÍï`Eª~W˜Ä»ÀKIÝÙ÷Kÿô&øñdLª­%/'÷‘¥Y}.ÝkN÷Wÿî;à‡¶‘¶(­½7 öˆ+Iéòãê ÊLñ¿óueXƒ>í ž5ÉŸŒèƒæÔèàGSù1´[Λ‘œÈwûÊJ, R£‡O™Bܦ­*ÉØ}ø\"fKÈéBƒq†'c%"•U ©ú¿›A!†&p™Lþ¡À³$v#RŠuó FÎn¶ãmÙ݃†5Sß©ö>,Ÿ}o“»/j›øzY´¿~­¥3z`ÜÛ$„”)4»¹‰‘pսȯEwäŒ9ÌÒZK"‡õg#ÝN()ºöBBÁÈ;õÃOT»í·™è“XÆëÉ¥í¨>‘ ü@çÓ*PWîÛ³¯ðý®QÑ1X!p!‚%:+á¢;\Šƒ>׳A×%ù6iªÎ0µM!#¥?è.T3AJÅí1Å è7Ç}äÖªñnaF=ëÙ~2Ó£æ¢m¾™b Îñ‚ôUq‚"b0én,b_zFS;e¯k€gùJŒœ[vz+ï1í«¯| ÆÒ«ž3ƒÌc´#ë³Ù¶|ƒCI¾9Àê0·²<|¿N"ƒYˆ ™»ÄÚ„5'²ZÄN~ ®>ûWâí‹ï=HêBDqUy »Çb?í¡u°igãî¿ÊA‹Mò‚¤_£#ÏŠwL°!ÀFh“êpÈc@Œ³ègÜHŠP¯$+J#˜™Å¤tԘϚӺFAðD£%§S°Þ¸}¸‡‚Õ êAõ òÅû7¸ÌñR´U«ž”}åò¨×&³B«ŽÕõC¹×¨9Ä$žÚ"“'Ì“^[zŒ»sf÷7v‹N¤÷æú\¿oS±]U.NG¥Sˆð ó›D®!æ:Àd-õ¦A¡]¦&ê `Ðb@_€¹Uuó: HéaMUÍÅ‚UòÉІm¸ØwLÈˬÇÂònmW`²óLYû ¶—kþÅžfý€!“AƧ¹Ì¿/[>¦3ߘØàÿ-ƾñãŒ:Bå'»·ÉÙ›Šx;´£FÞï34n¨hÐø¸$q5òl‚ëÄ}q%;ÉHT­ ×ß¿3yb·JÚ³¹)Ï)ÉŒk©M ¿n¹|üôyõ½ü¯TÖÀ¼ºÃØD«“ØÊgì5¼ÑØ9ù,Ïǵñf~)ÍGÙxþúŒ½BÌq{+ç­_[ÅØò~|Òò:mdÀ¯Ø4æÝaôfùsá!â"E"ývíâ솣‘¶Ž±ö.f—wíaOÁ«&û:yäwÂW0 LfÜf‰È5û¶cF¨ªG`‡¸É>œÓPä|±‹ì*›}¨ÑÄScñú1›ÓPEšû{ ?Yˆ“Wd`0Åä¼›šDIÖrwš6$ûº_8Ú–ú\~û —qíáúÙˆõÓ&þªÞZÛÜ‚*:…°…ÆlgÉf)³$=‘ÎZa’ñèóPÁîû9(ùˆ,\Ž2{FYjôµÝ Åk7R%T7hÒ­ˆ%ýâÞéôÑ$î'jÖÞjL¥yŽž/¡Þmc¯|,[Bxdȱ!ÅÒ´Ò7Åx¤`¦Fk[¤¬x_µx:ǧXiY-=ÕIV 4+ÚÀ.sr—\<öHÒjTB!¶VÙe‚~¦y±c°Žo¦Ö’"z…^ªb›MÈ }<†òK¬ gì~è]GQòÇw" :j>«“·u§¿Ì¤aüoÐDqºŒ4T*âFI8ÅÙJ{Á «Dð‡‹àe°´|LòÃjØt†1#,#ôóxàõ¦ËÔwq[H7ïü‰õV™¬wÇáG¶pŒÞlŸêÛAé Ä0È ì96?BÄ®,A«]@W„ÆÌНµÁ2¾´•Þ/kêå Æa^ÍÔÆ^þÜ=L^”|ÊȇA¸$\*¸&Óä ¹(#Æ<›×ל„8áŒÌu'î¯Ô»,FE¾z½š?| ³vÑA.± ã™}óÞ²r“†YѶéC1ª¿5GI݆Ì[“Œg­Aw­ÖR µhuœù‡˜þg¢Ï§œÙËÊ!r ,ˆÝÇóËŒ¶uhd23AÞ' …$sÁ59PÁ?%ilo7xÅ““Vz¶(»ûoÏØÐÛ94É^° é´€O*׌—§»ËÒQ9Qâ7¸(s’šå7öH.~ž×z„ü¡;̧V(o No§æ]`7ËLqÂ×*WÎöd yï•Ü(ÅLÉ5ØI ß«øq-¯,ÿ6àß³ù“ôÙ%JQ%c¼+óù€©òæ) ÿG½3ý–Aÿ’“k&µ‰üø…ZÖÅ R® _y8 ŸK—þ–üjÍ(yuKBë‚÷¼çw»‘G-ºÓÝ4{¥¢ LÌ»…;S çW-š†À‹¾ÍQõƶOÖ΋³@™äÅŸræ³-DZö¡vl'ùO|m¨qa h`8# }sB‰Ú^¹cÓÍ>ö)š¦x0×ÛáaxÎòŵÞ6ä>W‡«2Û3k-æÞpáó­:i¨ö–ýL‡s>MqìÈOÒo1…±|Úâ—Ý1Œz2 g_GãûWŽVå:|8Êdb½qd껸™®ãÑU¿,„ Qd‹Sšº´;Nâ=®’ˆ ~ošÏRâÓï¨îº'Ön¦Æ9s 3\ŸMYâØ×Z6´• ¦øˆË†Q”%Éà#“·*ß2‰——yL@Fþ"×pŒú$ha-ÿù‹e’^¥=¡òw«’>Ö·b ”¤AŸßÕS¡Õ-}^{íS×ûJéw´V¾^¹ctSs:Ï9^kL®”¨cS§ÖÁ6:ëMü!a‰ö§é_à^¯MÄìÝvkÒØ^Fç ”€*íñô²Þ²#K!ö8O|â@Êf¨ìŽ·<\Õ•²ƒ%zñä£c”ä‘XU#$¯¢¤Àî×x­ §Ý/šá uAä]ÔwtuÝøvÌœXîüø,UÃ=±URÔ¼ý‘¡l<¦›ÛŠ<¸äGp2¾)CÛ;zVâÏXZà ˆ‡V…³tÑ_^ûÏtOcÍ)¶ Ùlš+ori\¨g† Êc{žf±ÍÍTÉ¿EÜËLC#"üdiˆLŤwœ›·ÑÀίš ãZ<Œ5HFûUˆ÷Áˆ©ëIºT”åò²k?_HsБêõ*Ž´D\fvÅ9½‹øfV¥3p¿’¡|ôMÌýÓ†õfùS79墎‡ÑÇKŸõ\uƒ=~$Jb™KŽç(¯gÑ<“RÔhªyp`°*@ÜX-Ì Ä©î/s)i×v©Ž>æ½kʯ–аè‹jáX æÑYü%×ÉI'Èû»þù„! %Ó×¹¯©'Hú†­§ î‰Þ5äÂø‡E»¨XL±dÛYÃVšWó™±ñVÜÌë ñƒwg|BoËb ÁõæSh¤øÍ­ð¥f³¢áRQ¥É ¬Ã"[{VˆÞ+4Û4mÉm©&Þ¿è°" ¾fæiù/²Ê¦J».BñSj ¤àa,BæWnù–è¤K€ÎŠx¥Åœzõ<*â-ƒ?O^—7ƒ5†ç•nyXš+SÛ'ïÉ K—Íî°èdÖÆ®é¤ð®áz+·%Ñ€‚°Êy[Y›Ø}ná¨úõ|¼J%‡7l‹êÞJ¬=FÁ׿ïšÁ+›ÝfnºsHwZ›’ž÷l°Å؈µ“÷Z„[ˆw&j¢ä…fm'*½Ùi|*¸^ +Ô«pRç¨a—”¢ž^[b6ãÐÓ›qèèӮεßWLÎD¨×ÛÐЃóÌ_(_q”qDØ¢ç6ä eéä?ŸrÒj¡ä>Ç"üèë% n/¼X™\ðû´ý6ÀhMöÐ3«žO +¡_zõ›yŒ¯ u?µüûÝK¼Q‡)gÙ¥²·6{k­ j!`i~QÓ}fKã—o ò0µRžù½6ôµ%”ÙüÜ*tL<–H•üú‚€i²ZÝ”üµ Rˆ°çmF4táÚêÃôúà5<¿þB…6ô;÷Z'[p(ü†=Ñ3ëAÈ ž”ÙV!Õ´¸ÈB“$.K˜h:;ææÒ³§ßÄãŸ/îl´ÇæN­ò¶°ºTádó®È•0Í:lUH2öL TˆI§)# 1¨»}µñÌ¢òþ â½U“çXT)ã KÄBŸ`µiLg¶v¡Fì}wÔ/VEZî´DME|¹Cô7¶Þ´ÀÖÇÚ›Š(Ãz1dK–Q§Ä„k[ X.Þû\u ìÓˆâÅ>üì³è@Õp{óè!C¢†W?î€×hñ×5A‡­¢÷¼Â”†ÜüðÔó‹—“ºïv¯_‘×5Ï0*5øÓ/­Î‘ Äuäû|.$=^#ónÞ·(a%ˆ‘\ އ؛R¬~[dÇ‘2Mý]yWÌ«qõQ¤Ôr9×(jNŒþ[\pqÓ̘Ï:ªÖÑYÿºcØ-e!Øu$l\j™d÷¡ÇØ¢‰ÈŸ¿-Q$‡…ò¤,h׬/UmÈf¿ç\JztöN8AÙ}èw@Ñ%šn,„™ðÞ°º wºxT÷Õ=aÛªŽ‚aLþ»å!YH¨ùjšvo¡½VÌj¨X*æ¶è%ÒµÙCÛŒúuœrw¸%—yÇãÏwkÊ”+ó3›üâ1‡Œ‡v5 .¿a>À¥d·—š„’z°ëtÃK©ÑÈ\ùtÓ÷’Éä„XˆL°¯^½V'|Ü8·š­%¬¬Ý:õrCŸNî*còº µŠV©ì•m~pµŠª”úÒç+âžeúò™ÏéA7H·ãØèFœæ¦"ÈqšÃm‚ÚQ5Y­9òëE2á¬vìiëû 3t3YjÙ½Æ£Ü ½ÍymÓ+¯±³Øª1gêÒVšZ–¶ïîvæõ©ë±›²cƒ ¥LÑ Œz¼=þ[cz«øU÷Ÿ›Ï6œ¦ŽI’û´Ä-ªC4Ù{œ'ó Þ&ŠPŽ ; Tt¹H1”ƒýgi(EŒr­¶ûý§²ke$‹t§ƒ»rX’;L/·Þ \Ÿž¬ïv5ðü;ãílîµá ’c[“c©…HìÚ8ë÷ßEþIÕ,Ïýž÷|8èsEŽš2»÷y<1™ŒàC»DÕÄsÛkŸ×½}ê5 "e¢H‹êàˆ¶sô£ñ|3¸4gÍq³%M8•pjVãYÏ÷eǰ†h]ÖµhEåd-jrÁUg‹•[÷צ&²–PÈ‚²Þ\dO7Ê“)——¡nâö­^yƒcžDª¯PõÕ·’„$Éæùà¶ì5½‹=Yu+"!Ó(×Ö,®†³£@+wȹC,*;´Ž ©%¹y°²VB4Æß¼rºÏ¸W‹º oo¶!OJ~:™âEá3d HÚq,µùi™LV’uL®Ð軨a\>Lj¹Ò&è®åAxaWÊATW‰(õ ~ÏÚä ]ñ©uÎb냭>i ýqÎI¯x¹µÌY=騥íãwÅ/w%}å*ÁZ=I¨g›ï¾Ùié¶îЙ…%wµÇV)AõèI´P÷© «cVvµQ3„´¼4\ÖlºCޝ¸Þ¡Zñ§>-‹g7„9ù+ „¶.™¾_*Þ`8½ü• 6tﮆKg‘þö-]Èz|ÅqjÆí g‰Ôõ1õ•¬8L´)ìwd¢žïǪÈZ8Ì|Q‹WŽ3G;‡Jò“_kcÕª2—jíj•›^“äñËp†¦ºJtL¦òm#z´F}ÚÊ08M[Q˜ ¼Vª"â¾I–uß§ÌÔ[Ãð=íõväv®˜ÊÁ|æñaµSX6|³¸|`p_vi~ØP•X œgaC}U¬ØÓp‡š8” ÖÚ÷e*Z»ŽmÞÜý[Ò~ü¡)ñŒ›U•äÃïgÈàÛêÞ³Ôåè >î%í1•|ì»Z8ÒäRSýìºÀê O]zÎ5 Ä´Ì“ü7Æ”‰šrf8Üåû¥×lÿËõÿü?`n4u†8Ú›:Û¢þy³³endstream endobj 89 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 45 /LastChar 121 /Widths 302 0 R /BaseFont /RBVTAT+NimbusMonL-ReguObli /FontDescriptor 87 0 R >> endobj 87 0 obj << /Ascent 625 /CapHeight 557 /Descent -147 /FontName /RBVTAT+NimbusMonL-ReguObli /ItalicAngle -12 /StemV 43 /XHeight 426 /FontBBox [-61 -237 774 811] /Flags 4 /CharSet (/hyphen/period/slash/zero/one/two/five/eight/colon/C/D/E/G/H/I/R/S/T/Z/underscore/a/b/c/d/e/f/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/y) /FontFile 88 0 R >> endobj 302 0 obj [600 600 600 600 600 600 0 0 600 0 0 600 0 600 0 0 0 0 0 0 0 0 600 600 600 0 600 600 600 0 0 0 0 0 0 0 0 600 600 600 0 0 0 0 0 600 0 0 0 0 600 0 600 600 600 600 600 600 0 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 ] endobj 70 0 obj << /Length1 1612 /Length2 16800 /Length3 532 /Length 17707 /Filter /FlateDecode >> stream xÚ¬·c”¥ÝÒ%šv¥Íª´mÛ¶mÛ¶mÛ¶m»ÒF%*í[ï9Ýýõ8·ïŸ¾ß=Ƴ"b͘3VŒ±I å•hŒí MDílihé9²6†.N2v¶Ò4Š&f.€¿FRR!Gg ;[agN€š‰1@ØÄÀÈ`ààà€!ÙÙ{8Z˜™;ÈUÕ(¨¨¨ÿËòOÀÐãzþÞt²0³üüûájbmgocbëüâÿú¢’‰ ÀÙÜ`jam’“׋ɪÄLlM ¬ò.†ÖFi #[' €©#Àú߀‘­±Å?¥9ÑþÅpœìMŒ,þ^3q72±ÿÇE °7q´±prúû °p˜9Ø:ÿí³ÀÂÖÈÚÅøí¦vÿ"dïh÷7Âæ¯ï/˜¼“³“‘£…½3àoVyaÑót67pþ'·“Å_7ÀÎôo¤±‘Ë?%ýË÷æ¯×ÙÀÂÖ àlâîüO.C€±…“½µÇßÜÁì-þEÃÅÉÂÖì¿PMÌ ­MœœþÂüÅþ§;ÿU'à«ÞÀÞÞÚã_·íþõ¿8X8;™X›ÒÂ00þÍiäü7·™…- Ý?ƒ"akj` ÿ·ÝØÅþú\MÿÕ òf†â/ c;[k€±‰) ¬óß”òÿ;•iÿûDþoø¿Eàÿyÿÿ‰ûŸýoøÿï{þOhQkkY›¿ðïø»aìÒ€vŒµãÿ+ÜÀÆÂÚãÿpá?ÕLþMòÿGÂÙào3lÍþ BOKÿo£…“¨…»‰±¼…³‘9ÀÔÀúo§þeW±56q´¶°5ù«è¿š  a §ÿŸ²¹…‘•í?­gù·ËÄÖø?Éÿé_Ôéd%Äå©þs§þ+Jþ¯öÎÊö‰ýRdìŒÿ×á AA;w€ÍßHÃÈÄ`ý›Áçÿí_0 ÿu–1pv´phý-™žá_…ÿßtþFÄÖÈÎøŸYQr6°5þ;^ÿËðÛÈÅÑñ¯ªÿzñ þŸç º‰‰»‰ÌƪW°ezV†s=FÞè´°Ö`?èhˆ}Y“rq¡­]Ÿ_zøG•þG]mó,çW‡ÇÊ…ýç‘$åñx?º5Y_ªÉu®1Å@!ÒöÏ.6ªã@:ݲ—jÑ^7ËÒ»`š¬ôªÇûÓ Šº¥x³]LŽP7ÏþÄ®…þ¨$Oöð¾Fiqh݈Í@ÈõE—?“ΞŸÈ†'ÆFGúîÀŽp¨rã I¹\Á~üŒòwÈÅáÓT©òŠ €Èhùë¼ù"PëõÒÍ'%Á&‰´‘~“7+Ø´í”þHÏèäãN’qo?ªVG¿]œâHšåXÈûÞr!qÂànÁ ü3oE4—Ùˆ?úrK>èîUoSKù6Ÿ·46§Ð]ÖèÖqDJO3áR /ÔnïDꩽ&(enòQžn—2ü´¬fÈÓÕ¿`Uw)mœ§ãXŸ…)O{ÑvŽvÞÂZdÐ|'<4#=Ôr«);%N\r©àÑå{å:ˆC’PáõÄ¥®[“þ@×\¦ÒÝ&½¤üœ<Þ[ÒÐa޳œ#BâË‘NO n¸”=¦õ}1tšé¾c‹œ^uàyê2ŒN3¿TdâMG‰QY@b-`£^ÍOxˆ£'J‰é¶zß7KÙÞOÄT6ilÆ‚!›Ô1µ¾F*ZYë¹)3«*æVŸ¿Wý±ˆ?ߊ‰*„* ý¬IÑÙÑk>¼p ¤ü•%˜Æ? È¢Ýß-c¡Xo3f%ùõsé~zF7{¸…6 * ‘H| .Äp`5|y¼ÝðšÅ]¥Ten‹Ï A¯©*—’Sùˆ3x.hî ¸"÷v5$ͧNŽ¥÷«MŠ™Ÿ¢öB®F9Ù]_#µGO¬iƒ.†‘Ù™­È„iÜä5x^U²r×$sf·Àg•lý̤LgzeF1'e_ð„6H²t}ã}#¤ªãê}[&ƒøv#~à6€gžûO/Û>7Èõð¯dD92´#\a¾†:¤ƒ™Æ‰»¾ÂÖ‰Œ„ÓQÝkØúug07Ío;öÍØ}K Ú[#§~‡Ù’pú‚Èýåké, ÍÕÄGX—W3æub X§úC£ëVŠäŽè¦Ìå²åSÜçßÖ"_H ÔÓë{†i%‘!®#a”žynì&ŒJ£[2Á9M*ÖZ>­–Ê Áàt1½¬œ•ÕØÞ‘ð²ÚÈk?Žãï 0ŠÅ±¡ÔÊ6Ü÷A¹ N U8>©ö¬¯L# ÈÔ ÒZó¤þ¬ôñ—§cj¶›ú‘_‡Å;W%5Ó˜©ºùøíUÊõíÓuï ±âû:Ÿ!Cvš]µÜͪ^ßœìM;\žÏöõX­Ï#é Þ›•B±ã$zCÓp)Ÿ-/^2ó¨¢"ÈWgõN²?¿™ƒ/5X6Ì9a¹ãk<2Äñ£”îf¼,̈ì³O¦Þ»…¦C‰ÄþFÊ -ë{±)³~…ª€CÂ0–ÈÄ­-ÂËžáuËä®d㚃Á.oÙ±™à0Ô/Ðhì—5"9ÎÓòDA©%µ!²ð‡Z•" [Œ„½)R¹îç·f\ò3¿qÉÐ1IýzbÙU©þ6èžBÎÏcFnÀ\3XxàgÝ ëvÈú¥¼ÒbGwÈvógã#ZÝ“ThäÞ²:ÝÇAY¯ŸÏþ«4¨L3ªyfű'„>ŽºYTx%XßvŒR›Ý7¬ Œj ×ÕÞ­kóp‚æH˺@ï”xFL4Þ=~V«èü(9¥ù‚*WÂ8‘‘YF<¸õ’~½juˆaðϰîÏ…ÄCdú‡I{³ÀU¢÷½äò®Œ.ÕXT•z´÷Ð…¤e›Ú˜æ× ¾ÉN(ycwF5Èéx½CAb΂š^*zZKgi…^z5änǨx«¨ôŽ‘WTEgù¼÷»v¦¤Cð;míÖºwÈBéE)ñdê™НL|,´N¸á|b€VÒU= lhžª±¤ÐÑuÞÝ R þÚ(’Tp ;ØšŸÇbý]¤âºzI(€O¿[SZTau”¦°)8høí'ÿÕð IŸ«ˆ×8‡»ì<ü¢Þ1dµ$SrM<“yGÃwÍiCº²üAÒª¹H—I¶³¿þQõÙ:yù)ÿww™K^+ %–%‚´*Ú(LÓKkâ²üޱjÑáÓ›t»j “¿ä'ÓP: ¨ò[¯k¥˜¡GÞ÷¹÷kîÆyå"€‰ïïàjWÂÁWðÍz$ïï*•ç7ÇÄ íßtN¸$G ¯}ö#”Sp ¡G!‘­gIÉ¿¯d–9ẘª72Æ0ç.’ó{Ó9­ßf½|”b#3ààHaV-Žè! /ɮ͋XÅ4]Ú,K§‘Wî‹ÅÁt#p»¨ ñ±ÛÉk}€íS½qÂbž­¥m›)k&%Ó,W<ºÖ ‹9ôÜkÐoZZ¬fm ˜øm0± –t+²µ(&îGÕ þ¼^(ô¤>Iï+šÝƒ0"ÜaòGWöNß׿ðé“(ý‰4–Ì™„4¸j³©Ã “mÒG|îiGÐç¶¿UÈŽ‘Kl£àcG«>¬?w Ã|—nJ,Xvæb6s Ùºêå}}è²Í(¬ÛX†k¥ÃW«³{’| GÚЉýžEŽèî~ˆÛÑ¬Ê mt)ì@ Áy{ê@µÿI83åfH€ö@æ9ñ©§ª÷O´8Ût‘_šý1nS`¬•`4êP¾çð9L:?sšá öê‚pß¿•G“ÿ>GKwõ¬öåó ‡yz0êòÕ½RItm;!¯Ij" •‡-c¾òøJÝæç.Ô¿Ü=à¼ü¾ŠwºÝ>ñÉ6Ù˜æJ×2¬èÆÁÈ2,/‚«eƒ÷û·ÉÜ@µƒ£‚ôÝÃt2Tª+¤¤/Ãó(×ð&u,.î…=ÐwI °æ±9v†J²‚„Exƒ9qõ!âÞ‰p‘¢b!¿X­vÔæÆ£GßíDš®êOg¶P•2ÆŠîµôà+¦Â@å$6Îz‡/c!K˜BsNÿmçÏHo¿fls)@™4UÕâÎ5ù<)\›Â^s3-d¢´œè!³‹¸;q×Ú=D–Á3Ýås˜Îjݨo\Þ Á—`çª%Î?e‰+è›Ò›­*ª¶¦ªÜg9ÄGó¨*܈gÖïNÎñ©cãz.ªÍ÷næ÷=TµòÔò³Hsj”®áÆ÷W~­aRÖL'ïQ†›˜é ¹RäÄÒê9„4ÁªÐKÏ ˆ¥üÄôôûÓã×ü°³èÁaY€S‰¤·1Sg=§¤¡’‘ ŒlÐRluJÏô5ûãÆ®wšM_µºn«=Ȇ3øfðN²g¿%5±2•VŸz_Lpø PNü”Ç—àÚxÿÑ–/°f—Èm%¿ƒU‡V/Oú»ŒôÌäŸ4,ø9ª¶ù I$¾ñâͱ0<Ï}$oœïx©6 }ºƒE‰Hî0e“Ró˜L)§ðªK³ÎD9½'Iëulðð5¿è$¼#\g> bw£²ZL•n5#½´½Ê¹åª­Èi`÷¨’“&®àïňtäÈÛÞá†øÈ¢bÑ4^nÚ:TH!7ätw¢ÚrüJÄ­ çýM×@”¢ô?Ùwötò:§4åîIx‹wZ0ESƒL:ráÊÆ6;¤GvšÙßÈ¡n8ëŸ,Œß~ÖÐŽâµ03Æôm-œ@,O0ðZ7ÙS±ý¹+1ÝJM‰°V 8r)…ÎÒœ5hÝkÈJ4Õ%š)lƒêß}Í~P'†A|]}`TÇ¢¥ñû) y(à*ñkk`ÌÏW1LÞë¼_™¥Z¬ƒ¥Ï rå}Š!ÜÓ®²Ÿ4)èí3ÑN¦oÄ= =’ji2¼ç(d©‰4P9£Ž££Êd¤-«IÆ'ðç¡^pª_ #—¼ê³îû™zѱ"¸²Rǡڹ,:V÷1ÐsäÏ"ö«oå ȧφìÔ­|ÊÃú]8C”>q ¨I½”‚ò…/wƒZ†ÀüÐ,RÝ”*¾z(Ë~$gŽ7‹™jµºÑï†T“Æn0 t*DèqìÁ96O¦¡»è¡|QìÅÈdôÏ$ &½ö·Fµ{“KÛ£rD; L)˜ð´Ìñ®£éÓËÚ]t€Q_È ¼‚•ŒÌ˜}öq>rÛdV°1.c6 ‹W•b~ô’Z^}¹¡XñˆˆyzQ;‚Š¿Ø1 Ás6 .kÈzÌ.PmÚ ë™Ÿù|–tÁ³´ÌÉgyR׎у™íå~_Âe ãBïŸbNùF5õ’jhœ¦ªt.“Giƒäí·ÛX‹N[!ùŸjÃFÀ°+…K —•‡‹@&ÁÎP©\vlvýèáHß{Õbò¹RŸp<,Ú¾þZhÕ³¬Í6›¬JˆáIòQÞ¡!z`²]:ÍÈ1."ã%ÑìzÒÃûtùW´[4ˆ¢)Jµ3ÖÆh3V£˜‰5È ÎâBµ1s³Ò“»ôyޑǤ(ÔÝÔ-€Ô·±Ø’úÆ,5Nóó$YÑI)Q`À{íA„Y]‡‰»Q…Håß n¾¿ûJ8Þ»]×o’\áOB£¬¥…©³Hb÷ÈBˆƒÐSÐOì(’|ePžN¤§½.Ãè7މ¬ë*·ÇM]Bw‡„÷<ÍûïÄíBƒÉ”n;Àû«@Nûž÷¤ã2ð„«Û¶»ÕÔ}õ„*G.õS38dÿ¶žaéÊÍiEG¨óFÀmb(qIiª}ãD2U»&Eu«óÐï¿^‡ ÕqõJÁœBâ“+`e4 ЇA{ÕÉ"ï?Y?76L§@jÇ.¾·±Ñ5|†°:jvÈ ­LÜW¾¸í[‡åÌ6@Øè> ô¿às`.\«y €zƦ<´ À+lød©§P\ ´QÛ À_'Æ«Á×§ôÕ‚l2¢’n¬ G¹—/Õ§º;qµò5 9xòÙÊ%¦ ê[·µëo§´2yjǘznZÓ q‘")È…{¤Ä¾©Ò¤´–§ædù¡ µ®Å²­p<2*)gj­`C5ë@ǹ. ×Ó—Ï÷TçGܰy»‹{ù{^þ²1vc'“Å~gޱøàè¥#M[¸Ë²KŠÁBRI±¦ýõ˜‡EEI½4°z«ðZÞ7ÁÄ6Eêæ±àÃ7¿KñgóðV‹Èp1M¯7CÊPËÁtY„,˜} Þ£šþfÏþÖWŠ ïèìѾ}1}j•¡•†ÎG9@M„jaÏ8ìfÄÍ;»` ¼¶²Ùt=„iJéè¶>Ò†ÝÖö4"ÐÔ‚Bò+ìQ çŠvÈp<ê‰Zqˆ…ÐòÕ]x±/Ãte/S´^9É%L‘w/¢ò©>ô™{Ù¦ù£Ã4%µí¸«{Êqõ`Û=šZ]R_Ь2, ‘žñ3R>ó”§ðòQ;L}±gå4Šœi–uD6Ô ¢„+Fö¥‘Ê~öMÕØ6 jš—Ç‚Vb|Ù`\¨äÙ”¦bÒl„6ˆ¼¼T#ݺF%Â9M¥± ËßZE´ˆj—ÉP3n„’M¶«WLCµ¥t+ÜMSªç3¤"ju‘KBY­ÁY2¬ ;.{”ãW*®a†îHÒ„Ç,5FÄãrL Ο6Ä;êp&ô ² m£ç#›š‡_§i«%è[ʇ Q"#ï{®QJ&-¨n‚æð0%Aˆ…P<½½¸dÖ8˜€™Œ=¤%auM¬EÊs!ºÅ×nUUøÊǹL'ýö7*BЙ·úͦÊO{ÎÚ ;HGnzÛM\SˆÜßÓ3¿x¯Õ9?i¼_Baå~ #@²î#tv–Omäóàs<ÓÂ&d@Rž¡°¬›F4r[Ž:»Ófá6\fƒ…ôÌ}œVÊj€r0ÿÉK¢à$òýÈý‚Ö3Rµ© H!¦zþC]±^;QçvÛÒø Põ]ä›+1yôJŸ°ƒÇµäƒß3”J°/…•(¼‡®¬WA´=ìò¼¨ëpÿV ÿz͈1”G|¢)B4|:GWª¹ö¡Y3¹~}¹¸x«ÑZ.:ï`YP¼­Î ¾²1TÉ1bD5btMvÊ‚/ÿ3ÚŒ ‰E~i ‹ø6¸D÷°€"2ª¥Àeë¹óDÖÑëh×WRG“?™Ñ1®üùqº¢|݈š~˜Où7R *ykÇNl<‰õ~P÷·Ð—EŽ[­àòöž¨¯)„U®Bx³þoX)ÃÍïä¼2Cz´ŽíaRšd©ÚÔD ‚t°Oð '¡§O9EN$”£«“Õˆú¢±ÔA±2¦ÕûáfÁ=TŽÀ{É+b*a帛Ãv¯%R–Û2•Ç㘔 :Üýå[qvÃÃÞ|‡=oðž`ýöd4F¼ï7¢oý=©IõõÞÈÎ:åæœèp]HîL9:EFöd;&*2¾è ò¶€UFŽyn$p—@½vÂJ«]à ¦íÁPªD>ïÓ$ä—¢7n´¸ ¤f£^u‡ÒóB¡‹óéÞ'-Æ/d¢«¹37 I‰“ÓeVK¡‡n9[„mùZIŸºúÒÝ4Ú ‰tô׫Øñ‰O¿õJ?¤CΘ]üï}‚lªèýÉÈ´ðò âïØ†?†òz$ç";N¼#¨F 7™©g]—ïgìéº;T¶>ãÚÀ%vÝ­™z®š(/8ûŸ×aN(AgJ>¯vÅ^Òµ\Vw¸‘•<^¹þB}³Ùrq°q+øëÚŒ‚éiçQ‘ò(¯éëM8£W©ÅìÃ)97Ú¯¼ÆkÇBðr÷ñ åÖVgVö„ kŸø$O’Ÿ2Ʋ-Ll >µÆrÆ©ß?o ÉõZg&|qûe~ö{Y ¯fþ |Óãv8vëu$Mǰñ }Ö—r„jñ,^O‡Wè R-'å+ñBB¬ä4ùP§ñ]ÿÙx-¢/Òi«Åî‘©0`Wö „=]ß#òÓ|Á?3濃ÈÐ|„7 L.•ɬm”ÓÅýJîº ‘\‘Dt-ôžÇÃ1× `€'ÛO­´‘0ør)/=Ê!rUNô´é×ÔD%ÀøêŸÃH×åÿx’¾Ç_ž³ÁâÒ ¦hÛý®õR^]àŠç¡;X ,†]/•H~,boז܆!+wÕ–[°gní3Ÿ?fÈÿ™;y1Ë_‰xGëÅS1Ú+ö¯‚Þq€ÊèŰS¨¼Eëx©/ÈWkR^_/íÄ|¾Èzžû¶RÚZékm‘5Î.c:Jzr=^ž€¤ŸkÔ8GÕÖÎTpãsiº’&‚ÅÝùíÞFž†;7!¶ž¦|Ì›ÿ„V繞>1]‚¨iîå¼90Ñz´OÊŠ?=ޤˆ’,Fsa‘K»;œ›è²ŸægˆõΨv“ÔƒE):‹?°¦©ˆ<éS÷!ˆJƒº;ztnæy B€ KÌ~Á†rn‘3|ïšOg,æUø·IÊtÚioqŽ?¿p˜Mé@·òt¨PÞ!.é$›˜‹˜hþ5#P‰4¤ 0OÅÀbȦËÉëµÎãSÎL\S¸S³/¥< ÂW&íC÷;¬!¹°ô4îÈiF“cä‹ê w…ØàNzRÖL+Z×…ëŽëvž/A!âTãWÊÔ\¯uÓ¸ŽüWû3þ+ÇûܤonH,ÿÍYÖ=yâý&Îò§öž§Å™7ˆÁ}‰^ ö.Øïï0SÄ0ØR¸ Ú}Æ.ˆøMÑ’–:¯(1læ®›Êö„°Å~ŸªP‚\;êA5½(Ot k4{øî}éÑåÍñY4þd^“!‘¿8¸&}}´E‘†DŠ&çÈóPVgZ˜+ÅïÝ%f—÷fÛÜù_9O×Bp`Àð‡ñQîyl£É˜¨Ãž0\ž¤5BÖ(ý²Ö«Ä·‚MƒÔ]D.ÃQ‰`L/ã9{ΞÊ<ÅE“Ü8`²Nm<+üøkúQ—üÉÓYÞþB¤WxY*"™LîÁ}d²iJééÔ_lcwÓ"ÙM­>à6ðçñ9g#`'ôÈJ"üÜ8ÏGÇ[Š(&ii§ÁÓ=nü¶zĤ•a2‚)ÁïQ*»¸Xí–¦#ÈÊÏÈþƒàì°.цP®u~-W ä¼"F‚¾2°%´:ع!G+;§pR`[rX=l!c¼¦*ÙÀv`›¶<ˆ´_Ó(* ¦™ÒÂo'L‘|¿Z~;,xå~ïJ ¾á:Ù‚^^ᆡ{yKâxç+5‰ÁJ€¤`9îK¥G™“ÁÜ4EcJ1Á‹tµE‘’@š…ûæ ÏÔöúÂà!‘QYŽ­}ß7e.;àIúç3cx|œ@Eæn®}`VZoç$lá"á‚r±\`Ûm˜d8¯³p#Y-h»ªg\Š*”ø[np@qro1ô.›6ºÞ¯¾uè̾X«<^ÖHÎ ¶Rêî¼wî—Ì(¥¸Ù\L–˜Zýiª)¼—_årUÝ+T "p‰ó†4Eø«¤Jì©‘ƒ!›5I<âd=Ÿï¼â±úOéÚ®ÓÅwèÁ‰0µ>á‘åÑ©^vÆ L'Zꊣ†—‹y®: òJ‡brÈèýªQ3Ûß2õ \/”iϬ‹n"Qb]Ôø™ÆâR¹LÂŒíqo°¹/ã!ÂÛL‰o=Y@î ú‡h÷Ï(M‚55¦½qPÝμn(–¹ñœªý ä› ÛOfwmÿ…õÇ t˜£¥,H7¹‡ S*ÓïvîèÎßNr|4VŒ{þe¬–Œ.úId¯1ë†"œ´Kw#Ú„Š7ˆàmy²Mp¥ë»SÓªívnŠÁ µbå– }¦+5w&„¥DÅ9±JµŒ2¾£€*vŸÛ»­Ü1ÂÝ…”6%Sئ’¿ líU[smÞF Í2L¾ëãQÔ³o¾ž}…8JÏF"(G&!û©%ÀÈs½*°°9_°gÓž‘fÄwÊëÄôòå^ñ»¹)±÷Üó§qÿV¾ñfìs‰à6?fæ=N†ï)â®ÿ5{ÆŽ´ŒÂëô©Nìó?–î(øäÆS ¿I jòKÅ©‚öפBI͇tz0ÈazëÉOèÊËDdR3 ö©ÓäÝI™2®ƒÒ¿“]Þ•—'RæRÀžI™eJÑØМ«L&Zæ[I‰ž,.ûάÆJ/­‹ˆ72ΕmËa´QÄ÷©ÆJQ*&Ù;eHl:a;Âz+7âÖÎjªž8þ>r‹ ó¼Ye úÂÄš­e‚€àÙ‚2f«ë¿ËfŠZß\Iªm–}T|¿ô¥Ñ’7÷dzøÑ hªŽ'/³ \ô¿.™ "¤ÓÙ]:€þº¯Sü‚`¬ð˜O_¼/ŽäyXPÆ0u20ÿ0€I<ºÄ—!K{ß–óX(×sp¥wF1¼§5~0r¯ˆoä꣒®"#7kiÈð\ü‚ꎔøÆ¾««fxŠÓ´'Êl.èÇ{j‹ã=sà6( bÇs‡ {3­_ZÉ#Ay¿KöȤ"éÉør†ùÝYÇF¦Pu4Û­¹õ=H„º(¾ßXr¼= Ï3×,ý£»yn¡½#-qW· ‡ljiÚ)È_u%—:—Oð½=¶œ)lÕŸ€ÿ>0$µÊ7...7¥íIÓU¯)Ùæ³ŒzŒZÙqzAÒØ …ø:Ì Tô)}L`ìȤÏFQ&ßAKHf÷Ëub–Á„|ÿ·Å æú/Ø€Èî·òTÐiÙ- œ(¡ï®»Í#€Ñ Üöí:Ä™Mƒ¥d¦¡râw'½s©ÕTÌÄ͆2i?¶¨Â3BŠzMlC@MÉ ƒ8}õ…P_\Ró)u#S˜9ÉìöÀß¿ …ç^ºÞ,(°w}l³§Ìú(Þ·“%ûÑ£äkò{Ýå®f¢)Ó”ŸəݧöDGÈjÒòvr’šlýû “ëÞá–^ÜJ4ä?²Úyÿ0K CâçÄG»egȲÞ!¯â¶­»±¡¼Ò$šÓØMÆ_=‰üd³êx] Ï'3dàã{”AaÜP…Dø´•Çfe‘ïÝ­”“–"†¿4íE _{Xõ¨‰F"~‡Ûl·9…1ÿ{ŽS㡳ÉC‰kp` úÎxÃÃÝæÍ¸±¥ºÂ³8õmýÒéEUêPê|¼?‘B{Æ—z9EØFæ¬=>X¸Ñ@"7F¸œDÄà­'†§NBŸ"t÷žB¯1ïþ°×å­Ü7%4H„¶¼"Ôd¦ªÃÏy'u&«^˜‚àH`íH]¨ -­¼Ä^ôYF¼Ãÿå3À†N‡Óìô8µ”U!§÷ì7CRü!ÅÓ':žÖ>¼‚ApBÖz9§Ò}Ç—µ~6Ã@ÍÓsš>§C&èõ¤}’+®m¼íèIFˆ²÷.çw(=*HqöšoÅŠ„0Q’&³à䕲OaI=nE[Š¡Ý-Ð5÷Ex´ìj7t`¶:•Ìjd"0îÐC¹ºÇgTºhBv´MÜ9˜†U¸hQ¨^Ýëüýg²îiòÕ> 6Ó‚|ŠÄá®úÈê½,¥˜³"À½´ÕµZõ¯D±ÖÍêòwmõéLò¥™y–˜¡.R¤4cäªaá'\é‘:RezšœÖÝ ­³T&×2él뎲§ò˜ÞΧp içº,öo¨€!ÈèaŸÄý2 ±¨Qú¯Âh åÛØêÀjA/pµ=C” ,庸ª*ú; µÛË®!Àà U1,@4ǚƸê·"ùË+€”gY)¨$ךºYÙc>ë—ìø®>ÐZ‰ÃP::AyŒY£g«x!åJz쵦ì5}P%¬iwóô1¿A½‡}EÞλ¿'-(µUÕûkoð–vhÄ ¶›šŽ%%ΗØ×3ˆ“w3W—÷¢û ñó =ýÝ€íÁ¬ïF×¾¥TñB}•½Õ:³€éɽÝà63;¦D…\:ÚÅÜíÐwV Á7MĤě÷·N#õG^eÃ]÷'àMS3”>–I¾4>V[<‚b9C|ßFìdañ€Ÿ‰ŠÝ(¤ãª„å:ü;¬ÈžîÝ£M¯+ÀKR±–ñR…„@Ot˜¯J6·é§ßIÔÍ ;ÕaZÇ×ÏþÚ 5…Iëa‚öÑ·}sq\ñTHMYïuìë<€•ÔàüÜ b5ñù!‰5¼éëÐUˆ9ÇÌ̆虃Ýþæ”ë E…ÇÖÅÑLýŽÒýÀËžœhÔ¥«o;´yl4u‚‰u°7"ÂÊVÒ,ÖNÛh×/8»J³šû⤽îÓ°Ç“ræû˵»TèéÓ˜ûNž¹?LCwjÓMo¹¯6™rËN/ìÝBŸ*ëòÏ9”žÙRÃi‘ã« Zh—雿^Râ«üɘ¶éö>\Üj³”çG,~î£,´J?Œ÷²¶Í"ÇŽòêdwnÞ}YdFç (iÑòÔO Ÿ¼(PïÔH1ãn§ÏDä÷VÒ*^¢Žã© ®[¤éß„„Ÿ•—j–34+„˜¨_#^x–à¨j<<äÍ$ÀøØ¥ß‡02¿ÌÂx±Dï ¬q›ˆö[\p~©‰1.ò¿³‚ˆU“%¾Ô>™¡³Çà|E½¿ù$'F:ïV§øÅ[ʨo}‹ÖÚp.e-1g+n`´©•ÇŒ±»µv‘@²:瀎¹Q‰Ÿ}½®F_¤ GªÊÄBmhødì/+eyÄ¥ü¶$. À^+åG‘øjw‹ˆ!ÞI0ÐoM-ŒgÄlÚÍh¦>X2Dvh3Î5tµì±¿Ã×>nðÔÙ@uèû‡ŒÚZ!›عá¦A©Áüx=¾Ï7K]/¸9Š¿°SZ‡ ü¡ý@_ecs<È@JBHÛŠ'”[¥ý-ÏBRð¡ÃJ'Üè,ä¸p: úvhÖ D£ó mÐã%Z„7kÀðV¶X…syJÁ)Ë#ž F j­aVey6ÉV»ñbVbe¡ïÿ–g};eudГFѹ„¾¶Õ"Whˆˆ»—Fd>h·˜Ùz&Q¡ÌúÕž\ۉʧ‹Î½E“)ù§‚ }oµáN×@(•W?‰ÔYhc †wÏ[œüȺ&ô ¿jv Ï…b%3à TzBBÕ‘ß^ï§=°íðˆ›ÆúÊõÎݯy²Eý]Ä~4²õªò÷Û6ß +Í07ñ½+p»—-³³¯€tñÛ“@9A73š¦?:Ç6æëb0UéÁü6œQÍùè}†„Ý޶¬i J ‰0ÿT4Ðδè–†vÛ]@Ä«ÌìßõŽqÔw©ØøÔx…÷¢ˆSIDb4§l·„k¥^|.ˆÍ«ÐCbœyœš\Hæ "ÕE±»2˜J!b{g"2PˆRwغ6=0Cõî1%ÉçÍUqß0Ô!"*aum„aˆ)è/‰dÆ;›¯´– aá=ÏÃ#£üa#@ñéþå0Tú•#ØÛ¶sASfƒœTß=ÊÆC±Õ€"Ì/¼N"½~çÐüí³v'|b¬>ãBý‡ØÚ"*þ ³îµÆ£F\¾1Wÿˆ#}³bkñ³ÐÚ(?wx{¿Â?£ñë.~ZgÆ;†vøßz.2ÿÄãø—ŒFùOïùÝDka•/¿)ÌT¿C™*°»#¡à´ˆã)0†çœ$,ís§.ˆÓŸ[Ç!Éìf¥¡(x™á¦û4~ÖstH<Hõ5„…i£y§Í–Pè+ãõô[GP¨Çò £FpW‡"?Û°0òo[Aç§j®j¼ r†ƒ39‰2éÏšþæÜ ™AYMƒó(duIcâÇù¹hæ Ìäu‚¸7ó—óRDD:’Ÿ9#]ÏS(¢’k(٣ٸ? YcL?ôÒ'ð¥õ&'Uz,¥ÇíÒŒÏ×TkHY,’:°À•0EB²é‹ UC²êyê;‡I Æ’“½ÝX‰$·Ž´( %›Y³¤#%ë=ÙŸP }oÆ{‹Xa”’âôê¾Y ‡rà¾7kÒ¢.å×½l=Wé~7” ‡Ê.1?¹²fÐjþ¼º)0nÙMíï~¤`…aHØae¼Æ»Y^Úpý¤¹v2õOÀé¾cŽïŠ+¨œz‡ÅiÏÁÄk€ÙgêîÌ>ž¹0[ü°|‘ÖX}q~¶;ç+™€`ê©0Ï”ùÑzár×0´l­¾åìI¢Ò\…„x úÛ'¨›¹/Øiª˜ §l}í¼ø—fî»ýµ#†?ȼÎî„ãW¶ƒ‘'ÃT¨$LÀ•©•kPðÓ&ÿHæ^îâêz§»ô‰ºòõZ»Æ>ñQÅÙZ™cNò_±ßV;×gª“Ò+dß9–[ ­­ýÐF]~ìS¶ùCr]{³ ¾b~¢° ªù`c`”æ°¾8¦ž¶"§½ƒ¿F.¥±’÷:`lè4líµ­~ZX žõ]¤£=ìºà&IíÄ”À¢_dôu³@íŽ sF\qí‚}*‡È`~­§ÉÎh÷Ñ-ëPhBdosyó¹,tU”T Œïˆ¯Wò´<˜ì6Ç ÁŸgÊìôhØÄUœŒ×›ÈÉä>åó ~ó,ˆÑ²7eGÅÁXT/ Šó” &BEÐù „»ï –Õæ«ª2p|û\žÅÔ¾wãJÍíåûùpÔ-oƒW˜¿À®j¬%y1öñq©êš JÄ6ÐÛ±†î»FË“h^î*j—’Äg}1ÜoÈOE~¬k¥•jxú¶ÔoG'iÆ ÀÀ 9‹Cøçô0óz›ò Ozú#è«:wÎ’».‡üBAgÄ≠Ž®¸Ü5RJcÜn/Ê-8luúEåZû8õI7y.õ,h»üNpÜE*™aT€¸×Ý¡\-|³ü;»wÃo¥àLl­ü¶E^Gž<ØOîÉBIË¢¸ùG\X0¢ÀïÂ唤›ÞbîKÓ«,F⭾ݱÀþ¼Ýø½ÊωŠI]ÿàxµ×.€Çœx‰ið]Ø„OÀ±T?jxf,ïšr=Õ´Ñã±1ôT˜«ÒÍ7ï'SÐM&Á¢$53^-¬ ñƒäi`FÙè¤}ü@N ¾è:-²àÞh›õ†³½Žõ». àîÓF†Ó›ç­±c/›*»Në\hNüüÄQ:OXXGg2ÃßÞ÷ö-0:¤ŽÖ ÌÔ/s×Dže¥­y­Ré|á(\*Éyƒ¦\2 ¼‡ ?†.æÇ‘ž*À¯I4‰ârræÃ,Uâ€2DÍç¢Aøùh¤D‡'ìch1ïò@”˜£Ù$ål.«ÜÌ Ï›>HtÍÃ5º— +˜÷Ãóè Üљ쿟ˆj4¼{’k;I³e/LWÖ¼jõçOW³ê½ÅPN(U­¿ ÙÇAh¿üI „”Ëœ\”ÝëƒÀ¿Î[@¢w?]‰w?XÔ6¬=G¤?ugÌZc:±FûsU•I6—ð[§¨¤ï5ëç\ÇÏx[Ë8ºê·i‚žVB11Aâ^Ú&:×wž6¯áÌP1Žñ¥P-2Îa ¹±j*5#û¢¬¯|ÅDÚ—±_îÈñ‚w>È ż@¤uRÝK'6I¶“>´ˆ¦HÕ5Ä¡r@YrgsE6±¼x¡í»ö• "%Æ ùÓ%-þa´*ˆk†¾þÑÉ¡Ï2oZj|_ ²Qg$:²ŸX&F0CBdz0ý…康⑵¨ì @;÷ B'´¬QJ-cXü2T=,”h0²[­ÒœÈ¿º€`÷Ä©î K+‹@:®úà&)¿Ö¯ ¼Í ô{:›$xëQpzØÃ*zFòã/¡––*j¤W¥{l)s@YÐb¦z†“•@Õ ¨)(éñß‹Õ0@qÀKPƪa~¹çè hc#΋¾¿¹Ã-ٺ߭€óêTÑNޝÎQ²±tßêv«ÀBKù Aªô#IÖl ˜©†ï÷ؿִEZèO@Èßzeaš‚z0ŒFª¶].8ÁÄieg9 †4jB¬‹~„¨šðéâ)Gaœíð4¦¤$@ì^†TZÑà 9ðãP© 7æµé˜¿¢3¿µ…Ü'3€FÃŽ±šúÚ\‚?¾ü :†">$tjT ö#wÕ<=¨/àV»™À꯭†àzöl“*häô2ŒsÐË¥éõ÷éÞÝÙÎ%Ü8utÞ¥%T_\†ëíúuI°d¯·ÚWäˆÜ!#z9ô°´þS{íÅ‚ yù>Š ~£µ¹eÖÌè?ù*;ÅjŸ{[]zcõ(eÎv EËg{:f©Æo|zFå7ï1{Þ Çsˆ[øyWS3=cîëCÛ¼ ¼þndú¼Jq½‚‰ÓÁ?%«¾›ötBY`˱çáܶöÚî™B®'¯Îùår¯±Æá™ðºsÏ,{i¸ÐübžøýyšR±ök—,ßu%G$6ùë„æíïn ~ZµºéßG±G~Ü:¶køl®ºñ e£¤½ñ–¥‰¹&-†~ºåsÖFíºåÿåEùŠ0öë‹4N•Œ?¨ìe¨„s`Ǻ9j²kœN–´N\ÁÿMê÷V÷é¿?Øo®ÜÜ5·ñc·›£¤G ù5%¯Ëo6Äœòãüîµ9Rx^ŠCM•H£[öw ·Ì–6›øÏÍ–½ðöܳsõY:¥™gm–íË™¦vöž¯ÇJÛË? ŠßÝ»þÂí™-nïÍ9÷µI7£~cÛîø‡;…+H~g.ÌÉx~Ç”Ÿ7®ìfÕÊù<Ï0Æ×»±*N\õýÿûÍ×É<¸è?9ÍÂÙ¼øŸŸVi²”þœ”q~jÓ)åboßømGoØqÚ·ãXÌßnž2vIøº¬H»~ëóŒs'y—Ï»ÎÞ+n}JÚd‘íú ­Ô,sÞt2ÙqÈÚavµùíˆo~¿üåÎîµW={Ý_¬õ¼„ºÍÆžSéžWnm–´T²Kº'Q’”pL{3×TgžgVK´”I{0”-»—ç£uOØ?¢ûT¦¦Š½å?­·òeôžyþ<ÿÅ¥j§æñ¤¾>·æéé׺ÆØ -/$î>SÝrMõ¨Kõé›$ò&ο`xøì×SÞ¾ŒRJS›kO9²îñ®/mQ–ú3_åííËÑÿèãQu G#«··«ÆMy–¬+îš®i¬¹1±µéd™Ô¬m\<;”ƒŸí™£ê•7AÏ€BÀ5jÀ°0 9'5±¨$?7±(› u*Mendstream endobj 71 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 34 /LastChar 125 /Widths 303 0 R /BaseFont /NRIHBP+NimbusMonL-Regu /FontDescriptor 69 0 R >> endobj 69 0 obj << /Ascent 625 /CapHeight 557 /Descent -147 /FontName /NRIHBP+NimbusMonL-Regu /ItalicAngle 0 /StemV 41 /XHeight 426 /FontBBox [-12 -237 650 811] /Flags 4 /CharSet (/quotedbl/numbersign/quoteright/parenleft/parenright/asterisk/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/colon/less/equal/greater/A/B/C/D/E/F/G/H/I/L/M/N/O/P/Q/R/S/T/W/X/Y/Z/bracketleft/backslash/bracketright/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/bar/braceright) /FontFile 70 0 R >> endobj 303 0 obj [600 600 0 0 0 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 0 600 600 600 0 0 600 600 600 600 600 600 600 600 600 0 0 600 600 600 600 600 600 600 600 600 0 0 600 600 600 600 600 600 600 0 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 600 ] endobj 67 0 obj << /Length1 1608 /Length2 5186 /Length3 532 /Length 6010 /Filter /FlateDecode >> stream xÚítgT“Û¶6ÒéMZ^"HGé½#@zoЍ€4A:Hï½Hﲑ^DŠT¥‹_tßsöû;¿î9¿î¸#c¼³¬g>s>s-Nã;J”T …ÄÞŠˆÉôà®cRçŽ2 àœ÷Èxx¢¡ ,…Ta¡²s( îÞeddÈxQn>h¸£Àojd. $$ü—çW ÀÁçÜI Ü àÅ}xB(7W(‹ƒø4†BX'(G@õ ,4õÔüêz¦u(Š!8 C‘¨†B0 ÿj #‚ÃRÂ@Œ ǃzƒ¡n¿BÂ7(ÚŽÁà¾p À Bbq3À¢p$áùE燡~rC£p®¸Ì…ÁbÀh¸€«j ¢ö'O¬û«6Ž P0\&öøÕÒïÅ‚àH õÆþªå@à7ÈW憆ÿ¦á#ÿb @CAhŠÁà`pØ¿¦óWŸ€ÿÖ=ÈÍ áóû4êwÖ?9À±(&B¼‹« Æâj;‘d¢¿E C€bú!nÿˆyBÑ¿Äÿkgp$@á€@ad¢z(,®$€ÿ¦²ÈNäÿ€Äÿÿ#òþ{âþ]£ÿv‰ÿÝûüwh5BäŠ[€?î…Át¿Þ˜ÿ/ä Gøü‹ì¿'šCÿdø¯@4± Ü”Ž8)ÄDÄþtÂ1jpo(ÄŽ;` nF¿ý¦H€#¡8-pxïÞßb&Np° ò×Ð%e~‡ HÈß™ãäùÍ[ÔR[CÙÔPèï¯éï,œêX7±ÿêCù§ñ CYå ð»”Ü“Â]61q€Œ„LÀ¿¨÷ø—­ ¢áÞ+\ÓbÀß­ÿ×ÿ/Ëæo0ªH0 òkOŒ± $·Zÿtü ƒ=Ðhœ¢¿o;®åØ¿— õ†‚Éf&Q`¹pçä×)ØrÆŒž!«Îv AO„[A•Invp)ª-(9jY¦Øþ²,B¤zDöªÁçã–Û5-Áõ¾v_["t7‹5€K #›z·IJh=TÔ¶€"eÛ<ÆooBg‰ÐRRÌl}eÈÐÈ6ÿ’˜m¤IM²w"Ìå™LÇ}ìv3œTùœ¾™ª¦`¨YXnVgý¶+ µèP? Û¹¯øYyíÞúÝ‘³y¯³,«I¯`)ÜwY×¾Á†cc;5µvƒ?-øjä?¾õ½a¨HKôS¹DòÖÀ°KšLÏÛÃÕ7ÄMå Q‘÷Á9"çcu/’´k†ÊHãÔéÌ1^‹!Š|Å›ñø§.Õãñ9Aá°À …«µÑÍùžyè˜ÒšÛ¢ß) ±•ÃÛ'<nôYQѬO¤\Ò§ó•»*Â+šŽŽ<ó'WÙúîé.Ë ΋%&°¯åcžÁÑ#ÄõyE«¥ 98„¨Mn¥õ‹Ÿzð÷§ á;UËÞ}$7 4zuÓòú:p^3΄-`#Ótº0 b$ê¤àˆ`âÑilT¶&’£'¢Pš¥û¹R5¾›ËOjym˜Í`”¹C“”M^÷«³÷Æ‚)0ºï˜Ñ7îªÜí›Ê¬3TUŒ>Á{šã×Kܽ?8™7)}ƒÿøÕwrºsÞùQrqè‰Lš·‚‹íµµJ« dŸÆŒ¶u©4è¿û‘:П²‰z]ºçŠt°9N²J!hûVUt–uÙÇ8•(uõ’‚µ65[^Š%ŒIúÿ7; âù4®)C­í2jžJ@ß-*ŸÕÜù˜²#³áâ‰T©h'9å„.§]g&hLüõu “Ï|š×Ya6kŒçLwô¤Í".”²§EUнIõDT‘VjÌŽ98¢kÊÝm{¡ALôSÊßf·¿GNäÎãDíO4;gÚ•è=ä½+vç•–KRIÕlÒ0ìÕ¢¤ïu?fÀn0îL>¨=î¹_? ÁÛÑRMÈ­ujÖi /Õl¼îl¥ è@{WÑÞ2uízï_°»ïèél|çT©œ(¢•6Ü#áfG1Pöƒì(r+Ù}ûèlBô¼{½Ýü®575Ôªç,hLJõU«‰ ¬–¶$ãt¯YÎÓê`ŒÀ$ëíE3^®mޤ;?ù¦²zÌx£jÑ£=zöÉ(;Kg›Šî–tk÷1ñ]º¢{ôÉ{ö~+löŠq•öJïñ_ÓUDCÖI /n@Í|µ}Ó'ÞT/~¾Kë7å¬g”Wð0²ÿèÚW*0Ñä^oa‹%ÁgÒ²¤ü”’`í³¥9M7|ç9ÎÐ6ÉUÉ/aIQÓ'þI^t6g.‡DÎ((ò¼ÁÂÒ%®šTZ~´k›¦³5»å»ÖÒÑCSÅê«§ 1LÊ3[¶î²Ÿµ;mÌ„*ª|(»{r»²ÈMê»ѺzIÊ – `˽Õ@é‡åHS:¶‡{»2ó¿ìxÞ™AÑ„/Ú1½r¨Ù\þ¸×Kç1ýèòÇmøá–¡ò;ÞϬ'ªëIÚ¼»XLÆ6Í—ŠLbNg¤RQløÊ¤0T<³ñT`V€‘"BˆP7•ä’XÐð}_R·íŸ—¬éÒì9¼ª,K®¢»ó91+{Bf‘„\Víö5DêÍóëjÞmôfs¡D¯èˆÎE©+[¥Q±Ìé‰À æo÷t„·/ÖÕô¾Ñm”à×Ò(òŒ¯'=#Úüºï‹½¥Ö j…¹Ù¦¿Ì¾X£P­–_&Ujc ÖåÐ'Ù ûÃ<™M8Ó<¸ce7ZéSÅU°=pœô8©Ï¸%qj‹:Ï¢=“êd Î&· 5T¹ŒL¯ý¤þ‚Úyª*&K²^é-T•˜+eoø·BÜ´v2)¡Ðfå×-I„މî>•¡¥¨ü˪øÏ¯WwŽØhóX «è±•çOܣ矣üý €G™…ÀÒ>gùZÊçß5Ê$¿±s¦¸^XUk¥¨ÈWáõŠ$ã+»ÚÅa+¿UÜ£‚ ç©ÂóÒÁÏäXl-*mû¾¼ü<þ~¶#zYª)¤ÉwúqHÁ\§àåÖª“U¿lžOô5RN(¨[{ñÖéÎýkIòØVÛ-õÄÒÓÐÅW¸“¾–4]_L±õú^˳wvTkPµZíÐö" ¬#KÙÃlQÞBõßÿ¥E]Õ=çw?¦{g~^F“Öi1÷hsÐH6ki‘æ·ááÅéÚ¼óä½K13ÎÚÔ€,éª0‡?ðä¨ ÝYE#·{²Ð¯e†ôÞkç:o0RŠ™ËMS'9qlÒD,Ž¥‰賊“ßÌù^2»{4z`‡_F¤¡[ÂÞG, ®×oõµ?`.cÛ?í2ŠÇwX1Î|Æqo¥˜”_ åž!\0ÐW)6Ãu¤ë"»\¹¼»É,ºÓì£?4$" ö¤\H«îX km¦þºØ%„vûÇJWfÌ:7}¾·¯a]öÂ! ¿íUö9¬âÜBj ´9”Ó¶ù°ÓšÐ:Ï‹üúJg>ÉÅMÃá}Ë:®¬£!…=Zêå„Ã|x‹]ãÅÍR%·êFôo $rZuó…o2—5Ö5\®iðRI¥||KÃòÃ:YßðõÎr‹ˆW‰bد˜kMonú@`&"Kî;ù^û(¨l5)†9ú¾ Zÿ– <)¥sŸ.†d$e»º¥"ÕiÕ“ºû¸n2C—½ä µlê "¡ò™žJ§ùU˜5_ø¥AÕ§„b5ÄêbšŠ¸IR™¼Ë®?R'#EŸ}.•¤Ðã7)õy`Œ]¶Ë~;ñ–Óo>¢»²£(¿?,ðîåøXŒrpIÅŽ¶ ˰eQõ•¦¥¤ÝC­ãžï×ð’Bbvåº4ª¥²€*ýÍâ·ÃWõ÷–­ðRf¾ú±š©ñÎhsMÖJ™ò¥?|ÎÎè[Ý#ĵ|×¢DÜBî&úeÏá5nÞ›dÚ ¦2 zs;]Õõj¤ö4Ý…V²˜û’ç…‚‰§Ã×^­«@äÒ$ŬˆÇÍh› +œ‚ˆå|½ßT|>Êôóò»Ýj[P;}ààu;ÂÃ?‹F<Ç©ÆðLµ~ÜÏÂÌf¶ÿ&S”Ì$Û{à0÷£Ç5¢«ÚýÞâ…µÖ˹\Ó¯é9Ô)µ÷Ío~ŠpØæH™²w·SÔ¬©O[û Ÿ:7>/´½ ¸ãë3kŽñ6RKm%!ð3º¶(º{Ç¿—âÇ#Üý°ïå«L2\™Ï,F°n±œ{¨F-kÊË’màp2 °m–D÷!#uÙ}« üŒmÛRxkfÇ;kã¶´YW¶4áK°ªé˜èÖ¥G³µâúxp+ú©y?“‡ŽbDì³—Tã…a5Ù#DDÃ< ù7$~Âb›"½/:M–¼¿_–90xðú“k7FÝïe¹ÕßÀ˜~Á7ò§f»<0­ žvØ#6,Vq]k°ßØ*ÈëmhLy"{âÝÈžgš“ó¹Ô[g¤Î}œ/äýM ø®5œb¨VÄ"b÷„(å~N yöLër±V»FpJáf5~UaÐév)Óø ²Óø¾Çûrä¬éý4ŸBa|CÖè+¯v*ï0‹Ó‚Ñúñ¬òsCÆNŽÊÅ”aF§)µbû±àI† ½ë:›ñJÞººè»š¨À·::)˜w4|೜@Ë]Ó)â;3…e)j,ÑUCåti{›J_µnGÉwtÍTA‘amˆ3Î)ÎŒŸ¨°XÑ5ÑÏÊšz í^Žo< Ì ":|“Éižú$ôvË^`Q]£½ÅNâ)UŠr“ŠÂwý¸¦õ"Ç¿¹7spœäàk])Tõ8£ë÷F[ó3~’AŠäËÈúøñZÂ)_û×ÒduýÑw¾e:´f1'ñÔ¨F6f1.¦}\”bè.ë×û5ÂÙkµt;…¦VË(£u9‹ {{UB¾ÙR%}hš^ö¤Ù]öÆÜñuË`ê÷z<îÛˆ#<<ßDJøM-‡µÛ{þ4 )‰~ Üe,Ú# ÀßvR™[ÛK²I½q²«UË,‘]å…÷úñMÝx““ëï> endobj 66 0 obj << /Ascent 722 /CapHeight 722 /Descent -217 /FontName /ZKHBUQ+NimbusSanL-Bold /ItalicAngle 0 /StemV 141 /XHeight 532 /FontBBox [-173 -307 1003 949] /Flags 4 /CharSet (/A/B/E/F/H/I/N/O/R/T/U/V/W) /FontFile 67 0 R >> endobj 304 0 obj [722 722 0 0 667 611 0 722 278 0 0 0 0 722 778 0 0 722 0 611 722 667 944 ] endobj 36 0 obj << /Length1 1647 /Length2 16930 /Length3 532 /Length 17870 /Filter /FlateDecode >> stream xÚ¬·sx¥_³&ÛNG;¶mÛ¶³ƒŽmÛ6:N:êØì cÛ¶íLÿÞwΜ¹Î÷Í?3罯½ê^uWÕºkÕ³rb%Uza3{ „½ =3@ÁÊÖÄÕYÅÞVÁž[Ž^há*íblø‹±Ã‘“‹:]¬ìíÄŒ]€<M @ h `a0sssÑDí<¬,,]Tê*šÔ´´tÿiùg ÀÄó?¿žÎVvŠ¿?Ü€6ö¶@;—¿ÿ׎ª@ ÀÅ0·²D•´¥$T’ êI ÐéoJ®&6V¦9+S 3`nï°ù÷`jogfõOiÎ ¹„Æg ©Õ_7 ‡)Ðáˆàt²µrvþû`å °p2¶sù{.ö+;SW³øk7·ÿWBNöwØþÅþ’)Ù;»8›:Y9¸þFU“øwž.–Æ.ÿÄv¶ú ìÍÿî4³7uý§¤aiþ¢.ÆVvΠ‡Ë?±L€3+gcÏ¿±ÿ’98Yý+ Wg+;‹ÿÌ€à´0v2³:;ÿ¥ùËýÏéüg€ÿ­zcÏyÛÿk×ÿÊÁÊÅhcÎÇÌò7¦©ËߨVvpŒÿô‹´¹=€™éßv3W‡ÿÀÜ€Nÿ: ªz†úoÆföv6ž3 9£‚½Ëߪÿ;•þûDþoø¿EàÿyÿßÄý¯ýo—øÿõ>ÿWj WcÛ¿ ðï9ø;hŒíg @ðϰ±1vü3p¬Lÿ?®Æ¶V6žÿ'çÿº[øï¬ÿ'ç…ÿBØÎâ¯BôÌì ìÿ6[9KXyÍ”¬\L-æÆ6ï_vu;3 “•ð¯Èÿ:ß¿NLLÿS³´2µ¶ûG öC@;³ÿZÃ_ÝþU£¸–ˆŒªíÿaÚþk³Òß®pQótþg$My{³ÿµø‡JDÄÞàMÏÌÁ  gádú{ÿ^Gn6ßÿŸ°ÿ"bþϵ¼±‹“•@—‰‰‰ð÷û?>ÿ¹Òÿ/4âv¦öfÿô‘ª‹±ÙßÖû_†`SW'§¿Šÿkü­ü?Öÿº@ ÐneÑÞ”7ä{Fv¦K-ö¡q1Ýß½ÌàC¡e jÅ…5ö=þÛÜ•Fï¿B'y>Û<N>öeh†{±l({Ò€—ø¾¤Ô}…¨œ´AŒeˆ™gš1ÞWór[:L;ãÊ*¥ïP“¬N0WOÔ¤n…dH~¦éõñ˜( hµE§gÉÇO”#†{n ûöñhóâaÉyÝ )¢óðuÔ+½ãÐååš*'粆ØWA3Ùú2Ê^Ú.@¨Ê ²¶!ˆ·–O‹:xeåöõÉà¤Þ 8°Ÿò° u—õUåÞ?ÏÛRJá}ÆEº4Ü©õØì‡h× o¶}+V¨¶ZØÔ¯ïÈ`.̘Ú\°-yn½À£0íí¼íÝ•ø–é×îÕ½ø¦î‡µj¼ž®.l‰ ƒED­S$”šf``dœ*ѱi\¹°#Ùñ„ D„ži¿…7Í9àíæ"g¨|’ X빦õÃçCÃ3ÞL.r£`Ï*ðˆ˜ÀÈ~~ Rž®»h;®†4$ÊÔQ}IBý°îà¤Aß®L¹þí)¡Åå8ëÔ£x 9ÎuÑ?ê(‡mwÚ~`ºPxš “å³ñ[‰¡açd„sAÛ% ýööŒ†¥û‚6ñ T€’žÍÓ"ÜÆ²FNú*jæÆ!Ñ\Μ[&7Ïòí•yÏ¿Ïã,½¯>ÿÁ¹ze©·'EHí,ÿ\v¥&¥[ĩהÇ)êÌ×ÅNÛ§ 5¬û&“–)’ø‡©&ä lͰµÏÖHƒà¹Ã«lã3UúW a¤ˆ†ÑMá, ª¤=d0WÅY¶É†Á,ˆ^ëJ¯}¤øÍAHíV6·n|WØðz5•BxCú“üË_—¸Ki_œ:„„×5x£÷¡ï5;QçZúßrîq7Š ¯k‚#™q2¼ÏäóØô(ÿÿ84Rm„ä\&ÙS¼Ùî¢Â%|„Î@Ó>þ"T¸³$Á¥U¡èš5{¿±Y[èñiÔES•ÿ, ²YeÿOž…•èÄ€i§"˜w½š¯ŒümRO²õ¡[÷Ë…ìd-GÕ&œF7:Ïñ‡i;Æ|0±ò2Ÿs†R(ñ‹¡ÃÀô˜ÐFÈCUÚ>ÃFéúÐH7 7²i©À‘ãkØÉêË÷Ù;ûÙ3“)’eá” ™† ÿQG“WÇmƒ²‘Ù6I™(¥Åäòy如EŒ, ŸÛ¥o²fšµ¡·Ûˆ™¬ï že9,¿ûÀ™M#w»¼/°ßXd¬î F2Ú@ÁõøA!Ëà+~q¦Âv74:ëÅÚyUø±ö–’4íI'ª,RµËùmå¡’:2¿ø¯f4¯Æpßøï2ˆþ°¿/Ø<¬Òâ_èg[U6¸Xº»®#™½q¢=|SDŠEñSH9¢w£v­é^–I£ŸÎW”µA‚ËÀß"a[ÿÔjÔqœ?ùØ‹ô–XìWµG%•”OîÕƒnµü1¡‘¹ßáf4Êû•?#:ãJ0ýfñ…²¾‡ãwB‹"‘™3 ¥³Æ¸Íôèhм›ÁÚ «•†º"©¹A‡aå–ÉR -6ˆÞêÉ}µ²Å<@cÒkh}³Í † ¿ÙW='Ê5~‰ª½Tì%qÂó§×uñªæÅmKž¤oþ´ñÊûטÊiß½“T…eÉ@Õ˜…R'‘Xû‡ÎA…^Ü1bvÙ,a‚PR‡ºm~ÂYÁÒª˜!à¤Þ¦ÞÀ[½ð)Ï§Š®xm2Ö@ŽáD.ÕÑúq"£±äÁED$Û¢0ä¬$¶c 2(íŒ|óäz‡Žû¦eUâ¾9‘vL›jÆ#Ê` ¸jŒé{•î@ÔŽ8ò ƒ ýª¨”Åü–G½ó©ÎùX?J²=²³F÷&™‚·’]~•JY8ì¢'‹LÌê»Á”ܦ‚<˜«—äN=œÂ´*ipÕÙšw¡!Æ6IyæK´8®  ^@³áƒºß ¦³)Š4ãrá\ª,Àï!"ìßì¿rÜÿœ¿ƒ\zëvÖƒ'Õ‡´K•u\Ip[u¥!ùL‰ž ÝÒ££Ë'«ê·‰"ÿ=•[Í:·æÌxköj'¯d Ž{­ÅË-‚ièJJ\ÎW,4a¶NùêE„ª‹™h`@ÓÿVåóˆ.’|·ùl±íÓ¦¼óxzæèü-—Y‚U®&üºà÷$ Î'™@ â$ò-Ù;G‘Ɇh‘)î†è^l ·0ð¶ÛÅ…Ò×+*Zïãºë¡¥b ˜cb}%?§¹‘ ’-A‚^†Ð$Ðr¶5ò)?Ó`Xêз4Î0b¼3»K…ï"’Ø­¦·›"`Ж[á¡èù³åõÐo\Ç®£ï»¶^wþÀ%<—RAau²á×=Œ-­?JM³LØdœ UÕííî+Òk¤»’}”^ïE(Har!†åŠËýìôÒøüžOeÍHiiÿ~0£G8œ>OUæ/r9;ï€]kÕi€ÑŒÞvßÔÅIJ3\2ý {*¿…¸ üZÕ/GþZèt^y'X_Û½†ö‹ïR<=» GsðúÀU.¶XFHØÚÙ’½ûúWâÆå2¼$öôSL¼ßðÉfîÖ@_-¶ŽÒ‡á­du•ÖšeÝq®¸ôâ±ÑÑÁôÖŸSĵπ¼¦LvÔ½'žÒ§¾0TÇð£ÑÞœYëcüÝdÐüJÐÓ ¥¨ø» ª"8m>õ2À_[¦‘£GýÈ<«3©C”tpÞQ°’×f§è·ŠÂ…ÜŸ¨…l¾¸W×I»F© ÔB—6î?`BÌmL@uÐýíRAÓ“˜rVF–÷µˆ.ìIÅ ƒ#¢yûŽ>ü¯lQëa4•+Ïü´Õn¯"Òx^ëaµuHÉ£¤÷bWúÙõä€ô)(8—¡ŸLiؤ¯-_‰2ú#ÉjšeF<Õ«cO ™XsÚùônŸSìgheCÓýYk·ä 2Aú”ø¤Š(•ãÆjþ‹ÑjK~XQ Øky$¡€Ú ôØ%c£3¾p2ÔlÒ Ý±Þs×étùÖX`ب‰¶Žš’1ArôFj–oñQ…âw$\ 8ŠÉhHlÕê–t?ˆI›´½Xw‡_à ßÂ=v*&Åt«XeԦƂïöÅâs‡I©©-2óÛn£Í5gî¬ak­RB+­™°üá`ñ¬Å'–˜j ÕõI…‚f¤¥Ì¸Ø‹¶Ë^sÿš•Z«‰BkìÝþÜõ’ µ °)?æ8Áø± no›½6ŸxYµ%Ô‘6 Ø’œ]‡±’mÐyn^L>‹´î‹_mÆÓO ‘C%qЄ”V+|ç¦0º)CÞ~Î_H®*E#(Χ_”Ý5£FØÑâ•{3;“Àô×ÜVJw2VHÝó:ÙmëÜ«<´éþiVSËvšºÉxóRqhÙ9ýZðlHÞqÌœG(]Á´*Å•tªÌQ-liÑ5¥rÍ•ïJñµE·U" ð(œ ´ý%~C!¿È>< Á%žëmèßA6§¾¸ªÑšdYÚ%Ar:çÐöF‰XâÉ"Úø¨$S FïM:gƒkŒY n 88½7¶©2 æ®&Hf»ÿî$ï/,%Ý<1B¿°€`ÙÒ¥­¼x7ÏñÐâ‰9,öe R©ç¬Çå_¡x‰¢å Õóï®&…ûAqâ âuÒùÓ ·ÇÔÃ×óýÜ35öYƒMê; Ý`À©Q¤¥9&iéÝL¹ßŸgÈ}nÂŽó¬;rø4µuîûÜi˜ªÌy<‡Î{9¾*·*X;¡y¿æÏŠ)àò0óúêhv ŒÞæAf¡Ö_“ÝÙx»°£l?ŒîÿÌ‚”4ÍØæ'’Ò¶ã«æÆiyãmÓÒØÏªÊÒaýæ* ‡$u~£\F¹w[‘ %äò@úæ˜C†6pý´Û™*²1þAœyá&Æ wúõÝž'•°_Km³YÓn˜ª[U&ôH…x¥a±j•‰^öMè% EE½’T¹Žiò¯³Ó)Ì!„tT¡<>Ÿœ†“ZLÌáxãç-ù¡ËéáùJÖ-jŒD„V i³›C.w5®ÌoITÓw‚©½=¬pöc° ÕÇY>|ÅÂ/Nƒøï°YƦkùXCMåpî|ê^ïn|õ?wnXê–'‘~Ê6:¯YÝFC¶tqŽ9jù™ðÊ´‘ñ6?04¶ŒÙ¦¡þûã©[€µœ ò² ³vÇÖ4ËH[ï»/[‡=4 Œµm¡¥dÍ£ ~)&=%¯2Ôª« Æf„Ú*ãv ñáýçL^‡‚dÈHØ¡çUÊYªI'O˜êPñøîNIfÊÿ§û³Rf%AdòšñŠÁ»Ø/†xOý,¹Þ±…äXåKE5ž@‰fN$w£l+ˆ@>ùóð’‰ôóUmWëǺjeu­q‰Ài~^)2ñ¬t¾Ù–•=äHË¥¬‘ö [¿¶!ÂÜ®\Ü{«ñ¯™®hù;Ñ¡ö!-x_×ÐQé‰2?òùб%aùΖqs)¯8j5µÎ‰–!-‰k,d2ßâÑý%„•曋Ôrš *ƒ Ë^Ïoºž~ŠjåYDÇÂUÃp{ú&íd×ç|nÁq„º)â!Ý_ÉêÒ"î{Ö¡eÇ{kâ1>1ŸÑl¬Å`±¡„“‰Gaâ³!¨S"¾g‹†\Úgaª~:{ᮕ¯\§}R=|…Œ–«›œî/0¸k„1ÐA÷¡ìÌñ_wùU]%®Gùl'D#ç[1$Ï­9wàyÙÞ½×¼Ôêåc'_»‚&c¯‘0¨Ó²CåëÄÞýь۳²Xâ3Šê( |xøñ¾6Ôý¹0ÓÁ½+G':rÌnDRM3å n…ÉQ þ}”þ á˜/q ÌZ·'ûð ÄyJÒ†2íåoª©ç±ô¬5ii уùC·a=v/-¡)“‡¥ø?ÞI% ¤`ŒclÉÆ®"þ2¥€&o=³cô–©åIT^wi¦öë%AH|îÈútaüi¦±Ãì½sjSè5À§ó»ÄpKÞþ.†Èn|UŽô˜v¯Þðzgm7f²€÷ª€e·exxí 2Ï”0o‡ûø­1ó›-ãO}”×rù¯82¤{—ªŽ¡ û£¿uŸ¨ àñy <Š£ƒ e>UáÌíNj)uëS}ˆ,bs.MÓŸÂkmS Ÿëüís=Y=r=rɼ\.…ürJˆ^žF=H»S_.'{œÄÑì¶|çážÍ"çÖühDc‡A‘Cc_xc: (gvÕywj P„+**zH:< ÇZÒ¼P9îí‰(®YïUz0òëÐ7WØ®¡Óü8¡ÓD?øS<ž­í‘Æ3ÊðØÖ3Ùl§â±f/ýD—xat[š †ó8Ï2ÕUËœ‡+Mc´ÜÆŸ¢èmÝHK9q_Æ—.pÓXqŽâ¾¡:ïׂµIÉS©®\”eŸ\«•Ä·_dC¬¦e1ã_Â/™ÄyKôú¡Ôh«àõ“£K1xRÆÉòÊ„%Òóþ}ŽN¤ƒP=C\ráA¬^™‰nádTZ­¢£¯ À…}|Û‘pgŽë¶ZÔ8 8TÄß;QQÞ3Ws^ÕÚq‡|w,:º¸wÛ¹z«¤o/–t{œã6VÙ¡ëaFÔ¢}o7¥Ö¤ÕKæ <ÑÀ0Å¿ùLw¢‘× ÞÈ`÷,‚«¹©£ßä(˜£ïx"îÚkªLmŠC'´k\jE•Ÿ:‘0)k¹æò;Є2㻜+AC!¯OÚÔ‡õí êÔ®)ùUÐFàìÇæúVùj¡'ó1L¼(n$×`®ï¦e`)›…–6R5–ûŠ<\£kûßž D9'öTø¶G­=‚µ@çÁµb¸øŠúöæ!|¾$ñpXròvÒ¢Ÿ²q &4% ´èŽqÿö[ÕˆÏzÛë{UÞ‚<ö…XT¤~öŸPÞËçÿóG{¶œ¦…øYú}÷éí^$FüRkU”@k%Îæ÷•>D.RV† õeíú)ë$Æ•lv&D¹‹­‹›UÍfŽð¯ì§¯&KE¦\þtߤPÔ2¬×´ØAJ_—0Ò—E1‹”“ûÍšï%”‹¿}NéYøéTf64¦øŠòÄHFËí®‘Ö£nðn¸Mü˜8 |}c\Ç’œŽƒ¶m6Ð2¬®‚ÙèÆä!¦èòfiøÙ6.ï—²qS ÙF· d¼¿Y⬃´E=5Å6ZWÜhÃP³´ö‡ÉMWcv†Òšë„YÚFŒ_©ñª¯§à3;„íþ¹”8;Æ|4J?^6 ¢Ú3Œ›ÖƒI:Ùe Tv}è¨è@HÞA˜>»ALõWÛn©‹ÏübÊM»mÿžËJ^Ëæ´Gâ)ö­”^*۪Ҍ&k0Qï·Ù}d8Ÿº ÒŽ”Ó²T2 Eê•poO?SS͹ ‚jòÚ㊸7ñ4E:-È7J9w$"Y8ˆ'Ð’÷p^#(šƒµ_þ5CûªÉë_hxW¤1`!2ØR(Á„ÞÙùCœÜ†›ƒžwµ…±BîLK’éôuŸßgê÷ëK ~þ¾²UêBµíÑ+Ö¤:!#EÕ!Ÿ®W¨ìˆ7°2Ô9@Øê½åsÙ~Œ%¥Ë6W„¡ëqºÚÕVÒ™hA‰zù>µªz÷´£Î7}‹õ¥J‡2ÊÎ[ªÌ·_níüY¾­ó{å~»vÍ”d²õM¸6âYÿt¤˜Í|Rx¿ý@‹~™pä ÑÍç^Àî9qMtad~ùJ—ô!ƧK~r—o$ÇÄy¸¨Y‚m5‚6°¨ßÅžý¹¯•ª'­òçþ ê åg1¸Q ç~ ÷pAÍx½¯uÄŒu,MÅó m}øØ¨çœ\ °‹+3Üuðà"ocœ¡!NÖ“¾ˆYˆÁʹH«*¢8ýCY!yÅnM~ü ®ÑÝÎ{8÷±4/Uµ€ÄÈ6îóœ¦, Ï@d¬Ø¾¡5êš';ù{¯E£!„|–Æè¢äà§77õ2M7Ée&ÈGªÑ> ý¨²+”Õy³ô<¹%›Í*Ó1Ùˆ‡¦Ê®ÕIè+{Ø `«Ä®¯Ë`o´\kÖª”a))Õ|îú}žã0±Fµyj¦•: ¶WXŠR·‘ne ŠzšÛqT;cÀ+èŸ?_?¥î¤Š*r²$ò9”ôC]ã)Ü|§k©³IÅ•qÉѬEÑ17÷"_Ô±–Kñ ü0º3ïíÈf}/ؘàL2ªŸcwÊ ®DÑ–©ÈHpŒŒÙÁÕ–}zPc2+4 È'+4ÔÑÞ9.áÆ)9´*G"è Uw^€>.œÇf=ZË~VšS¸i…­91Ö|®>¨TîO?uúdGÐlúR}³ZR©E’¤ ’vXÏŽc^Öd5 ãxZ0|e-ÄšïsÓ²ìÚ@-±© (Ï'[$'kò øñô(i6VÇ1¨§C)a,ž†ý¤ æ‡sOá|¦ö Á%ëÀ‹y†IÊæ·}ñ5”âÂI™Ÿdh܉zÑ£­[’T<Øj·9lÃ…XvÌ÷øÉ4+¿+È Áf•»ñIKiIS©çÎPP~Ð5êW¤Ô ”üßÚXZ¡IHˈr%ëÕ¯1ßÏ×~bc¶2@%ÈoC.T,c6Mtì±lŒÑìbÕòý1Pjt6ÁI6ÚÍÛ^zÈkÇÌ„XŠ}Ù>8AË{Šzñ³ðɺ‹8Âd,(]¹ƒ’'„lJ lǽGM’¡¯\–È»¹µ^&Ôàó[šûƒï,¸C0¾¸…qÜ%œ}ýµE‹µÇx8pÎ>gwK?ûâhU[y×h›|^%¤¢}¢š,„šÉ¿IMÓÖžà&°™šx¸¦:xŒK…ØÈ˪W4ä+¼ÆÝúb©˜…eÉ º|= ¹}Xï¢`Ç–îï‰f>,¢‚Õ\¯³ÝžÛˆE,޵1ËÄâ;ˆ¶Úu€tÝÔ¸Åî??Ø~¶èÉhQy¿0TÁò}–ú¤Áã.$·aüÅ™øéãc¬ ‰Îìú] ­ëíŒ ;‘M^Ò Œ›(vEžüàÛ„éfT1õüÛëªyÀs²ÏÇ@ÀJ 9†Â­4Ô’qDÙȹT2c6sŒ+“Gðcöº. «Ò¾/þã|;æ—Ìù"ä b¶ ÒC[c´àY;(§±3ÕߤT4.#Ÿ×ÉRÙ9¥¦×gN¾œÄÿH“"Hp2|'…Ë­u÷¦ÑÄRWÕ¼m­º¹BpñätÏV=O±æ$ªÒ‹t Ãj´ÐèBf…wDU¡ˆH?„áåî Þè÷ÍÖhí]ÅýŸßc¾TÈ+]ø>¬„0O“7¶WA(PÕú ѵÎ÷ÿúå¤&·œx8“ˆo îaf|:ƒ`¸¥Ì³÷ñ†ÿ5ŽVÈá9êCu!S?µ¹¹vNáïm¦\öCH¸ýVõ³Ñö(BapõFS |ÿ~up”V’£IýÆæ›¯Í`7 ÌJÿÃNÍ›+ƒ×@yF'[ L £.Bª±Ö ÖU®£“ÌšÏå÷Öpãã1§^âÛ ¸–°›“V‡$=­ªÀá-V(:HtÃÄdÜ4¨ï¯0|ŽÀÍ*7³)쥱Э7Þ"8ó:l1íˆxLA‹\00j2²þe÷òʨeÔ3Y˜Â®:3~Év"UÑw{Mz* °›шù}…!ß­y°~ÙgGF00ظ|6pÊêWO$•moÌ+”;'èfçKÌyX[…r;Gð©ÜÖz¶è;ΆHøóP'’Fç8N›Ïí;”2_¼p:|%µdzÕïJ0·À)‰`ÃÄY¶74é²7ì›X¢të§”Øs‹×yç:„¥}Нï ƒª1œ‰eÄld*Jï욊>±À‘,–îaXÇérqàTsúÂY¥ç%ªÏxJOøËuœU6lð¥ýH Y¸kô¹Ò$‚Q>ÖK?âýæ•)»@éø.á{_8Ç“c_ƒk&·m Ù·U©ÇðÂÄ gEv9®ˆ¶F{º&ù÷c2báà%~Où䟻ה,“Z Œ³?v9޾/ô«£„Èø4&I4Lõ8`¡d«³¸bÌȶ'ð ö-VÌ—Kï"oý sŽŸìWù¸)F"µöåqÃЧ²õëéª!ÂØvcsú’\óRs"‡™À­Ì+6†åÎ@ÓÊÆ¯±[ Úºjœˆ ÂZÖ¼ù‹+mâš#\À¡I®Ô·Àr¥ª_¼Û…9±‡7R<ºï5Uƒ¯JœK…–u’ûÍãc©×€Õ?Å6o7­Ú~E…) 9Ù¶w ÛíFM–Ì"žÒÄHnKÛ_™Àd/eœËþóV=èÛ›Uõûn¼¾aç·M-›¿lœ8I°b¬ùê=Ëë…ñQ m½a¬õ?#¯Š!‹öF´ò9‡+œ-,4æMðsª!EÚ<½Å­kÙ]:ˆÀ;­ÇÚ"Î:Ù®”‡zxB“ä/¡}d´ùn}‰ã7ì3XÄý)ìÜ(½‚c·õ†% xÁ„lzjÓ+å:ŠFRX¶Â{{Ãk¾)ÙYÆÙ¡Èñ“=Õ©™Øi½I†%-ŒS:½é¢õO£"|¡¸~Lª°†K6Æf--(Ù°`göXá®ÎÛAKµs%ÉaòUB§;ÈÝ'hhñq û·ZÕº’Ÿ|Iobæã ó¹9G¹ºÓMÑŸW·7Ý_EõIì–¹1h/Œ4B$ÒptXú† TgŒŽÛ쾎—jh¿z<½õ,a²»•ÆØN iy^ïI½I߬éVôöò ®Q©´P´avL+xì®ð]è…!w;ùÖY‚‡8RNö°FÙOH¡)4éhÓ´æ+œ^kVç…u»›” dW"T(u«ló’?xéêuN/ŽK ²×@Û 5õ>\7î•Èð &*AÎß•±¸ƒÒå@·.fCÅj.1^Ç¢÷ïmÁ¿h¡ŸýÜuM™ë‘A;ûÝJ3¢ðIÿ´¦ /Ä&¶¹·\ Òd@Ý{¸ÛÞjG°åuaZä7ãLë`äF°)§Ã%}6D^ú S‹°BZ]m rJ’?˜Šp*Ë´0À¨UÌóuF,¡žä¼¸²%Ö  ˜ãÇu*=ÕÌ ôñNpb1ói¿äû3/Ä4$îPò¬‹¸×–à%Líþ²r÷žüÞß·çýý #I¹˜Þ7TÝ!L‰<3#þgÝì\©’¯Ì pÁ*9_lkÄwÈZ©onP w½Ž %/É!Œ ´ëØö {ÔÁ}ÙM ÊQãc³èwbú'B©TÀgI*ü}Œ“僋ø'ÈÛªn>·t¤ö¾!:À É&òeäRÈ‹_+¹Ü”ý$æûS˜šSñâ½Ç¢êÏ-ö/.]E†Ä¹#ŒU%ò˜W"SëìÂ*š*Ê®qÁu5Σ·¦ïMë¨ÁKÚ{®õ®I ‰ÐýLª_$û#ÌðeQ.à¡'9&Z?_ÃH+U¼v]g.$K19ˆ` Rò»2’¦]’mìôö'±N„™djÑü4÷Žt‰Åv”Ú3t ý0\1¸RŒžæ*j)ýf¡ûy^ô+Ý—>ÎzeÑ*5³ëOÖp!¯:ÞšSÓÀÜ]x ‡·J;»'—ròœ ŸÝ_’C”0yxA‡Û@Ê‹é0Ò>ÔED«ƒ¥$ g÷æ1ò».œ¨.à‘ò6˜D >=é Ñ= +ŸÌ¾©¹gÍÕ±‰çoc÷³Ó¾@ìñÑ8)Qö–Â;MûÀºNlÚ^Õ¨ãJÜ ×´vùé¸6âÇ䌲,oVèa—(5øÇ&^¬Á ônKÇS7Â]ò÷²€:äñ'ßQðŒCŒwžfù0w±È²åŒ|MªS+KEÿÎ@q®¹( oP¹M]³‡b˜ÅGŸ, È­©“5¬fÊ,·íBTŠríT¢LñÒhÌwÞ©ò&R4òaĹpSÒ4!bÄ;q¸N:ÔX$ø‡|ݺb\»è›ì=â­ñ"@=»ôƒq«*K¯@šS1¡>—[W“ÖjùÝ,š,ÛÁ­4åÒµØnìÜÝ6£'d‡ùæÖP9ͧWz,I¹}Oú„¶– ¦•=¢eB}Lªye¨VŒm†¿T6ëE4.É’Øe|2kåTc¯ûݸYTô‚ÕB ýãG™f2‘¤‚ù‰À¾h±~kóˆ7¤âÝCIÓSŒ°#ÿQ'ÞÍû J9Adèjh|ÇØn¯ò(iò‡¬ïU0ß’:ú E4‚-‚œ…ãjŲt;¹[&&=:ϬÈCîêé!(v€dk!ßÿ4²š6m$WˆÂTúE/lîÞ‘ÄÈó­+ÛÕñ(Ò=Ô­XZ[oð†ÂEü¿ø3*58IkÀ²‹ó´7B¾c+ãýMÄ_—nݺp¡F,ƒbLÑšŽ Mƒ:Þviv©ï¶£ö_uMsÛ‘Ü)û" Ñ/¦Ùl}õMÖQ\²õ‚…§ˆgO tN{pÕD_™L¬˜µiõ¶aÁ»á ¦óÈÑùcà4€Ð”,|w‘7Ïç=J¹ü6…Èç.r?"‡Á60Ás7ÍAñG;E¸ãCìë‹}ksý ÁRç«£Æ,¼YÛ@ˆ>® ;Ïëgß:£Ôçqaª'ŽÈ[‘ȇÆ"(:èjŸøà¬za•¾›`]Ìž2#6›ë f>%RòKãÂé dì—ßÃ:€ô xþM̈HT!lÕŒiÊ:ùJT·Î¢^}âÖøÈI?‘´ÂÃ"ËÃk,‹ÎÏî@ÿÅhÍáp Œ’ƒvS¿‹¹ÆÜEòª‡õ|¥™K)A¦²äó¶ri‹ajD\öo"¯ê¹ŸpõòªÐôi®È*z[›óI=2$E£„Êm¯Æ’ýv=¸Z\'’õRS¬£»8jutD2{ÅgœÚÚÝ×Ê32ið_â“Ü$¢7.BèQ,/Í,ñ™ÍfLoËëðØ0‹8ÿXÊ’-Ÿ%§òœñYÐ5L.ôðœÄùzhݲÃâA犼«ÚhÌCI: ›­ìþV1&Ûp=}ê©·´\uÕMMeß—È%Ô -;;c‘Ó8.CLÏ7g5lÄ×t,bt‡n{üÇ{¡EİÑ$t‹|¯ì’ NÁ‘Û^KS€X¼÷³%]FtÇÓÙ±'o˪ÞP@ÔûëE&së-¡øGu|ûó% ©Ö‰÷»¼ržwP¿óu¾Pƒü¨ }il6ÉR¯±AÛgÞVžìƒï d•Ð6»ƒbÆ«XĠج4^üó®sæp©Ù6b=?væˆ=4‡žán÷TZë üÁÁü*ì{Næ7{혔.bBoc»J¬Ý(Ä‚öOCõš‚\¶O?ižšEúGòÕDjm+ǯ$èí¤õ•‡;‹ÁH–Ö¼(—¥Wwk*n826OÌÞDÝaŠr¢Ð˜Áj‚Šš:ð€iä C<û€Ž #¶T% æíäÝtÚ¶pûµÙÛùšM„¶ßÍtz>(Œ!Š\ WBÅ‚±f¼¸s4gj%—œµ(èx]‰\LñˆGWñ!Éž¤ö!¢TÞËuxHÖ§zÔŠŽ‘˜YôO… d/6ÄŠ5¾›à—߆ÙÜ_Ò]$ø!f¸½1:|â„3¿êËaWÛå3ùå)ç§+Re5PüP÷UÀ™!ˆ¢Ù°Uíàep­âÔ' U«nJh‹%ò[KV Ü·ÝôÁàÒôq>pV²0šÍûÃOM¡vF6àe9­ ªÄˆmm’¬‚L"sU>­ùYa¼XrQÚÁÛó¼n§÷Lvo`$”ëZsÿëè”}æn[9Ñ„ÒLfZ¼¡ôŠ˜“¤Æ:ƒ‡ Š%Q¥ôcNèøŠ<Ê@ûã‚`}•¥‘·²Òjq¡û±#0DÙ‚ü’Ê’"It¥LsØW¬ðí·ºLBѺµ8€uÙN*ÑI;¿œkôÕ ošua;Î$`NÚ|{©Íαz ²nëh½?põ¬vš°~A+A»[O( 6Ç0¨ëôéiÆFtåÂ`¹^ó®û檮CÉüÕ;J’]ùÇœ‚þÞÄxÕ¾‰Ïg€ˆqE(ñ]ÁsÚHH•£©Ëý áuòú¯huJ8vìˆ21s©›P3ëmk\­«ÓõýÎÑ™ûȱ8]Š@¾Mj·ù67Çôùù— Uö %~œù¹4hÛêPG‡B5ÿþ9ø‘°PÂeÉòîmÌÎðñø…<)”ΨkpŒŒ•Y÷K•ø¹¸y²}ïd«uñ%NìAgŽÎ8ejd&5®¯‰Yè“ØœN`=±'“ŽìÉ;WI½ÓÞòæzõøé[º$áºQ}­wd¶ÎjöM|ÝÒa•9V»ùä [h }4œ¹ø´VâAk½ÄSŽ`tÑåH¯×L Nß ÇÙûédÎ ¡PkRÎ8tyÁ)]â@*â RÁ0F¥NÔ^ !"T:55à|ΗdœÆÜg4œ_M¢ZdZBdªÇT[(AÙd #íO[a+‚zاiºµ/IXü²ëã,Äs‰¶¹ÿö*jžÄu5ÔÅ^˜W]î)‘`.ƒFœqÁ'©%d,óÏ|ÓÖe<”ª9LíeUyV¿ä2f¸½Q–Qģ闡­dS=fÊ’¡eæ>ݧwŽ6i¼DšdŒCˆ°ÞN‚_.y°õ >‹jÓ£ÞI’ÁJŽRŠ6%ÆÉžè~ LU©XcËb[=ÏsbˆKªJ`¶á=91ìkÎBþûÃãá¡Ê\´cÜÎÇ[µ@¯©Àj›…\@»5QýKåùƒ¬&\ãšíàsŠg¹Ù6Ìvsõd3èº-†z̪NA„¸y¯O_f¡Q¾á^IúaÉ©oæxxŒ¯üL„˜ ƒðJs}¦zÍÕ`]‚´Ñ×v(ŽÃîjÑm šù‡€9–TÝAtL§uÄã~Yéä…<ÔÁ󩩉ÃÖÿ„fëj-³ ïL.R +ð·röFuzýD—BÑ_Œ>¢Û-Ç)•n¥&—©ßáØdÜM’ÿÜŠØ>ø¼ Âú5)M'áÃ')½øß^;&`^S 2à¡# ŒctŒ9M:T÷g#Oß$ôÒm¡Q%Y5XÓd×WOšÌiNj+Z•`(‘Ãô³z›Ä&¥ñíúü.•“ïD´µH`×÷[jM½ÑŒü‰[ʵ²Ø¶«áøRõóã¢ÏNã9 ¡—ÔU AÅ,™¬ÄT×`·€û{EÜhŒvð¸ÔÅM‡u ½\dÕùO ê;ØPUi ø1ÐÙÐo'µm²ñâ`3—"bYrÙ[€¹ò¤˜$–suÞ¡ý8~Éiš#ìL¸D5Œ}f·»TQmÌâ’Þ/PáÅeŽ¹Ò«ch]{®i¬"ºB°U’ŸÅ]³á/ƒ—há+*rü’fgB IÍ04à†,Õîj0þ»Åï6°üí«r˜ ;õ[ð¨èúj b5Y[:Þ¥÷gÕk¤œã°¸ Ïémå½ü:©Î(¿±$ýÁÄk ðqŠ"(CÖ0uz%Ò¥¢÷âó©C)œèùe°ÜìÞùm¿cZQ<:òi¨òž€s{ŠØeH¤ L¿D'64,â…4w;¯ñL›N›¯šÝQñv”n}o¸Ö=uÝXÁõO!œÂ}cÆŠ æ˜Éƒ¶ˆ¥ÑîßêkIML ~䨣:.Ÿ*™úñßx*~ M¤Š£äÞé›ó{¢8â²ß51zÆ”¢'÷ wnc‡AÅØx<ëÎÒ%ˆ6°ÖâRb00vhgk£\úK†“2n˼ñØ”¡§­b,»‡u˜'êC½ èJoLc’N#aPL”cõÕ)Ðú¥ÞLQ±âѶôx˜Þšž•¨¬„!56 °§òµ ßÚ'¯å”Ö©¯ïí¾Jö]¿Ó˦ÒÔ‘½{^¥5üÐà"Z€œÕnBQ¹Æó¢¶BŽ ÖÛ‰”ÐbnTw4i®tÇOR‚îî~MB«³DJÆ)F´ðÁ[iµŒ‡ïI»ˉÎóoøàý4þƒìñÞRµ÷ ¸qÃ< }6š€o/Ö ä?ø¡¿Äd=„OuþíËvÊ%¥’ÞÈÌË-¸€oê½-%ôïSé1äa_šþý>‚ãì,p#ùîK*ÅñÙÌ5ä„H¡z`©£ˆU¸‡Q­Þã>qql]¢¸Jõ@ÄÓá:OE€•É_ÛáwР3|'rŠÇÞ›QjÚxPã¦"”—Ž=Œ‘)sîe<=ñ^†Hd´¾YŸ¡â‚C_ɘ˰qÆTÄ®wÇt³ÑëATsª\—«*î hYZyñ†-©þDúîʉ²¤Îl?I_ă„9VQå3Ÿ¢tt×v÷Ò\Ô¼ž(@Äfí|·êÞòµU…žUŒ|[Ù†øçuàìoGo•¢±¤-iLÓþë|yn ²@¼ÉÉ&º0Ñeƒ½¾Òü˜¾5Jø¢ºEIeN £…›¶ÄmÿÓé6‚âÎÓ2¶ª`txâŽÜZŠz—]ÿ¢Ñ_ŒÚ$íu³Œß¡èÈAdMoñ-3O?Rõø)R•{n¥ph.{úÐ.&¾¶cô‘õH(#ñ•wˆ4¾ïx-œñ7’Z£!=(Q‰Éx|Gj-§E«é’)ÆCJ¨f—îWkõ¦Lo…+¨eüÂ¥ • „z5n¥çì±Å÷Ì›û¯#z¿«ÑT¾ÍiWmÇîÀýÌŽr¼V)5eBé|còaÝpú =vã²À=6:c:ƒßO‹­ô%;á㤉ª wߺ¶üéI13û•(Tĺ(ð,á„´ti Áf¦3‹/Û4Y`™>™¢E_x1QædXÒ†%¦yø[/Õ_¦ˆØâ刭ðÖ¬/§=Ь›ãÉ~,tÔ‡˜ðá÷G›}c.ÖúÖ b¿euç’ž•þ5ï.f°Þäøê@ uE;»{Lœ·²P„:õU^K0Ý}½sÚr+ëN¥–1z,…º1ã'Û½òàÙW×來ΊDRÉÌýŠÖ·Åƾ£U$ã¶fyãøX¦³ŽŒ†'{}Ú :ŽÝ0[â^- ¹Z~ç»ÔÔ EÂÑÈ‚R¸U|ršÜî‰j̶Z¬ŸQl*±®ïtÑ\•v~}u@Ü+E-½[/®\¦H¼ÁvŒØÖü*•û”¡ÿåõŒ ûE•ÈaÚ<ñ‚PU‡Ý:žè'\hõevÖ…¥¡(œ®w\ïÏ|­•3­òsÎDÓŒ7ažÞW‘A9uD‘çKGR§”+¨ZAV±*¯·Øg66Ãd·;»cDeÆ!(þƒ^`ÖÕY_Œ:3Ì#»Ãb·°\pªÀ+¶•õ¨ØCE‘ôÖ€b¹Ö÷ÇË|\>óe2]ØS.HŒGÑÍÉL‰Øþƒ‹w^ÎÅÂú, !çößP+lGR×l\qKxÝýk^@m»&]ÆßvɈÿc?›ò9®N=½ýg×ìÍó¢"Üæ²,ÞqÆÄÆ­ïÛ/7»‰›ôLÍW¸Òg“~Ü¢õ`wç}[îÏŸnñ~6öN/ôb˜ö‹kù…Æ5ë”¶æ*—wphÝ“–¿»m鵕Ïÿ=Úö©ôÀ™›–t^µbƒK¨ ÒZQm¿‰ íJLWš¯,{&™`xËs_O_L¡ûý/çìüØæVíhõò˜o%÷¶Ìøªí3W‹÷Aî~<×ô·ŸX¶¹›7áÌî…½gns^ l˪%a÷¯ò#°¹-5ë¿«Cæžù¹[þÅw]O1ªÖß™¶çÀÓíúlxÏ×v黦޷Å\’–ÏKœ³kÕ—×êRSßΊ¼¯$ÏW6·¦OjC¹óíü k™Ü']}õ’Áá¹ìÆsÛO=šQöuáµß¿D£/UñöÊI½>|A²eÞÅ›éUþ½­“W‰1È>W‰f˜¢(2iÏQVM®7Ö»4œoOù¬)R•`Ý|b’:÷Ë/[dYC3&±]‘z¾b§žqЗÓ._üÝxÌëûÅÄî?NšÇ(ùøûÓ“›û¾^Uy9O8±oÍ6'†È{Ï%š~vâZ¶ tAäÃ#çn<Õúûúʦ5?¹Îµsæ(]3[{;õ¿ÿò5"wÞlç¨þSœÚ)õ¹8ÛÊdww`Ì7ù©m/ ¶:Æk\sÞu:`¾Î‡g‡Ã[º«¬u;kóe/ãc}ÕÛ3Rï1;œôŽavŒìŸ2 íÛ¼”¾öN3Pvå'ͳbÊ»f‡ÝèWjX=GLïU7~ý’®'Çj×üQÜ5®~nÎnËùG&†NÌ`ܸãŽëfå ­úˆ¯¾[Ûøì™\aŒvemÀ…+×Ëçïfkþpáù»ïnj>ÌÁûž‡-ì*“=í¼øeÖ”¯™WÚ\¤³ox%¼ñ99cî§{rû7yFLó¯É–-yW•òÿ9øÛÜ,îRŽÖêàå½ÉDzB••»ú§ÂoÎn‰ø³gïp =•_•3÷v+CX¿ùûy¾1kf.–{³ðù¿ÇòuÿþD¾ô?=Yuff‘ñ•ëÞ5I¶œ¹ýùhÿs6]Ý¢0ž–Œ#î蜤°!Xª¡b.ëDþuáÒsçS®w©/²÷ÝšÙ µ®óÆØ-òå?÷3¢’Ä×ð\¨¹÷4¤Bü‰ñëµ/Wž‘¯[²Qrí ÿ»ýñ÷.…ýó7 š•™Vvóˆã!¿“–zL‘›ó R>ï{˜,Rßåziñ”ðûVÓ&Lm½óåJæíB†•R«Äèd¸ýÿ¼z}ÝMÅþóéŸ_F­ šÄ½4¾]}§®òæ÷ÌÅs•,Œš:®úîz'ìŽãâ;ÿDì~÷õ{Öoú¹\Y°vëºÏÝKv¿¬N4R™ÏuX4ÝüÅö)OÕ]UQÊÇ´ãýíàÜ:ë‰, Yb£t ÏÍü:±hŠÍ‹EüEVÿû5an²Õ>ýy<ŸŽ=Ì ™¤¤~ªúð‰9zW³t×tUÞþ#nR×§žÉlLXïZÁ¾ŽÛ.^øè#eU×+½•^ËŒ}–ZP¸F $ç¤&•äç&es¸¹£®endstream endobj 37 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 2 /LastChar 191 /Widths 305 0 R /BaseFont /EXBJST+NimbusRomNo9L-ReguItal /FontDescriptor 35 0 R >> endobj 35 0 obj << /Ascent 669 /CapHeight 669 /Descent -193 /FontName /EXBJST+NimbusRomNo9L-ReguItal /ItalicAngle -15.5 /StemV 78 /XHeight 441 /FontBBox [-169 -270 1010 924] /Flags 4 /CharSet (/fi/fl/quoteright/parenleft/parenright/asterisk/comma/hyphen/period/slash/zero/one/two/three/four/five/colon/equal/question/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/W/X/Y/Z/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblleft/quotedblright/endash/exclamdown/questiondown) /FontFile 36 0 R >> endobj 305 0 obj [500 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 333 333 500 0 250 333 250 278 500 500 500 500 500 500 0 0 0 0 333 0 0 675 0 500 0 611 611 667 722 611 611 722 722 333 444 667 556 833 667 722 611 0 611 500 556 722 0 833 611 556 556 0 0 0 0 0 0 500 500 444 500 444 278 500 500 278 278 444 278 722 500 500 500 500 389 389 278 500 444 667 444 444 389 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 556 0 500 0 0 0 0 0 0 0 0 0 0 389 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 ] endobj 21 0 obj << /Length1 756 /Length2 643 /Length3 532 /Length 1186 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž44P0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22°25çRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥r‘g^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<8”0äs3s*¡*òs JKR‹|óSR‹òЕ†§B盚’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;|`‡è{ºD9kCã,˜™WRYª`€P æ"øÀP*ʬPˆ6Ð300*B+Í2×¼äü”̼t#S3…Ä¢¢ÄJ.` òLª 2óRR+R+€.Ö×ËË/jQM­BZ~(Z ô“3‹’sR“A±V’åÂôŽ“S~Eµ®‘¥‚®¥ÐxCC3ssÓZ…É¥EE©y%à ?-©©©É\7¯å'[·dMßÖ¶²Îuñ…U¬úœ?O¬}y“ý@ÄŽºÙ™)µÁ¦óÓK–¼Zøhkßañì‹^ÉÖS…‹¶HöúõÄ}Y$¼fkׂeL÷ëݯlîšÆûO[ý•çá°sZI[í/z<«SYçæåú<óR^8E-Þ÷ýÞ5n!­ IZJRæ7W°ße¯¼ûü²ü§õÓÛ&¿;{ËÇ3@¼Ø­KýbšwÒ—ÄoO¸bÓÊ.^Ô|æxðÊ‹Gå)ü{öGW¼‘íPjWýx$xYÅ×®:éêë§ ØÅ/u¼î]øµÆŸ“k¿¬ÓÑ»·¤ßßà¾OÖGæÄcãŒßR'´ý¦‰¤Ü3fÚôl‡äé¬'¡×¶ÿÁ.µ´îDzÄì9ۧȺ¼©*\¾Ûö{¨xo­ž÷¶‘ï—ì>Ì}m·¨¡°ý•›Îý?çsúaë2ò-ÝúmÚŽŒ¾×úâOßšœ¹vÁ}Éã†\ɹ5±Û¹zýÝþ±õ|z¯ûh¹à-Nf¡]ö¸8Žã<¦¾bÿûÒ-÷~}övÙ¶Tl{êú³—¿ºGËOj7¼0W±`gÃGs÷ý³7—減|{Ù[²ý¥ÓÊ»V7_Y[Tÿí~îQn%å=[úŠ =iãº2!Ô/åy»ýgË9[2zçuh¦Õ\{õ^õÁñKWüµ÷/á›9Yõg˜¨H‹“âVî|ª®õ,WâÍŠÑúá¹øAÆÅvcõ|®,M³Ë‡NÔÜ‹<+õÑãˆk…WìÚ°ùñ_mØÂ¤ŸÓ\÷ññ^ùv.XfqvMÖ»ÛWkÝš´ìNØØ:/?ò´ŸäÑ?1ÉêoB¼2„]¦­ÜËÝ~ÃêÛßŧ“~Øê¿æá‡g‹nx»UýçOºm@!à5`X,ð‹Jòs‹²¹×;žØendstream endobj 22 0 obj << /Type /Font /Subtype /Type1 /Encoding 306 0 R /FirstChar 13 /LastChar 13 /Widths 307 0 R /BaseFont /IQEPZC+CMSY10 /FontDescriptor 20 0 R >> endobj 20 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /IQEPZC+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/circlecopyrt) /FontFile 21 0 R >> endobj 307 0 obj [1000 ] endobj 306 0 obj << /Type /Encoding /Differences [ 0 /.notdef 13/circlecopyrt 14/.notdef] >> endobj 18 0 obj << /Length1 1626 /Length2 14303 /Length3 532 /Length 15163 /Filter /FlateDecode >> stream xÚíwePeÝ’%îîÎÅÝÂÝ¡pw»¸»»K!…U¸»»KáîîîNÃ÷½î~ozþL÷¯‰9'âìÌ+WæÊ½o\ %aS{c3 {;Ff^€ÐÖØÕYÙÞVÁžGŽAÞÌø´sÀQPˆ:™¹ííÄŒ\Ìxf¦13++€…‡‡Ž jïàé´°tP«)kÐÐÑÑÿÓò×€±ç¿{>#vÊÏ73{[3;—Oˆÿë@33€‹¥ÀhcUTÒ’VPK*¨$ÍìÌœŒlJ®Æ6@€ÐÄÌÎÙŒ`nï°ùÇ`bog ü«4gÆO,ag€ÀÙÁÌøfæabæð—‹à`æd tvþüNFv.Ÿ=p±íLl\Mÿ"ði7·ÿ›ƒ“ýçÛOß'˜’½³‹³‰ÐÁð™UILâ<],\þÊí ütìÍ?wšÚ›¸þUÒß¾O˜O¯‹ÐÎàbæáòW.c3€)ÐÙÁÆÈó3÷'˜ƒðo®Î@;‹2 8™Y9™Ú˜9;Â|bÿÕÖ øOÕ98Øxþmÿ÷®ÿàtq6³1g„caýÌiâò™ÛhÇô׬HÛ™ÛX˜ÿa7uuøwŸ›™Óß ¢þkfh>I™ÚÛÙxLÍÌá˜ì]>S¨ÿïTfüŸù@âÿÿGäýï‰û¯ý§Cüß=Ïÿ -ájc£`dû9ÿ¸cŸ—Œ‘àóžÈþºh\mÿ·#[ çÿ)è_wk˜ýƒ­ˆ½é¿ú¤]Œ>["lgñ) 3#ó?Œ@g  ‡™©ÐÅÄ`ndóÙ¯¿íjv¦fN6@;³O]ÿn)€…™ù_|ª–@k»¿àø‡ËÌÎô_éJõ7y&1 -1MMºÿârý{£Ò縨z:|rû·RäíMÿcñŒˆˆ½À›…“ÀÀÆÎòyö> ñp2ûþ)ÿbùçZÞÈÅ èÐù¬›™åïêÿíýçJï_`ÄíLìMÿ#;ÓÏIûÃ_nW'§Oÿ>üŸUÿûúï™73ó03[^°7ùb•–™îRýspLL§·›|0Ô¡¨N5?7 Ò¾Ë?-b‹§ÌðOU(cýï{‹çü‰ÃÛž íþp7– UWªÙE/MO.ê:eÝ~“~bú©FŒ÷åœÜ&„6'³úþöØWeýÂ?P„mlN0—4dn¹äH~&ßkã1ÛQêAЪóNN)“ލú t]CöìáÓeÇÃR|qƒ@¤ŒpÌÆÔV+óŽÃg­@B7p'Å<ñk:qžÅÛnK5:¬>r­<†A§­’ (Û©·p‡ãG;ð.ÿ^+÷ŠDeaxwO4„Æ'Ún;™Á$m•è(XoômÂl-n¥Râ|ÛÄ>Y$‡6Ž Î.’’£°”ôj —œ.$<„ªÜÅÄÐå–25A)j·»MŽ‚sŸ"6¶/ }†&÷0!ïëû•h,ãMÚ¦bÌYsq2Zž@g3f“Á¸ÜagûÝøìVž€Ê˜€„ˆV•Ir­¢©!rœÁÿa;”×&´Ü …2“)³`ÇDeÝN†&}ƒaj³ýS÷ö‘M<›U(«IAÃã1„ÝR¬ÜµÆ^ß™•”²K?fSØHÔ¿çÝXŽQùQtnuœAð«Îpº W¹MmÐ^µ`ŠÂLBÕ ×³¸¿Ï ŠC0 2.2½R¾WÜO÷³v#À#ÆõŽ„pZêÈÞî èD¾Ø …7¹q‘‡§öÞq;Õu ƒ¢jõ2®:JWD²rÂEä’™DŸSøA$°V)];y>²¡Fö‘Žê/7Ú)шwÖœYÖ µw“‘^.{ijc¶§F»A ž-¦ò¹hT¢^Ðç¥ä³¥|¥}O–ŒB¼ô‚}I2&ÍíÔ•¿qKRïÇáI%¨Æ°×£(õ§“ÄùOŠå:+@p'B¿è¯ìŽK}ùuK%z˜éu5jßZK;|à ñq¶Å=Ì-IŸ·Ñ#YF(ŽýÖ #ñŠ“z©òÚOjªÖž²ct}ƒ§[Òµ·¾ iÆÞcîŸ|<Ê=?JB6ˆÆ(}ô$zÎév_„Á„iÈÙ ª?T;l~]Aí̧0-ÓJ H¿¼¹ƒåŸ*êœG'WJ÷¥ª4ŒYžÑÅ;[­FÕñTtúxCì)MÄ´iyÍ›apzY ÖCIcÁÑ;}ùe¸¥5óPwr†MßB|dÊv46ÙêÏ;å—"Ê@¬q¡wdx¦¨=*üj_ˆºy.=.ÝŸµò‘­hý½Ö¾Ô%g¯D§í6êÅ{R˜Ü)yð2AUZOí,¦¼.÷³Ö‹äÁso8èøoonðÈ£ adÐLi!çžEÊ$3yîÔÀKû÷Íñ,ú^Û—ôHPt˜ ° s$¶9ͬUȽ¸u­-þÕó?¯uÚSj/P3PIÍá$û—¬†¡ ìZaªi›•¡9Ü#ÃÖ ÏWWï´Pé |.µ'¦Œï[üg„.Gµað¨1Ñ€©}˜Á΄؜¶æû¶Óe3¼µœ]'ãxœ}y}7èë,§ tw] %šˆÈ0 ßP…VºŸû¤NèôÈØ‚)ÿœkq#±É”^Øz¡©Å‚/üL1ö²7LÇ%ÌQÄ ÐxJhQ〛?Nœ%®íK™«8#õØx¨ËUKÈñâ°a“A&ßÇL[û2ÅMëÔÄçU“¾›Qe ýd°WIµp.˜ á5XfN"«O>-4Pr[ž:ÆTÅéóóñ§‰ŽªXú\¡J]ô°ûÜ£ªÛü¿˜$˜ÑãVª o{'¸ž¨Õ¨gH"©Ø(©Xtâ\»k‰\F+I"å¯jïùPyÊN ê~æôЃÓ_V'çÍ­9ƒ¾B6“n0Ól–Ó©lÇ#$Î+£„ÔËP(÷"eí‡ÉÂ\¼'Ó?±%SK&?¯¥ííSЊ_×-ñaòá¯=’ hl£ŸÑ™o™ÓïÒÜu±)€bÃd?­'?t»‘\ÝG‡ç=Ò‡õ-ºçÊŠJËÂJÔG—©F ¡PA4ì£õ4¤¦rz"–öT$´‰¸Â¦E#ý1ƒÂ£ûœf2sܶ“†$>”üÍ5ãiÚZ¿„4%&Œ\@è5§4…®â/Ôð< Ù®uþàí÷šK9ú0oòàé‚?T¼;:(@E¯^Ü€xϪ¢š¡3S5×éÂ’CÁYoŠ|@øD§¯åEU\hÑF ü‘'Ž$3m.—‰ËŸ£R“^ ÒV²èÈØe1)8ÐïÙrÙGú v€°¡Î8ŽÜçÙŽ/^æTh!D£=ö­¡’žÎ  ä"í°gº!»Ëw|\û­Ç¾ž ƒ›K’Ö¡W(È/7ÐWË–LTS¯ä»ÀŒMdʾҘÅ(ÐÃ[=gF½ï¢ÌŠªŽSÅeÉÈ ò[\£±˜èá/ƒåÖ¼tàºx´j†öÜô>°µ_ÒÅ•òpkhÀE8ĈÎfŸ„è6=¯;ô³ë)A é =ÇQˆh&PŸð}—ÝðÛè§®qy;Z™6F@d®»qkAVÍ´î­‚ˆ]˜Þp+ Òª{*&2mÀ]‡.qúД•¼ÜOT&;…/ï˜?JÿèqgSâÍkìc©ÿê0©ŽU “¼RÆýèÚ„Os°×=6dSoÜOÔ³{ªˆ,Tí¥Ü{H³0Ÿ>R•%õyóvâ6ÁAHÔx,zù:Y ò63ÖR”Kãú7ùjB^ÕW]ü{Wµá|xòŠn÷7„¦B6¬Í<ˆòp=Ç¥‡@K—xãd]cåÇÔ–F7oÄs&Nw\§þ{6äÆ|Z?a5z{ˆæþ¹dÔI}–¦Icè’ Ö1Ãàç¦7W³Ç2Ÿ÷µó\ã´Gžy}¼Êýk2Hîe«Z)… l)Œ%f;¨Vò.¤¸Ž”À;Þ«ÉnÊP5;ƒÞbƒ¦Ë…g_Ï)L×§:'Ëßïš<àÓ­Ú´y•^§U%¸À§–õ2޽3 (ø¯¹„7çÚŸ‡Ñë!BqgRÌÜ/êKôãÖÐai˜Ê½pe!‡`ÈÝ }8G²R? Pg«öã>4s×ý¬VÈ'}JˆCîLÖcßyÇ( ŒÇ^àXP³3õúâwtL–¨5Sp”¼¾äiØ"Ç'Lœã#ÿ1ÁoóUa Jø ¨-â×W·s˜èlæ*dz2éwü³•yÄL¬j4hao4×tQQÊÃlܦDŽw<†~‰€ŠÒ Cñܘ)~[(~vÌi‰&[±Fô>Zî{#ZÔ"ÿz†Mñ³ZEXò{ßëLÜŸ&ÍÞ73l©›˜NeÛžXn!&޳zÂò©]Œú7˜èÙN®Á_××*‡*¯3¦Š'g+¦x3áF/O6ýø[m4f¤ÛÓ%2Ì„¼† vÜcB|-Êî[Ë‹Ç=IïÉxoË·òúÈËwv»Ug(gŶí ágkÎú´0VS¶a¦{-¬…›ÅÞ+ÂP:jëBý›±ß­RÐ' ö+Ù½‚Á´ŽÀ¼¦¿;Ô;²½¤yà!ÉöÈ 4h}@„¯‹˜ªdǨٰWä¯w'¥­áGcŠDaN„ÏÍ'”øg«P~èX_UɤÆsFN–Y¾]Lxo]†TÜÖ¾ïI¿2|ÃáF-¤Ù׎†ïƒ†³‰ h[Ó‹‘Ü&¹Kõ(ýj(Q/¥ø¾£¢ó5 ïzyúʼn$¼Ò3ŸVÂÙ”ƒW/áÏ\Ü…°‰eH¼¬iø…Xm1(çÇ$„ˆ‹N«ËÉáž³ÞnA䩳‘< ³õ# îÞU†¡˜LÞòwrÿÖO!¤ôªi ù®ä\áÒnrCæí–‘¡W3ÜvðE$úQAF Ü2-œ†÷O ©!(d^¡˜µYåUx D|˜7D%÷q™E¿oÁ"[Ûq,Žì¤•®Ìf‚¼eÐà æTä¬bm®4Ù6} Àhø3·¬”òׯÜ?© hIµ¯sý MÏ#?ñ Lõ¹‡œcËLv u|ÝžIi;”DiüÚ¢ìï$âåq,FÎÙäìõ\ï¾g€àsÝ¿È# I¹„æºÎWLÕLmAüaÇPbZšTýB>&[ŠÆtÂB”šy v”ZK=ŠU#rÝß°,ÛbÏ”(þåÕÄ~£œŸ=Ƹ¤bå÷bš?4Ôé4ƒ½­»Ø±:ONŸœë–xÈB^·PÑÞx}~Ï39ã7)R9¬v Å¥æ!sQ¤—·6ì%Öi›J.*ÙK겋~2º|6ÉôÂe*eÐs²ìûr¾z3Ú¦@’ã¡18¥¡¥’ÃÂŒå{ÇÖ¬ß,FÆ•«÷P\Õ÷Ù`.4‰­‹ øi(Hœ*в„Jê;×aÖFÅ‹PÖì:1»µø¹j>ÒSÅòд[9ÍÛ­Y,Xä0 ZÄm“ª>\ ¿KéŒî¨ôèD©ÉÌï¨PXka:F„îÊ’øµ\h§ªÇæO'¾J’›ißâ}ש"ï½ÌB¿e^ƒP•[»Núµ†ç Ïkê—´_WÕ1W–IG‰>NcÕNÇ«âÛÁø%Á¦Ëñ½tûð&á;ë)/m.ï!88„ ä¶ä+W^肨€L•X½Ÿþ€Ì$)ì¾4€’èÃõNzVÕŒU¥a|àTº¨· ¬=;†êñý„òŸSÚ—¯VéP E#ßÞ$ÙÂBsÜ4tkXýól,é‡uŠ€ô±_<ðNø"Jâ*³à!Zgèp ÷Jf¶_ýgpêC±dŸÑýâ!亅Pš ¯à{»àŒÎ´àÆÑ«}¹”iò‹¨©o1_:û…ÀLV1$:˜³0¾+6éG‰°ÿqÓä?ÞæA1§#C ‚<Õ=/A%oŠJS¿¦ÂízÏ]µMáŒ>œ«¼U¬)D ½Žå)½ý ä­œX0Þw~«—÷ˆxpÛuÀ•Ž2<ÃÜ×$cºZ‰–Þ@b¦íÛ·,3.È®þjM“G]?¾˜šUs`‡e$\nýìéÔ:â¬KŪ"~bÒA¶cŽ/u‰½¾úûÉß8“`àó«³3ÖÏ~ VíQ¼P‘]÷½ V¢|öšm°Vnåãz[¯dÊe¬ CЛ9“ÌêSŽ/öß`Þ„#=êsjçc4Å(¨ÞðÉ @ ”Òàߟ¸®>žñ(9XãáôíKËZÕJÔ3£Tü›~KÓ3ý¾¯«‰Q,è:*è%cJŠ63ï´I]„ÈCVM®”~ÏÉÖšNÐÌòÿóÓîÚ±$ÿE±Q#êŽË"göW•÷E×Ä/”-²ÜWT¹—q×}ð8—ueRÖ{U÷ß%HøëCóZj§w?Êc7E|—ÚÏßô0ï¿X†:ÿØÂÁöY]SŽÛY%$ÿ¦~ÊfŽOQ¦y,­¨ôE®LÖ¹‡¹(”$;ýû¥ce/àžsS6ôÙƒâmíÆJ>w†%E±E°)a°ùdÎþðô½9 ux–ùªÂŽ'L%EÅ’z%r¾}¨e(¸À¾¶lÊ®›–’d<î•*7ª‡/.5ªeÜ*™Î𯊿ë À(&`Ä‘V\Hòpf»¯F ¨$nàÐ!‡^HÀ|áÌZV“c𨒞dƒb D#Šf(…x`®'~ÀÄ4¸‡åáp²»v¨~[‡t8ï ^œ¸ø+!³ë )î…-hr­ äDŸi?@7…áQÿ¸âõQÐ-­,[dnò.é×3:âbÁ·ôJT‡Õ•Œ¾º&jÐ-Ôêã%¹•TJdevÄžaâsm²Áóipò¦µÁ i¨vÛžoàjÛ÷(X±ƒ« |¾®à)EºÍèMæ,xiÎÚž/ë¥uRŒÂžß3œZû˜BMáPxœø‘¬";ª`Ò$<î¬ÛÔçO4/ocÿ„ëÕÎ##¢„»>së‹&Þü&Ͻk5du_4.ÇôrpÁû¤aÜ—ÌeäÞ/“çc¾Ûk‹o]C)0r¼QÓ)—·¢<¯%N’Ìdh*Â"½|k’—µaÜ"aÓ[™€9ïø³~˜5™m‹­AK什{¯Ö!KiþÑSìðF£m®ŽÐ ¢/†}ÈíèxÞ}ô}|ÇZº FÆOyGþÛ²jµÎ:ù'i\pËúÍÙoHÛ8|,Ô)÷ ríd#â­FÂ}Ñ tpãŽNŒ^êÀïœÙ2@Òt‘{IŠܰbI·^MŒûŠ0–ªÁé—ÃñÌdË‘!oÜ 2½M}ìêj Wó;GÛ½ª”Ä&ý˜}ô/¢"' Žôi ¡?©­çs¸5Ó±+Iè€4òßÓ»¿ÆÀ)]d-ˆ[!ñrµƒW¹Q&Ü|œTc}„eÐ!ý”ZîØ% Â;èÔoméH·ê!ªz´Ä!m3"ˆ $L,îÚ›‡\\¿Ó[y÷_УžÇxÀ>S|ð0ßáJWô‚»åñyû-7&–C¿S®OZ¦ÑÑK Â.un–³z‚ôôç„bõ`-Ú£xŠö¹BuË Õ”Õ”ši a*›Ì_[ê†fa Öü—V‰lFBÙÛ³ä²ù¯Ø+¿‹#¿râôC„)…Ъ{käTfd%tR€CA|Þ(f­Ižq"¡Ô3£Ïh«BþºX8F3P^§þHXµÅé k˜ »¶Š˜fI8|MZ¼<-Q.å«I9ˆÓÇVŸaøs€‹³þÁNÞeëÙ÷2£‰G-ÙÆC viÀ²?¢Ôdð©M¨òA«Ü¬š”.k­àŠW*úFa:ÇL‚<4ߨ›º¨ Á4ó=Âk˜\­E­ÅªjÁ lâ"ÜA¬?öÂ~™È«²kiý‹bøDs} SM,ì·}ä$ ˜t}‚¼ë=cîÌÛ*¬œWâ¶¹ãvrmܦêÒÀÞ¯·5õ²ï)vÏ5Ú°³Ó+*z¤‘'{ šÀtdèÔ±¤zw}HJ­ÍP¡á[ îÁo¼ï$eÝ5ôç8PÛ"Ñl¢Kù•N~Îj?ŸÓS íÎŽy@ˆ¨~‚vV®,my_|pSdî¦ß >Nt|-êùÍ™Áù”BÌåçOÜÍ­2¡Ÿ¿Zè)ÑÃÑU¤…]|=¬å5ªË\r˜*{žžú}ב L]4=7*£N:|ð€¡$øøºÂ¾Õ‰ÝÕ]„!˰sìÞ¡ dÒ‘ºnƒ~ŽÝ ÃJ>Úº90{œ7ÔÌ­Ø%—šÃ}NæÃ],ç5&ÍPÃÁu8õáèPѸ~Þ6 U†¼Î9@™¾„ogL‚ˆd‚6å °® yÇHt_MIïmy º S¡œw„ÿA‰<®þ:ò<Çf“8Rº²•TÏLOo”®ky«ßÁ!SÏlK ë*’DRülÇHü.úF&ybXB$°B­/§÷, •‚>lÞ`J÷ܔ׈Ƹ¶>‡ÑvteÙÑf–šis_ŠåyÕÅL Û<ÀÁRƒ´s¥c@é? †KûRZ¦Å:™¶œÇw£áÐщmiêz3²%ÚÁuÇ6ܼq‘÷õ'í³†E÷ã-ެ%‚íŸ ¸ã×`YÛB¨S†ëßÀº½#ÿΚ°P~ˆGO/3¢h䆿0T"iô=ꙟóš:>VV ƒÓw%Éo‰=[Y\iìlî'ìªüù`z«>¸¾™l¿íL’ô³. mÔê®3Wõb#"~‚ü7ÌTš®i}j}aYA~|}ÝT²Â}—7YXl4>¥-Äš\œc%Ó霌cAw^Ry½9OœþV/:pšÚ’¶ß&ÍÅgv×ÔVéF'X°sž'¸>b±xܸ†ŸiÖ%”[ÀRC­2q…6r瘨LƒÜUˆ ó5ÿæ¹P õÌÙãÀ\uÇÕ"—› ;{6í6 ÖðÊK=*fñ°zƒQ}GÃOè«3%TêÌ<åöêÌ–eX•¥\p.Ž¥x=7ÓÄ`îÒ³ª ³ËóÒïì4=´„¢'s°Îªa×-[[àPfŽ~Û=7:©šÃÚ‹ä¥uø[†š°ÿÄ_ŸD× În†aŽUÃkäWi!%‡L]ì5ÝÒš,Á½™œDZŠÑ[p]I¯7™|Ø]Ž-CÃüÁÅE-ç,Iéõ‰Ç·[ä…Fz´SïV-XÇm:ð@CŠb ¦:Ý_šÆÕðŽ¢´Ûxàȇ÷xI,SÛãXfÝG³`¢ëøfµ‰"ÈKK–1%:(²KYH!•篺k-ϧŽrwj xÆl\Á`#‘ B;À¾Í½ž* )ERiÛFÎ].Í$â‹m:íUY(º¡í—»bóõf=Œ9b‘[Ñßr–Õžµë*°yÁ zž¬ ¥Â¾,Ò™q çv‚øÓЄݚs+”ÅÃ8´|…~ÅœGŒNÂ. U-O³ríŠ{` @Çš°žºàÄ‚.X8 Fó½Ónm~Ï„²¬aq-Àx§îý‰”+œZ ƒ´ÉÓ™¾•©r–:N1Ó€’­CƒhÖH|÷«y ÙAËy9é& ®‰ÝínU7kòþ"ŒÆÓá@ïá¿ÝG:]™-‚¢lø=êÉÞP¡OÿXÓ®…ËØN¬L3ŽtدžQN~o'Y÷§9¶AuYú¾Á’êq¾\‘b ê\ž½`/÷n X§c+7rr?!”‚¥øaçOÖ–‚× ½ßˆ|O·ñW‘^[¸Æ/Qšbè"Ln‹ãZœ"û§%=`ý âÇ›ýFðjØÀ'õ cŒáØ»†<-á9áR[a®,n¼ÔG‰Þ„H£³ˆêó¯Uòª”÷-ÚÃè°h\'‘k®„sh®lŸÌC!.sëiLú{ŠDÎXgîX;™îm½¿wí#¥C–Ä87?·Æ5Bmoš&Ë©¥%wS>wÑ­ûV"DC.<_'sMt•tPÅúYîApåüبÒzÌyóg³lK†’T¬(ŒÄ6×Á|¡>ÁRÈ% üî]; B©(N’‰ôÖÕù¡çp<8RägÔ1h}Ù‚zÞÒDâœÐ¨Ãq,Ì«Iøvp§¾Y5×'óç ú>|ÌWmtÁ5‘ù_ÚÔÌËáòtoò‚4õ5ç»Èíýâ)Á‰š™¢D s¨P;•N¥Ž 3_–çubß)#„„à7†bêà˜’²]Ï#À\†‘—3ŽY„•w/… ¾œzbš@¬ƒBèØôüY:« >›Ã&}ï×ÐÌ;2k;¿ŒÃgÖ֞䓟Ÿ|áú0ö—T¯zŠ¿†Ã¦7dA@yF&±Üc91ø%?‹Y‰òÆë4º~x ¨õTø‹þÝÙ¬¯¡&±¢ƒèCÍàÁ¯ö¨Š¿nþx‡ÁY¢g¨±IÒR=¨ÓbµâÞÆ¹e¿ÑÝ t í–î2,¾9òOPÊÀ ú<<¤0ÝymËuPΰzId‚ú-2Ù¶ñXá¶J‡œÖ<.¢˜ <²>uðÜnƒ´ÀÁ‘À°[ð5jevl(¢þòƱ]2ùºÓ+νçâ|´ VÍ4= w)^ÝßÉllòªH†Q8­DP¦[dO¼;4ä‚U„Bß@#1çþãz)¤îdâ²KO ¿wRUZTx@‰ªÅ•61N­ì+ÒZ?ŒGtÖ6ÇÆB|øåâ¯9–6mFü,l!W‚êa†8¶/sÝÆû^ÇMuߦ-¿¼õ P˜™fªØÆ»È=üªN+R¯ªÖSµ}ˆMWâäöû¾X µ! »(GP‰Óaˆ 5ïø>rK8Ä(ä¡2]þêòGóIUË oŸ¬Ç @D²Ê©·Ô¬¶×Q˜'‹¿|±›E[¦×n-OªØÝ^¿‡ Š‚÷À;OE^œPKø(£€4é'M Á)5ªÿ€$à [푆Õq½è  ´«2Ø´N ÊR&M_àÇß’±»[%|Ð1ûTBTÚíŒÌ3 ä¢<ÖnwQÖcóræu߯pÅ” |Gð¡èê ¨˧ÀsØ{r&WÈF£uS¬oÊîÓ¶Ž% ”‹lçÓnòÛ56ªÚð'pBëi9’œªQ¯”¬'ßÛQE¤±Bp‰® ®ªöb`²±ÿü™‹lc¬þ[{%FKÚ‘XɆöý¾ñ²öWÅ šääNm ‚Ã|p…’•qÀºåÔöa%¯zè‡.{T¿ÉK’+Â]ÊH•k2bYEúëMÕRn é9ÓÍ,^ŽWe” ßLï ¥\ö6À’\±$žÆá¢š”—Á{øu@6"æjå1l7_×Rïî.šqìº0@“k¾Ù˯ÂS! \s2ÿà#ú^t«¦K3µñ¥Ùó;Òvâmw?"c׈§ûA Òn˜˜vŸ•4ý3î€îˆÕµ ›ªJ€é›Rý,0Öàjä°Í@·õI¼,ÔT‚öål_ùˆ…j¢@Áq¹®÷ß×jæUÒ%…nÒcÃã‚OÙÛ ~”ư}l©˜(¬%>’=³€Óâ…1/Åß—ÊbV¥røxP‰§—J%t guNIÚ¨øi,íI‹~sX™‚‡^aŸ½úëÜ &ú6+Ý ”›ÈûñÈñ°ÖŠ¥µ' ·n /µâ‚öþ°N“M¨w¼똻…!½üá/\{ Újàì¡y»³ÆÉ~÷ò²íº$À#À 5¯˜ KÀÂÚÊ–DN];r_‰I“›6F‹dÁÆ<N**Ö©Í/ª|Cóñé[ìÌଋ¯CêSi q³»úM»yì•>¿¿F^(·(XMf5}ÏÍßo½O=ÕdÒ¯šå%>žî- ’ÈéεK‹óŽÒÆæWž•ýAvJœL1 ³g5¢¥d;\£gi´¬˜¥h˜°yzNJ‡âœ‚×0Ëe}ë7i6íSýÍèž|•§àÜ0ªÎ@Pî© u’JR=®6vS½1MQm`—ÞßÀi(ѽ2ï ‹ÓDù¤®Ÿ$¶;bW4B˨<_Ùñºêôj;vÒ³bßp×+ÿŽç_DãÆ¤@Ú²©ó¾ùŠNG s9žöí* ßT%RuN(Oešß zcIJž‹Y–òœ¡ R¯ô—jr`;íÒ–Ïjç#ÇHOå÷pc¸=èƒì$¤1I¶á©JQÅ‹èI™½ ]1O‡ý› †îõð±ó`DK#ô§Ú‡`ŸªÙC[eblÖÜýö>&µñz?,ÛŠš—SíëeÕfûddÕ¢e‚ϳ{w„Hb{Ÿ¨8ŽqõšÀ`ç;ôºlRà) Ý\”Zãh€R±XÂbù;OÇ‚±f`çh7r—´II"Æå ›«~5™h5'i$ÄO|ljv9\PÅÞW-Ùµ Š ©¯".©Úìô—Uëf?é+ÿ¸IOFÑlÞÊ@‹{¦â¥ÒQ|Öçñ›hLC0,ð^o·‚£?ö'|-‹èCâ['¶®Bâ&{Ò½ylçù¾hË[ž_êJaÓĨiœÖË:Ðîï‡yˆ†ð/2úO‚#sÚÊØÔ5Ä÷åA³~>ªõt&k~¾ õÊ¢†¹m/8öG™êq`AÎë_âB;ŒòX¿>$sPGÀÕ¥aÀþÒ"ôDÚJ4–ÄøhLCx‚Ñ¥Òú ÷l¢lµÈÓ«õ j‰P¿P”Τ®Ò¬¡'£; k¨¾HíK›„ûa—<*g]êãMî¬g•B`›¥IŸ™ ¾síÙìgÃÚ$m‰1+~ºä“*í£ ‚fz ÖZ¶/Ò«X6©G¶ˆ&P„ËÌAè"¤wɃÀ©7Â+Ôû+ÒÀO8­1o<Œ@uê+åCSñêgÞ<ß“èë‹iæ©–lk-“ ÉQ©hÇ'^M˜m<Ú¾êBÊÛ{[LÅTÒZ,¦ul¤ÍØ÷¤Òô8Yu `^`ú¡vYkÓÀæªKQÿ0­ÝBÎ18¯M‰aãcŸYäÿÁ…öú›c4…”=ëÅv×VÉ÷4IœDoEäQí:æðª÷\ü…¾£;}$ÉbE4¢*«5÷IÜÆ·÷'ec”l\ëf>‹×§_yJ±Ðc(rï¼2ÙQõ%Ô9héÂ-ÒõÚoÖFľ9/б6Ñ•ÁLg4­'òý둨ë¡ë’‹~ºššãcoÉÆüråd-oXîUá<ôzHåk+}à[ïé¦Pš²å!-Ó–š®©ãù¾ÏÁ~R¼Ä$WbœÉ Ï™$H¦LPdkÇփҸІ;Þ’/-꘺mèÇÈw⇊]H$ä=ï€gó¾Þ[:9‹ec°îklô¢`Zê&{Ú»«#T°Eÿ]kÇz°~¬ Œ/D™HxÙÐ,¯ßÿø…†„ púJ‹=îË“%ø°KñzŒz ¥ÏWð>øt²ƒÅÈ*ò2ÐÛm UÝj¾`úì/g9-Iô±‰ÑÖø lcdè úK«Õt®Ö, nAf°âêWgü›‘f.”œL"N²sE=Ïi^k5v4zv`¶Vo€¥k~D‡¼ôôlTœV­NçFè]r$˜·NÊ Ài•;“Êc™S x¯L†*R˜h,N¼áþv=T¯ üá­PR *BÝtì:ÙË»J`á;LŠƒv‰L€Éîôc° ™øc#òó´¥B£Ïƒûh¡\Ï Õ>ë¹$¥hœ©kô(]oPdj¬ûÿ½ˆØo ÕæÄïoÃ×ÏjÜ@¡5ìÖ‡Ì ¯åD£€¯‘€jy€+B œÅFVæSûͪ0´Uc¼fýn[+ò–õ³a¶ÿÚ¢¶#AMÚc±œJ9嵫ΠÒi˜^× a <(æ È=jÍBÂkTf»×yÖZ‰zIë/7Ú ãð,ÅY7Tx·À4*0¦ÄyÞ’þŠÍ5ØÓYs^kHX‘err§3ï[|ãxª___^ýâCcE¤+iµÛ›q} µÌ湟9¢³L'#|®?ç›8ªÈ8Ãöû  S_cøàÒaý€j+‹+9¥û“0Т~–°ÌãHûU¹¯?Í#7\âi>×)œì¥¢iEím޲ ·½EÇšeÈZÚ?AOx±íòV¢¯fº…ž$@«xÝY} ×½{ÙWÞ×À'm\–ƒ™°¢²,¤,'9}¡Ö+yг¥8^ì®¶ÜÑ3Ǫª±—¹ÍíãÚÙº“ƒ1‡–Z¨HèV'©à¬GêÚø·)òMоH½‡Õ‡ 48¥AÿH¸>k$¹Öè ±|Vô%âXê¯ïV!,bÈÀ4GJ­”e-ùµÜë ÜöÆ4“ãˆo.jÎZž ùÚš¡\ôXך §©üë!^¨Þ^v×OGk Z7¼(:/Ó‘œ´{»Úªåþ |þSz°žõFí…9ˆhç›àJv v—N?é0ð7%ySOøO“w àÜøÓ—²r©ÀôuÈŽÏßf2‡%mÈPAörDT¼|épvDäk74ÿ›ÍîÊ à%_w༑36r_¨„0"ðMéñO¿ðà©ø-Ôþ|ž©î=ØõÝÓ‡¸´pSÌ ^¡Óéâ‡f¦OJŸµðÁº3ŽÀïð÷RPÊ)¬ßÁc´ñüXë¥: QbÕ ·|jü2VóÄàmñõ]¶M‚¼=|ÃeAû‘•ñ®3`vóø’¬èöB¯‚ÍÖ†+F¢›¦+Q†¿Cd³—†ÁÆßQß~qS«3Mr§÷ç™Ramíµ½xCOŒm£­²-¿"cÖB®pqŽ©Ú .9L‘:þV)ª«ýƒÉº{ëØO)¸îîìPÄÞ‡z‰û²Øò¬0g•xÍ´Aö5Õ°K$/µ —áblÃ>W˜[Dr£†hPꪵD2þÖúE³÷MyÛ(Ô5P0hÓÖDøÎ›jÒS;Zt“½´bh9SgBeù^B~)…kêBñ¤Î @"ûæ÷S¤zzJ-¤B'{©=ë¬~hwÄþèŒäéŸÉÉ¡˜ :SÍÀ5=4†/|½ÆpƒàN”ùX»a£fñ•jñ í«ðÙõc’›Êü^zn›xü÷îǯ>™¾úàdpúgžïºð·XÔxÉDKãnÚ¨d¼ì _½üO«AØä¡kö øÖI~H‡Ì‚aÂ_1ˆ‰= y'àtíjšð/ÌRÚÃú._kU´º—¸ °õõì® î{©›xä͇ЅCÌ Ü几ò\Óü.)®3¯¸¨ÝÞû­šó˲°it>ã×,ö§Èåz5‹a^ÑÆo-²+ ç¸™Îm‹„×ø„1£àEño0ÌÏ`oøšÄ¯&Ý Aðh}ðñK©Í&ÙŠú¨.G;àRãTnŠí™ÈnW¼êÚ Á}5s|¸ai[²‡¤¿ÊÊK*,ÙŒ,õaè·¿lË6]í{Ü}©?$ðï>\~ÇUÉ÷[¢×>6ÝâG(]fY¤ù>FË2³7øt÷÷¹Ñ¾© ÒûllÑ ˜^uJD_À2ฃ W‡tNÇ'Kj­£” ÐÍÒ’,ö需ÿOySg>9ÉЮXø-t}'Õ&›ªú'“y-‚“ÞŽ1µœƒŠ•‚AÄo™iñù#&.Uêµ öàc<ŠxÇ–ÈmöÊ„»œ™Wuæ þœ‡v¶>çxÑ£e J8Ÿ‘™Ô˜€ìõ(¸‡;Ý´Éž@ï/…ãŒùi%åNá*2÷{Õ_©ƒ|Ý,3Öºøítš[œ£'DlxŽIðöA»°„A!Ð?+…žû:äØGX½î&ƦûJJKâ·Eª“™]›¸Ï¨ñmÓ(iLf-ëž§ÓCg¿¨Bp ƒÕg;Bù )9½6P_EžCe¾’UJƒu½(F`¡Žâh:4+Ò§bÿ±rÒdZá`æ9Äý£ó‰ñ­˜‹´UFU>Ä™ž<‚ûÜÒ"*‹èæ+³{iLú4œ[àŠŠ›å!>þ©-Óƒ‡¥Ûh®°!½sÑï¤3ZtWÖB= ÕïŒ]aç¿ü'‰g ¶sÒŒ°P‚p·æüöÜü§¥Úû4E*¨Ýßøül’ê  é³çE~ dkŒ†¸$ ðÒ'ªh?Ê­=B´ÝYQqÔh…ÿ¶?øM—ôÀTÎÄHLs©Xƒ·#zOÇ2Iðù'€òÛ áI{-aœÁBÚ ¡‘Æ·/B3­È¨ô^)Ká0ÛrÏÞj6b©|Ù‹Éè©ùÛRÞ £C%ù*®¸X4–ÈÁËN4´»°ÝvH-¯Æó…A7)s¦ßßq'’7n.Ën:ŒB$…u|tZ‘zkz#ô«Fyp\~MÙÓxhŽÆê)¾~-IÖ«ÅÔTxpÃó01‹îD»ç¼³E¾ Âv ?¨<1¶ûB|1ÚEõôæåëm—L^ÈQÆ T#ÖÓÄF5­^2±Êõ¸ýd3éšñð`¡ØÓX5y) 4JÒ•½8|¶yHRôˆ2%6ìm$ç…û•j )F*öRNÜ_ã] KˆûÚçÈ×´XÉåïçä½QÇÇx$ZGWr¿þ6[Ûµ«Æx7‰à‘pPú™Zš(Ïpà 䑦­sƒdˆÅ™·^™ƒÔÔmÿñ“¼üÄù6~ôõ4)z‰F¯ý{cÎSôš8uF…Ù–$7n«šDåôdý:Å/> endobj 17 0 obj << /Ascent 690 /CapHeight 690 /Descent -209 /FontName /DWYDXX+NimbusRomNo9L-Medi /ItalicAngle 0 /StemV 140 /XHeight 461 /FontBBox [-168 -341 1000 960] /Flags 4 /CharSet (/fi/parenleft/parenright/comma/hyphen/slash/one/two/three/four/five/seven/nine/colon/equal/A/B/C/D/E/F/G/H/I/L/M/N/O/P/R/S/T/U/W/X/Y/a/b/c/d/e/f/g/h/i/l/m/n/o/p/r/s/t/u/w/x/y/z/emdash) /FontFile 18 0 R >> endobj 308 0 obj [556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 333 0 0 250 333 0 278 0 500 500 500 500 500 0 500 0 500 333 0 0 570 0 0 0 722 667 722 722 667 611 778 778 389 0 0 667 944 722 778 611 0 722 556 667 722 0 1000 722 722 0 0 0 0 0 0 0 500 556 444 556 444 333 500 556 278 0 0 278 833 556 500 556 0 444 389 333 556 0 722 500 500 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1000 ] endobj 11 0 obj << /Length1 1630 /Length2 17000 /Length3 532 /Length 17910 /Filter /FlateDecode >> stream xÚ¬¹ct¥]·&œ¤b»âÚ±]±mÛÆŽmۮض +¶mÛæWÏûöéÓã|ݺÏ=ƽæœëš¸æšc­±I å•hŒm MDmmœhé8²@kCgGE[kY[iZE3gÀ_9 ,)©ƒ‰ÐÖFØÀÉ„ fb 6101988`IB¶vî@3s'…Š¢%55ÍJþ1ºÿ‡æïNG ™ €ì‰•­µ‰Ó_ˆÿëJ&&'s€)ÐÊ $'¯!!+ “Uˆ™Ø˜8Xä ­€Fi ‘‰£ %ÀÔÖ`õïÀÈÖÆøOjŽt±G;#àßm&nF&vÿ¨hv&Ö@Gǿߠ#ÀÌÁÀÆéo œl@#+gãø+7µýW@v¶-¬ÿêþ‚ÉÛ::99íœ½Ê ‹þ;N's§|;ÿª¶¦-mœÿIé_º¿0µN@G€“‰›Ó?¾ MÆ@G;+÷¿¾ÿ‚Ù9ÿ†³#ÐÆì?# 8˜˜8[™8:þ…ù‹ýOuþ3OÀÿ’½•û¿vÛþËêÆtr4±2¥ƒedúëÓÈé¯o3  ,ý?½"acj `dø·ÜØÙî?t.&ÿ*Å?=Cù7c[+w€±‰),½¬­Ó_—Šÿ;–éþûHþo ø¿…àÿzÿßÈý¯ý/‡øÿõ<ÿWhQg++Yë¿ ðïø;d lç @ðÏ ±2pøÿí1°Z¹ÿŸvýWk5“‡û“p2ø[³¿Ô0Ð1ü[tº™ËŒÌ¦Vkö/¹Š±‰ƒÐÆä/·ÿ*+€–‘á¿è”ÍF–6ÿÀòo•‰ñÍà/]ÿŠŸ^J@DMX‘ú3`ÿe(ÿ·œ”ÝíþÆö?²‘±5þŸ‹`mÝž´Œ¬ìZ&vÆ¿çïo@L?½ÿ7.ÿÄøŸk' @ëoÞ ŒÿÊþüþs¥ó_`DlŒlÿi%'ã¿Ýö?ÿ¨œþ’ü¯ð7ëÿXÿ«ïMLÜLŒ`Wm¸‚,R3Òœj¿ç Ž kõõ0~ ¶+iP.Ì÷«¶íöM Ûæ¨Ð¯ ¦kœäüls_8µûØ—¤:îÁ´"ïN6¹ÌÃó&¦ìÍGÙ ë`£> ×-AH;S‹ò¼š—Þ×deP=ØWPÔ-~‡ÄŸì`v€¾z¢ô#vÉ÷C'y´Cô1J©ÅøÜ‚Z[pzF–xüôHÞ?248Ð}Ñ»K CÊåŽ@égŸË§©RáƒAÅ' q»ÿÇ@ãù@J‰Ä|hR"ê†SÛòXp¬ð“æj^^R’Ÿ“Ù8óg!‡{1¸ËÆÅ®K™Õ®qøß 8O¢ú7çö X]@tØoöúŠÈÌ·›† æ{ž;Vq‚QØüFÏa¾žù5Ðé;Ÿ+BŸ¤’—`dÚ òåãZ˜§+ë6Üø£È×£Nóä†õô!¯Íc±r™ás7 ²s} B~µéëI6hçØ&P-'áòœHÊLírݸDY¥ÃTçž Qú¨-ãîhÑ6ö= íe)ïË#Kï©RˆÃÌý/$Š9œG¼7¬–¼NPÆLK%³„àÚ1³ç™¸[îÇKA8ÆxIŸ>Jëvólf_ÎyÂGÑÑÂrÌKlV{2|²’4G¦rˆnERþöâP¿” o%†Ó‚®»“ŒXÂ×Ûúá›IçoJ“ºìÕ•í³ëfÀš€æJ@ÊCuàʲ©Ú‘ Ù1‡ÚHx Û7MgP?±Ç08» N~iÃÏ , ?é.$õ !MDÔõ‘vÉGê·jb;е͢‡vhö‚¡‘3çrI„Ü"Êίî8”?úªr3`½aú5–!W󻽤æVéº(²¿†~ §ëœ „wT‚ûM=aþT4™Ò]=ôzÕê‰ñ_ ¬\‹ßÖÍ„Ç^âÔʯsÜCt1‡ƒ+„åE‰7HíÞäÛ„1#Éi4¾Ÿd{€6 𒔟Äí«§VËSš;ñ’ O0€ÁcÔ³)Ç•ï6S´DþUA@K/«¦ Îàq@;zÕÜo^ÒµxTiØ)¢0î·ké~„=Æ4‚8çYª¦KÄ ŒŸ ò‡ýßK¦U$Öènëz©EYúÔìD7Õu'.⎛LO€=Óç~3Ipç¯xTÓ!qñ CxvUb¶Ñ66ƒ3bVeY›Ð)mÞ„UÕ•? ¤¯E¸_,‰¯ÖàDw•&l…†Ÿ=­c…ø’Àê96µ±‘³j‹P§µ_–ÌDx_éŠí~ú™î8L×JzçŠ@TG˜Møé(u¨O˜mlºC\ D(¿_u¢f!§i©oY'À2 C8a'á Èò‡p9z‚PY•©·öqx$7&HÂ{{\£Ðßäm­W×µhRw³Ýÿ;윶¥zDýÐÿ¸44 eÌg55¾ä§ü×¹ AÓË_Ó´´+KõŠ éYÞJË”22¹xÑÇ+û,_v÷_\uHþx«¸Ÿ©âäf+²öv»Ø&‡ºÊ™±F¡uHÍc5é]LzÓ)/jîÌ™ë~R/Ï¥O¢í%…5k'šï‘ µ G…KšüöJ mjnL !øÃÚŸHe%š.ü’«¥}Þd QÎPxãTy;â!1Ájúš¬ì^_ô¬ùªœqIé°9EéÕ'Óš=d˜¶/v¿˜ô`øH¥Å¢ i31‚þå„›:Î(ÏŠzdé·×š:Uûmɹªº¾‘[QÔ¸¶5ë:D=ŸMjdÆ»´ìt€ÔVYéÇ/ŒW$õb†%|ÕæÜi(Û€sR| ]Ù“—.²²€¥ó㾇µ?žéŸKð¨ú5ˆéXEmÆÉÙgöyðÝã˜ùÍT[}Êžßejñ³ðLŒ‰-¢t&ä‡}„²‡ñß}íz¹G XPðÎw¤Ãm– c§úþ !Ç‚jÈë‚J²ôýSv˛ܧCÝ÷á¾¢ÎÔÄÆ@c¥šŽü*¯ ÞxÒX'£ˆ ¿£îh„ö¦Nо°ˆíîN â[Ä©V¼$HËü‡ãÛfåì^”¨uY?†dþ , :2÷ÓíeÚËý§v9ð~Q¦ï²2H–pi®i÷°ËöñRâ ©wôƒÖË"rzŸKèû–0EáÞ|A_Nv…o؈mœ¤A¯XW„ëÔ ûNз⓯P3b†ïñè&|¼è&ŽcP'Ê¥À›Û yq®»ÌÒ±x´•÷é î…ÀŒïþŒ “ÉšÞïO‚Y®‡üR2>HÁ¥—é>§òÁ‰T¼å¢|>¸ ¶„pYºÞ9b3Ÿ„êsßÐ6'"ŸÐýŒkÃ\—h8‹ÊGy}×ê©—‘d;yjh6ÎsN­ø~Ï’Ci%ºš°ôp¯¬‹¡W‹t‘ Ç㓾‹´ŒçÕPfÅ  CÏAñ)gÃ…ÅÌ\½Áê%§0×DÙkà@ûãÍ|XyoŽÅG»7}¼û¾Ñꈦä)Ç\fä‘«,£®´ò°‡pÅÈmñ£µËôÞ¨ôwÊEœ7÷ë“'2ž¤5︦ë3ˆE´ø€öÐêG‰–‡z¬#Ö» ¯]ìØBÿœ+"CL^D}†± zó`þ§p9ð÷“‡`·~üÔFB KÅ*  pÓÀ‘ߘêë»{8ÇØ¶±¦¬­4ÜÇŸT›ËÃW#ç;Î-|ÞUMDèø„öpY?šY‡+ÔŒ ©Þ‡vàYîÌ#Ñ:QÓ‹Ó¦…Nšáâ¢@%$mx:éuIDÙkÃHHþqúXU¢Q±B´i`ÿÒ}lÒl3÷@Pɬ%RT®oÐÙlcó§lbëýd;)^Z|1(4Ìj@Â-ú©÷×’~û¡E­][“?x­Û›Œx÷°Y‚ µ‰3UÑù/™F 9œ6ø”e—BY#Raa…TýäŸÕr³H⒳ѿ”ïÈKÌM Pqg¨_ŸYÆ$Æ÷ŒÒš…Fíö“ÈRŠêN/sMò açkªÌÖ ê¢ÄVøÞ¥l…ð¹… )öª×zOÁŸòDzŠYÕ¢¹òÖÁ˜¹˜¶;¦Þµ£kÒuq“_Ç“¤¶¢BkÁýÑeÑ)äÖðb³¹£#5F Óœ$t®æS,ÆwÇ"Ì„+@j)Ú>¯3õÏ}ŠIެmëg¨LÁlÉ\,Ú"„Épùá°§J#¥)Ñ ;꾸Oœ£ày¨y|Sƒ&Ò)û—9L›}Èå=$gÜ«g¸Uê9t÷üƒÂý õ€x‰lS¨ücñou·fý÷PÄçúèF÷ýÙüÊ›ntÄKÅV¥>˜¿@'uŠýx–ƒÙ—7ØwÉÂçR;«´Ñµð^oŸÎž`,B©`3Rn˜<¾1OŸkj¡)rxH¡p½lÅâ_Ý3UÜIGÈÎ稜‹Ôf<Á JQ‹XO+Y«>ZÁ£ÞU$ ”º4_!-—©îyzNyõãÆÐµ’Dp·›cG…‚àPYG®J¾ ISýZУi™²Î¹–íc¤%L6®:¥ÿöJtü,L§Ê1^˜•*ôM;¨OÈlÊQµ±ÉŽ@NË ¶?×üN+Û§Î'\3Õp/Ì3Û|Ôi¿ƒdÔh^st¬=e„Ñ__ïøF]vtùÀ1奥 :Ý*ërAQÙ=ö«{wXéK_—ñmÔHgÚ3µxÈöì*Da£ ÛKuÔ5yÇóXn¯££Q·x)$™ùá¤%±¦PE§ ÞÙ<þ‡eÅÝ~ê}šå*¬%£UCÖ%RpÁ¯î`TÚg‡»<‡ÁÆÈØqá LÇÏå:ã=ö’ÞÕ?Ÿcºú\Ø /o!ö …€œÚÃlå®D6µXµCdûkú/ñU7‚?Ä“9àÅIHܨ»-õ, èu\w{Ü…Ê¡ÙȺÞÞŒ¼-öźm’×Ý|½½é¾Ð:Yç?E[æbœl³¾»GÆz˜ˆ³Ôä{q“GORô£¡›®Èz‡½-¢¥ž(BçýˆµÞŠ>‰~¼×a£ã{ LͰ¨ªf‡õ(7°o°W„ÍåèÚâÇ/°ðýÒædOá²Û)œÀcýé¨Ålè³|Ï)ÙàѼMõÙþe˜ùé?Ú}!ž`õußO€í=oýjU/¼¢ˆ4ìO’ï‚5u´4˜¢±‚-rö"Ïņ¹F­¯+%—C¬±ëüæë{g!îÞFµøÄ=_ÿ'±¥xøÞ5‚q j7Ї¾Ì ¹Œ½à;ÎRÄQ é‰_Ú}’nfÛ–K&ž=Ȩ‰¸ŽMRøs·V¢,[9€éûj²¨,ùž­jhüT!ñ'ª,êã’450{¼7) ‚Ë< ë Së0­9ÜÌN†¨Ê†œÁ™ÐåÖÇý)ËÐ~Á·Ä¦8˜ØÜ`HUuoò¦>ÙÄC̸ôXØà÷É$i‚tX0à $È)± ÁLŽ2ì@ë‡DCT&IyÚsm&™,xP&Œ …3Åwrp3Bu"_«?â"'Cê +BFöHÚªà KX£Ù R»®´±]ºçÀb6”ç¸ìÌ5Hï¢Ûål=]÷Á¡|Ô>(RŠh“L)7}Œ/+y)À]6gñóykntÕFb¤\ñþüf1³‹0Ñ`D@s3|Ü_ï“ÄIjy¤3š˜°òx('6>Ô-œŽâçnÔ 6xò•ît‘”Å;j5 „/\ø ØáMûÔ„*7 /µû¢Fêî½mtd—/XD`5°ÄùLK *ÕŸWýjÝK~%òHæ¢ì@œÁ–w*¡¬ÄIg]~àV¾f—&éøíX°¡úB×~/Uq“1/þÍo2·v{Âã'­*Üs÷©Ív>?2R´¦Ï!ÞŸîò›F ¦ôO%’îÔ6À—X™¦Ãľrƒ´¨`IØEG@¯lM8 lÓ·‹Ý a²Ý}BÛ\¡sÊx9 K•k–‰@nçÜ•^’Z¡IClvt=ÜÕíôOâù›®ÜOX¥ë¸_örZ¬ ‡!NuEFÍËË=ñYÓ§úÊ4áÎNôà&øó±ìõJPr²&{ß?¯ŸeÓ6šDfyDgm@ªáa–º4¥e?bžt  x ü%7~qŸzl€ØW°E ¶묰,_?\²!¾WÌ´•Ín]a‡ÕWö2Ý\Ë{Eeî¾&³m˜§>ºuÚŸBŠóàAÓc3`ÉÈš™–fŒ„Ö¶IY÷]Ú×T.´,‡Ë΢?§CÛ¿G8Ÿ?¤6žàë+Ç:TAN ³w7*Ï8° k`u¶!V†g–üsÄÚrÖ;ÎèµØ‚-È ¤÷Yë/K®À=^}͇scÔµœk0K6¹ùh)ÝËô½q[)—®.ÊP¢¿ §½@‘ýh;.œ±?ÒfÆÝá_ ¾Ç˜&Æ™Kðæ½Ù™¢.>yÿä˜ÃŽØR\ôŠc^­âÝi’1F/êmº@sk¼Óõ‡ 辈Òܨ0±Ü)ù¦]m‰×¦ˆy?þ©®ž†ù:&ïó½=ÅÛ¼UO ²€šÜtîÿSA|vø-£âN¸dûb‰ÎðºL¬—õ'ü‚È¥WÞN8 S¦BAFŒi¿åï0O¿8÷Dp.“∾zΚ=“žÔ|­±ó6Ôõî’›Ÿ"ÖDÉPŽS%n–3 ¡f±¾ÜÔ;ܧƒ"X¦wžÎU!Avñðjˆ–6/=kÄhã/òQ´¯ÊÔð`myÉwÚ}ÊF;âj+Ëg=¡;ŒbXhÖ9ªákXø„—êyçyÏœRc €¸&qû¯JXñÅŠ™SX&ÜèªÜ¯¹M¨qùn©Æùn/ÉñV;Î~‚Â"+âË# ¤~ôÆL2½™æO•R¯¸¸yÑ[$wi²V 9ÁoTXIb°Rkä³®½Gr§Ã0ã¥[ë„&š0¥c¢hæ«6> `È„£l¦g|WÉùe[B¢êîî¹È¸"y×!$ˆ›z~Ç z¶,Æó 5•èP-ýtÙc TÔ6ê8ÕF(Š^Š0z£‘yžKL_ÅÇÙEÊæÒŸB¯ƒ{"dm€Ÿ–]œçVEBÞ6ÃæžUàvõ¥ƒ» àÊZ ´;qOê%—9ð3l'Ôä/õú¤à L-d^¼ëoÜFß;(:¦S\Sbª 6R´@ã 9Xq”"Ùþž¿§ ® @6ºÍ`²Ë¬ÁOCWxÚ¾ ÓªÈÑ(8M¾`;ìb2œ©iàbj­‡oÔü (ž;c×9ÕÞ—"Ó¸T¢TNú3|~&îŰŽÈß·\Ü¥,›Vö‘˜´×O›1qLJÎW.B#`ç×D´èý|* y»—kùp-Ó.Óù=ç·váë¼¶¯f-¦}6¹ϲFÜ”ïÜQ¨Bžt€ä8+'À<GÑMLXa;¬Ùežáhr±¢E»%¥ÙºS»ÎøcÉ[‘±Šû ò0ògôÜI…|qP½æëEð^¯¼‹é…Nuò¨SuÍÓdÛ,¢|ã̾)ûjµA‡ 7Þ`©i ¡Üdd m’É(M›É£>Ô@_BU)Kb|}exƒi}qÿj ó,Ò8øÝh$Qb‹LŽÖè´:>¿Ð§TÍ^k¨7Ê®ýÒç ýÌ %®L¾34ñí5Ej¬i®è[M¾Pƒ°4ö÷V’¯À9!‰måÊè÷ÚÌ zø ô']¸)ƽ± "RËÕ㱦}Nˆ x7û0’НŽG!®¶Ûn™=Z𗽕.Në/wà5õà3ë³T–Â4È4HúeóRÏÍl3Á©è½Ä£†b ‚;pª‚ŽŸ“ÇÇZ=º*ö°Zg)>®U– h·|â꜇Ñ4¡8 ²¿±Ä¦?¯;[œÃµÅDU(,¦ _‡pßJ¸äVÉw²åí”ÚeÑ—’D·µìTžzØ“>ПÝ':dÓz`òÊ¥ýÀ&Ê XAŒô„'•¬#WûËŸ)ŽNù°,ŒñZÑ#ü!ßT>•¾t·7[µD®&@5Mßug.G~7W³f¸ióh°ÇÛžµaœPNN뺇уŠÝ# ¥Øh<š•µú–¡àÑð‚èõ‰9ÆÑyúa,âQ)q½Ú¡l˜<ýRRGë>iÔVfºEåD™du{ƒœ &´ÓÏpW_áEé….]“NF6d·"º¼+ï¹ß¼4ÿù›ã¦4Äö¼•¾kQ¼/a¦ü+´&`™4æÖOÐ/RÝA‘-Õ¿ ,.ËG­vå¦ÏUÏ¿ %k[F—7›ÒÇ@¾·ÌƒÙ¢â\Q¢of¡‚¼úëÇÂ/¡ˆ*º,f=×_£Á *,eê1u€‹?4Mõ6WDÏKEMU 7‡b{ˆ ÞhrÊ)1'eáàƒvc_¸ÞÉLÅ ÇÖ£*ÚPá›}hJÇê:zaŽ Zù±w†"£\”ŽÒ¨œ'þãÂ`<²Iö£Ì)<¥Kw->†/õ»¼´±ã§ï‡H”ÍJZüTQk'sš³–èQ^´CˆŠ‡yKœÊaÓQ5¢S¶å7;z ½ü.fÆz=˜ ²(ÐïRq+–Ë…ƒ®†%MbâeîÀÖ/Ÿ”õÚ²ÌKèBL) â„$¦–ˆ$¿oH(_£8/ì°srü£–ˆ54×^?(™å 9£Av›*ÐÍr}¬˜a OFç}üô‰…IQŠ·Ròºžªßh¦°ˆ$ù›{Žd}£Ö•oèug‘™°§Ëoí哆 È€æåû}^ŽsfÈZP¦¢Ž˜*@¹öçµB`ò6(jÍѰ ø¨Àœ*}¸WÉd€Ù0¼Ç`ô•:f<²;jvHÍ6'ßvHâ^Y#D|w'u¢®ˆdªëÉ>*¾ùÛ Kï|ç5me䦚KÚ¹\ìzrÇñìÓâ®×9ñû=r )oZÝ‘šT Ù¶{ƒÉáïÆºBõé+p”BßG¸®˜[Æ  ÀȤuÀ-…•ÜÜñWÀ8>Š3ý ´\"éøXÁ˜XPVbVg+Ì-æ·R¤â704 Ÿ#üõé…d€e I­XÃÞ)Tʴ쉬[ cS»[ä …²œ‚·FDÌe C}#Ùëož“9´õ¿’¤—T˜›PBc àC+öm©Ábå…ØbiŒCƯ9—ñ{öòVžwÈgå+ù¾Y>x„ Ú3VÉEþpö¸ýÝýý‚"¡ã…µKÚw|£Ç»AÏÙqÝuœØgƒ<ó“Qv‹à²Ã.¬Ø ¿ucçw'gr«©jz—̘鹩S/ª9²¸ زÓbÕ¡-» Œ+›ý®ô镇%RYZ}1 lóøïîl`Ï#£Ä‰¹¹˜Ÿ`ƒGc8ÕögœŠá]Öœº—w×y‚Âf;i/ÍÔ‚1$PéÓ@nòžA“ݾóR”¾‹`hè”ýrH7} ÀJñÜÃmLbÆ‚Ÿ/<gt&c[ov}z^ÙýWE(Y]g]”N¨ w dý±$ì+ÒéÅ‘ºíö£è7×Ç…*®‚†;‘ò—Oô´è•8‡u8õKu0ñü“L¨½ª¹½<½ä¨KØs1"4úìC°l4Åê‹‹¿?NŠüž-u¼çÝᇠƒ'àøÑ±•.^Ÿ¶Œ6»ºõ¹ŒpêŸä—±ºoC½€1=ðCDÍ5V`âä'î"S [PGö‡y³X#\%ï¤ÅF_Þ‚nãä$(v%›|Õ`;Ô¥ßRgv—GácQGFð©çR3ƒ]¹>‰ðM.pºˆÓŽxÛ¥ Z‹ƒ¦œ‡Ñ•[ž(R§êNÒîÝìR˜éåXdQ½Zé\ð5¾‡î‰«”›Jˆæ¡è + ŠeJÒBì3D(]ôG’ nv+>ê}m,ri²Ut«±¨ж¢-oî6h„(¬³ÏçL`šÑìŠPkÒfáJ$¿Ðåî:ƒ˜êÑïzD󭽜‰‹iœPRk,X¬‡)s&ÜúC ¸†îS]®ÔÕ½À¼”°…FUAþ`Q:„~!œÇ÷óƒÐŦ«–¾×“_Çç»,ª›Á!¥ùÙCo„…ï‹õÉÍÍÐÇS5+b>.pŠ`Žé+xš0×µXy[]ð`-àñšŒqØËŽj,g¸ÜÜÜ~ýf"G»öØ}»6EÃÏD¸j,1ùh–u:SÛ‘,Nƒ¤ße°Cg™8‡…óÁ;q]£qK}8¹ª¢ Ǩa%‹Òù©Tz ¾0niGHxŠá‰^÷2^PmÛc¥H4u›í–ä›éò:üq[Ráš‚æ·93ÛOMá•Í©[¯äÁõQO ‚jVÏ›0‹8:Ó¦J’?®Tòë8ÒÁþ]ψ[„–C»¥d¹‡œ¸LÅã_¹%r²aö žÖ<º *ðĘ3§ï£³â†­‚C &Œ:Çðâõï“zfÆyMt¢bE¿¬-z]´‚ VïJò2Øg<ÌÐŽ(@TÄ áB¬C: ÷qÜŠSW±ÅÒXrë~ävuy~•ž8Zíãk,* Su=·L¸xèÁ‰NôuOÓŸ¢ô¢£hlVm&š®!$IÎÄŒMî«Ö~*ÆåÇø8ì2}Ñü6Kǹ-ñ­£ÈfYÅRUñ½)U©¹`Ù}fªå eª8ÎRÅÁº3¾JaÀþDLlЯXgó󳩕‚††û5Q}ž=êáíÅ'›«Àžã)mHö«Í˜÷_·ÈxÉÓðGNþª/ ¢Ä Â&¨f…ƹ î±ÒÜIèc“'öÞ¨šÜ…A/OÇ&”¬ ©÷cÐ_›'?¥õò‰š]‡7¶º”â[‡C¡é{ÐÄ£IÎ ¬ 4ÃtÁúïÿ Îþ’™] œ´Àß°ðÃ:©Q‡‰J‘/LUépß B,.h³øô$ã…é¬:SÛøf$J°dÜÄ0û3¥¸–Ye-»NQ“€Ã©ç$oÏ·ð$â·'óe2‡"ªâeM\6æbRýe:çãüE¨ÇÕM“ ŠÄ¦lÖŒŽ®˜Ý·Ít™ u™ûHÈ‚¨Ýþ£?‡ÜO‘ã<´Û§ÕàŠ#^<4‚C}‹ [¦³¡ Ë'Ê’è›…ù¡xÖ~ }Ë#^´T®ÛñàMùƸ¯ìeëµop[J·~?N+Ÿt(•¬Þꊺð×Z’7ÍmÌ ¸wáSÊy~Ök7?ójœ{àÜÓ8»»1ˆ†ƒe-¼žÝŽ»I[à”ëa¤ž{¤«qºÏ­õ¹­{‹ðù³²_™Œnq¨cIß²¾xjÓ+¤J\Ž4~•ZtC‹–c-ý`)ñûƒXöû¹âÒ•ú¹$Ȩ6Czñç`Æ Ù0@ÐnüÈØl/ïy¡ýョRÓZ;E@ÎIíÌTŠÈ0ÕAb@¿$6tÎÔ‹R#o¼Äµ)!,šýâ0ö÷30TML§¾è.Ô*!‚AÒ˜¡q$гÓ5ÍcewS:·’ ýOkæC’ZjF“éƒÖ25%îK þ&®=Øç ⇳§óà¸ùdõ1î"‚_ϊ•±ºŒ& 4bõËú¨<Òú¾wç?öm!eYkt?>= „Ü)u¢ˆËE»Áj„*†{oF7µG~»òËûŠ!R–,åbÕE?%¾AÐWú¨Ä1“|«aã5¤Cy0HNHö‰“s†LYŒy8 /4Ýš ¥’zzž³E¤NÏJèýù™¡Fôkéã;uÁQ~r3:PŠÐ¦0³ò:|Á{?_Ÿ@%8ÈC‰iÄîžÅõ…2‘4õQŸ! ¼Rþ¼ê‹Ï{†=ý&Áñ‡ÞÉ48þ|gÎ"¯ éîÛ¿Ó¬«„—Ã_³µµ{Ô›aM€”ÐUà—®h|é‰ßÍòcåÚi$Ê#Õ°¶tƒx[§yÆ1Oiëc<:RpQîób‚½yV¿ªV6›±'Q”/e5û/·…4#µQžeFÊHúª[ž!ér†ÛŽ¥ 8Ôà"]ß0Ë,„ʦ(³ñ~7µÕ‰tvIz*9§+5ÇMyi›ßév²£K„bÕYŒ¨¤¹š‡ îR¯$ÈâÙRl¼SZé†\£ZÔkjç‡j‰âµ¢PI)P¢B¾?<)X®h7¬™ÖbbQòß ³03ì!– ·©Ì¢-!ãvêÿºn˜ÝÕ`<È,syB8†5í “8 e9òoB˜œ,~¹’Fu¬²nû‰O[îðô±=ÌQ Î&7Ì[ 2]é‰Üìó›Î,ÀTmFc÷Ke¢µ4˜ÔÅ5‡µ8ëO‡žÜå(U,Å% »ò‰Ï¢Eƒ±à~‘çÇ5½ùÞ‘ïO‰ÙÝw­9„ß–'—„[²ïšìSÀfÔº~ËŸT.¼®$÷ ‰ÜçÕÞË(‚Lˆ|Q^  2l²Gø\ä=f×· «µï6‘;¢óâµ_|vÒЦ!äYŒ¡þßô­8ÞHt†¬¢ÖÕ‰’Õx‘Am-i-’P«4áí™ß †{H ”Ö]>~a1}g%E£x[u©d¬ø¦.d+Íu†éŒqá¿õ½j±ƒiŠÒBôv“zNÞ´%¾jèû]Ò¬Q¢}™q«º÷7† (àW^|0œ?\Å8an‰¶Í‚¡BãSˆÚݳ¹;€]û@E%÷'ëZ2qôÅ[BÛïŲW¼§«þÖb¯Tãç6?pJì O}5ûQ‚ÄFI÷lY áľ_gÄÑz±X0Ö¬ó?Ò (OŸ’FÁ± yvŒÄ¨ïh(nÃHÕfèb1<0h˜ÎË”Ï[)vnêµÑ_ ¼ÝMó‡g6*Ô–~+N[Þº'<Ì”ºÛ:'ÕàG-:LÝù^yðŠìAƒADVE`P/Ã5ã¸ÐÍÙ“oÑ#Æ£ $w‚á’2Ó8éoe¥à1/ÖÊ“S¯£¡`2gWµ»´@ý4ZÖœ„%?q4fùûwñÔº²öê ¥ïøí÷EÌDreÂðŒ‹¬b…СíO*ÿ”)¹"0XÝ—EO‹¼]5wvu–U衜ð53¢ÜeÿûÊ™¾¼)PžWxÜ´Í0BŽÇfN¶6u|4ƒ‚·ãeŸ×÷¸|òåW¬&ùêžog1T¡ùUqÿÀ+úC} E*–F‰„¹PûáÃÚùÇv¹Âõ­ ÖæÅb"ÐŽ¤| ¨;‡¥Ë—Òs+‚»š"«9µãè8Î}(?(›ÃO÷UÜëuDÕâÆ2 Rc@ VPcPS?¸-ìÄV3'DµƒdÚKÚÁ <Êé³i9"¡Š[Z9>í[Ž¿ªw’ÀSža(Á._©)ˆ™Ý;|Þ¦ÛqñSùçÞú7Ö’4j^@+Îȼ¬H-M=èó`:iX ¾}íM…¾HÞ[7ß̈ÕÎÀº»ÄŒc"ã#• ñŒPéü’L¬õÇ·¹ýiT¥Í€Jò¹Nj|Ç«¶Á7xÿ–!Ìcóóïêø÷t±ëøúɇà\&åñ{~–m¯,ûõÇŽ”þ—áX¯,ƒº«à![™«ŽlÜìB•É(l!ÝLU*†6§®ñüá+Ïr3$)vÚÕèéK±ÑmÁpüª³WȉY´\b¶U»¿L¥ßKP̶w$¢ìý+vÐhèÆÌÁú¼&ti Z¿àΔX–û¬ŒxH<-ÓêJaúOãL©ÌޏYûßbž&" Auª`&=ÔœOxW¡í0ßÛRÛô‚]/ƒluD®]‰²¤9äÙx6³ï°Ù#èÕ‰ª5“º:›.GDk0ÒöÉÉΓº¸[§üñÙFÀ’¶æí¦f*šÞËÕmD]¶ÍÞ¸p¤4©ôR@—Ê´ê„M6œ±[Z³ þD*º@ÄÉ–™1,;J˜¾io0ÁÅI=F>¬4-úæóŽ{Ì+ʱ¨ µe¯Ù¬–@këø%Òè¼k·3Ç"cáWý¢|-s= ”?D9M¸Ân@ Vñõ?6ûÅ2°“ƒ*Ù©¿]C~vü %Q¸Ch’Ȩ¨­ ÂwoΉ•¥Å Ã=ÑU9ztJ䦚úyŽÞ]9¥KâöÞvl”Fa—´A?‹_Á¢¢v›Ýc¸pºŠuƒŸôE¨c¾Ñ.fã5æ cñX¶;{%nʸ²Ðq‹j}$‡#ÈÙuõ.è$p£Ÿ–‰½ pù˜Þû³D4V® *{­Rb°“fÒÕŸƒ. ßõ¶Ö¶ùùpØ„z*G[Κ¯¯0°ßë'Ë~Âéé—þ`¼‘pEæ%ëêL€!B¥\÷!M7á¸ÁCC ô¥àTNÜF+¨çzÏ-&<×ë`¯²LW&–Û›]]ÒŠ8´ØIæ‡üíoÓKOèì½ÊÒÞg‹ruºíi“‡ƒ¹Š¾jôØ\ò·:öJÞ_©ø|Ç $—¦çZ¶ÂŽÔà‚®Û\AAÜ{ðyeÜ\ñàôª##“7ðͯ„Ðy–œ"xïb{¿?¾bî² h3ö±•Å+šïë™7§§(û£è~å­î:3Ī^ÆŒÓä¶Œ¡Ëéoq¹7x˨I”}¤;ü1ž~ž™ žl±¹`çVßÒûÈHXq6—B-ÆÚ6Ê!@Þƒþ’“;¢-xôÎ#~ØÌPl¿Ÿ±žhšê$Ÿ…@Pª ~TõS8šÌѼçôÒYí‹–º‹âÃÂSÅ. 'hM ŽÃæ¥(×¶´ÇÎIü¤kØâzc5Î×EÖ(ׂeâ WÞ…„° ¢C&k©ºh@Š'Vçqà,„¬àyëÊY³ UNqþ)¾½þ6\äïüìòí“”³mØ´±&y*LÀ®´òœÄ¦ä~«XLÌóŠÀê¸î2+ª°ß­üM¹º¥+¨0/RW$kXz–ĹAIò+ö‹hØêe} (VÚÂ&;2™ëãU¢aïsï±(ë¾j˜hºi5ÉßÚ4d2\ÇÅ¥%œý´#C…—ͱ¬"©ù~moZÿ@ÿl ªùÒÛ\G‚ãƒÉæÄÞÅ]sÃîŽæ$ÿb’È5 — FJÓqH«G•J×Aèy ™Mø/è–P=R3bÜaA›¬k¿ †qüü-Óf]µ¶w,Ø+%cÝûŽL &IÂí9¶+l,m+/ˆ/M¤Uß7Øè»„7ÇJf|é Cc³ÔÔŠï¥EŸá¢Å‹i3íö‚w ã>lŽÈ$é@SÆh­©Âų=œ¨;åX EÄù)Ø¥ Pä+|ó7Õx¹ÇX›¬?·ÒÁ·[{_®Y¨ü¡Ç={ª.ž˜<8À{ÂVö Skdïi¾0;z›fðS2Ñ'wòWepÔŽKF¤V ®©•Ea…óÚІ­ì"H&ãå'%¥nø†#á8f†f[ïn)RvRo?HĹ”Ÿ³Æ»,\œrÞ’`‚®QV›«U'.P#åÝ‘sÀè—“~ÊíVð’@»ìÁ¿®u’ÛúB0g.þjʧê~á"¦›¬N’ؘ9ñ÷¼Î¾%‹{Ãj~qþiy0YÜ&˜¼Û3l"Û–¡¤þtâ¨]ïw»êüÁë]8¬rÜG[Z‰½êx:â@ &=S{_bŽW‡1dã–æ³¼6ç]Þß]FèÜà6=¤zë“p€XVoÕZ–B¾n=v½äªk²0SÕ®ó¼L 3œkÏÖú‚=’zösÊçÓ+®¨M?¾D4ØÚßzù *V˜È*Ë9þË£¶¨^dÙŒð ÑIXÚ_É£„éu€vóT1O(·D›Ÿeµã¿Ñ«JÙÏ-qnˆì}³âA½FX?ùÒ9á§<D1xÐ¥µù£’=–Ç,øÒ-­•v _d X¬WØCHXŸ)e=º²›AgÚÕ°åvС]4¬UÚ ”äÅÃoZž²rP}vdª}7õ<³¥ûEް^wûô`”g–£ž®tä¯ëQöc=•N±Kf½cW¢¿5uÑ´Ü0ƒ¤~²š±° 9¥æîZ+y.sÉÉ|¼±Oì5E£Öß_zT›ì®6@S g(÷ŠS‰XàÒñŸîíñÈÞÅ]xTíÖAžõþ*ÿV&÷ðrîsÄZb²@¤®ïŒ¦»ÿ«˜:.+c¡ ¢²¹^Cï—yÏKÄ]G .Iä–úÇ´Y‹uƦ²T£šýY7Wc$j+÷`Í[à’±‹üIFÌ{ß© ¾1l éB~ÖmÆÅþ<|sʶ°°èõ®á‡V‚ã« „!·Ç·…*†ãûÕ>†ä¢X]û‰¹&nŒN5ÁrjKlF]öôN+äÎDI¹¡ÐÞÇ…´’ôvº*òL±Ž¥ˆÕ÷'½õ‡kê¶yÿì—]¼Åà”Ý{ ¿Á:é9ûË>y–£‚s…Þª7³á©ô„6^ؤ„};hÒ1â%FŸè6¢xu&·êS´¥‰èÏÍÏ”ijéwlã@©ÚCáÔÄàzvoõ΂‰Î…¢ueýï^šîf¢Ä´¯tÚÁ.µPþiT["eš›?¤;,ÈfÒ… ª'ðšóZÈ–]IBpõ &ÑR ~žƒlò仩œ"ò+ëTtŠÈMŸˆ­$o#ÜŽ®ês=x#‹(}(»Š:Ó&»g™ˆÕˆ¾TQŠù£C¯@mfƒ I+Aÿg‰30yŒí›Xè¦'¾œZ1Y-¦e¢a;:5ÿnzR ,E}JAj¤€ešß°ÆNÞ€ò»¶C" êζäÄ _S'á}è÷¡HCÚ…Öê! ³ôÉûι'ø·¤]¿„%N¨¦ë7”þœ¬—'èzº6™¡„â·ta®®!؇›/Lq¥÷ØrW¢†ÑbÖÖ9Ò‘JWnÒ”R¿Klõ±3šc°]%\9RT¾ÖRæG›w‡µ óäÇBqŠø¥âCú_-ffyGÑ#DZŠ{ ·Ì¬¹ÕÐÿzè5ej ªsFv®‘ÎüXˆˆî–.š…†ÊopòØŽó0ê}õl%•¤G 0ÕËR¶'&M7\m¡<¢>rÇŒLÏ´Ul;d©&ÕÜ-Ù~*H$¯·’HÓz<ëòbV"ŸabœŸ‘º‚ ´êj–"üyìM@ôNEfÕ$aP{âó³_à9­/©ÏzJxM7 ÆËçÅžšsnó oîûO›½ê6ØYÏ9-¶ìÛQwŽÊ$*}Pÿ¥2ܹy­Ál9%FÈûvY§çsǫݛÄæB5´ <Õ»?FŸßo9f!–>Áe TâZÈO$^BÙä¾w†©T´ÿà¶CÁ­ïJKþ8¸¦Y“é@%\à5m¹ìóé? 8ì—ì6¶L‹‘Lj8ä­4ó’½øµ—…†jK.î»øï˼)Yk]¹ýS¶ÏÚ)Ôa~s­€áŒX{ŽÏ¥® óJþ¸µo»Æ¡˜lñ??ù–Áæ~È®ž ÓÔIOæžíU4í\ð‰cFà™ëw‚ë¢‹Š­'/}eôd·¸›×á«OæJFÅŸ3[gî=ƒkñUñð·+¯>zSãªîögRÌ“î[5™K8MÖUö¬u\£d¶²Í¢¶oZ†gz†ðŸikì¥.ÚY–qœ5õiX,X—´º[wcߺTƒ¿ì—®½+IY¹ì:¯‡ÐÞÃ*‹ªôßäÛýÔÜû¨Þß¹çUÖ3ŸK*j0ßœ_!öwþ¢„œÃö¼¨¸TÃyúGÐé“›óªì⻦ZÔJp7‡·…mª’^ûFjç<ÛÅK½­.‰z-v'1ÝÞíîë?Ó#Ü­Uõ¦?4òV?•#½iþªòsÜvÏø™=5ÃÛèW¡n˜°¡çü°µf—Õ5/Ïü½÷§ÄãÏá§®Ô®ckt\z]·-¦üÃ…í‡Dæ?®~ûB­ÚOQÝ-j®»½îZ>-qd´Y¸[âë¢!e6[ÿ~ñM] `sA6lŸµð'æûÿ˧XOô±ÒI,‹Oͯv>´çŠ¡ÞJ¯-J.Ç|m'L_³rý/Öo^Ï; éê¥KÇ—ÌM·ê¼}b‹ÄÖMyåÛl'_.ßý×Î|×òÆÇ¬ÇžÝŽ»þüß·³©Ú»ü—÷LÔüæú–¡÷çëöOü¦œ ^§#Çõ}Ap›ÃÙ#¡3ÙÔtý½yÞŠÈk¢úïb?¤0¸>]ë7±G»®l÷¶ÅÍ“Ä%Våéýu·o1qói†c…44.Ÿ*vôÛkY¥ß‘GBîz†;;z„Í•»Ö0yú—å:¿.n/>ùîÄÕYB¦ /hÛF¼5 YÝdÁÉÙæÖ³ÚìzïkÇÌõ/ßõÍç»°Akªýö‹ñî'7jO_^»ÕQl÷›­1¿Oø7§¼n(JŠÞ¡j©{¹ˆ'¢\M†¯ÒY!Vä÷öÚ6KÅ3öéÌ”UæèœbÀnµ }^dºð–ÎË¿€•Ðö k]Õ¡NU[î×.È<¼cÕ²àÉÌÅ<3o<å<ë;WÚCòÄÌ®`uÛ·Ò¯>\¶díÓÖú½Ü­&´ñ¯Ò¼¶ï¦zþ°ËïOãû÷òXÆyÛù2©·<³7rZ_UóD6ŠwÅöwM=µl'o‹×?Fù˜âU±¿ÏMoX _ÍÁ/­ÞiûaÇ _—ùÂ=jÕÅÊëS"­ßÄV_wºi½SdûB.¹_ì=Jò\3îD=;uR$MØJððûY,¼Óî]a~9!N×\PÜ0­ÀñÒ¤¦Ø×aÁ'¯f)O]'(µáUæƒ9%Gþ¨ÌÒ8žoï›âòÿŠsGÛ}8£æÞŠ^SÁ¸ÿ+ÃßÜ~7‚oéÞnÖTµ7âûæ#Ê”Ì,ÿÖ¯þq`Ü[Þ¥µ—«ëô–íix7õÂÏ„™ºëͯü×wøUþnß³éëÿtxñŸO¹Àðêñ1ç¼¾Òs›Ò~òü.½e-?ƒÏvc÷¹}Æÿì4K´2òÃWÔP¸F $ç¤&•äç&esMøª#endstream endobj 12 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 2 /LastChar 148 /Widths 309 0 R /BaseFont /KAEWDR+NimbusRomNo9L-Regu /FontDescriptor 10 0 R >> endobj 10 0 obj << /Ascent 678 /CapHeight 651 /Descent -216 /FontName /KAEWDR+NimbusRomNo9L-Regu /ItalicAngle 0 /StemV 85 /XHeight 450 /FontBBox [-168 -281 1000 924] /Flags 4 /CharSet (/fi/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/seven/eight/nine/colon/semicolon/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblright) /FontFile 11 0 R >> endobj 309 0 obj [556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 333 333 0 0 250 333 250 278 500 500 500 500 500 500 0 500 500 500 278 278 0 0 0 0 0 722 667 667 722 611 556 722 722 333 0 722 611 889 722 722 556 722 667 556 611 722 722 944 722 722 611 0 0 0 0 0 0 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 444 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 444 ] endobj 8 0 obj << /Length1 1199 /Length2 3076 /Length3 544 /Length 3877 /Filter /FlateDecode >> stream xÚíXW\SÙ·FZ$¥J'0&”€@ˆˆ”Ä¡)½’“ $¡ÉPF¥X"MA… -ºTQ±0EEa¨¢HDåÇû÷úvßîïžópö^ßZßZëÛk¿uUG's-°¢Q™:H8 ±'‡„3œpT[Ã)ËÄQ \ÀVWw&3)ÀO]¸ %À1É4*Çäú8†Cìptˆ‚D (ôwÐÿæH££!ŽtríÄ`t ™Ê…04|x@e:…‡†RÈá0À …Óñ !r+üyfˆ%-4šN&2!P—Ãn0--í櫓±1$ úÁ 2‰ Ñà." -t+— tná„-_G"îÌÜj d2CѺº¡DÀµÁD8`ê¸Å ,i![ ð–~2Às‹Öý™†ÁTZ$5æ§‘L%|iªëB%‡…XÌ?\ø»0!=„1 @>Pw+µst(ðDn™qTBlL(-BÄQ@,™p?à.€0éá@lÌþsF"!2ž HÜ#ùÎÎ5į{;“NŽ‚x!à‚Øzÿ]ùp—@£R¢¿»ÛãBˆ®£…“›ÖÏúÿ×Ó‚ƥÕA¡ :z¨=$’Û§±þ¬ÿêñM‹/VGùŸZß)±T" büµ%®–ßÚŠè î¬B _FùO~{“Œ Ðïcä0@p'ˆûAþt¼þÿéý˜Ã*œBù¢ ô«$®& ˆ-dK ÷âl)CÆÿ(\™ý“¸Ý€¯âºá¯ìæT€è õ¾É +r@p$3ñ_gç›Ü„/p¤1È[Wœb€üs$ラƒÁ=”/@%üôO#©$ˆ“;¢8:á_ÃŒ§Ó¹:}9)nì·=‘Ì-¢›7ª•«ꦖƒNÉ4éx¥5Ï©é0AåÊÒ*!‡iÌXæÃÑJÜ!´àÃv "èhJŽðÁަë»z 7Í¿—¬j“ðæôXˆÄ?L¶3Ùo<*ŒÐíƒzY-ĵ¡¥õ}BŸjß«wƒ¦¿9Ún¡•'U>5/›èþG¥ZWY,«l¡³|ôÂ`#L9©¡üx£3¥STb¤­S@š{ ¨ÍuuwYlwòšE,ÆÀÄüƒE\Ï)§æ’÷%ÙóÊË9Å‚aÊfAª…w¬nfÞü•qÝ5ÎúšacA>uvÁÐøœ»’ˆúŠP‡‡“Ô¬Ù|Np1΋÷]Õ‡)ˆ»|ûïÍ‘ÝÎ8k;’áÙ'õ)‚ÇE j·Ù y7ó¼“mKú,,É9>稭ôvYMtí:öú±— ø³BÖ67ÍyÃÓÙ™ñ¦2OEt­›o”Í«Åu…õ« =Îé¶áÛ‡#pÉzºT…,d'Ÿ»èŠy{X,ê¼®ñm§ÞÑ!äåÿÚ÷è’iÑæ„¡•F¥KZΙÀÚE¬ÏIGûò¦—§¦þX Íœi)èòÎÒZœMòî›`<¹—:âQØÜzGåwL}ø.=“Ïþî{Ügö_;Wf6í¹7mµØ_p‹_æï««ƒJe—žNfn NÔ acTÀ#sÐü‘¤çqi»ßn»£>Wšñ¸Xö._»á÷ž-Â9·R¬JÖÙi ÊiÐÁ"Ó_Að…WðþÝÝ—µï&¦:?µãHE+ê-ÉKg·ê˜ÊDj‹ÝÛ¸º &?»qr`'ì†GêjäëÓxJž¹ÁSáÙjN‚¶¡äìz+ÖÒÑg'Üw{.Ç‘Àn›ÃÈ÷Pì^'R—%¢øÒmã}V[¼A2<3…¶j¦J,_Jó.“Pä\¹¢j÷ÄåþÒ<ý¨•f¶§¯Éf 6ûäi¶?àý_lÆgù‡ñ x %~Þa´3®•ùha91樧˜Û5q50¹µðw[¢vÐèÉÊ{Gò}Ÿ–#eF$ÏÉM€jô ä­³€YÚ£KiV”ÄmÏÌc‰Ù¾`v˜“n‚EÊ¡·ç[¡{¡;‡Ò”Ÿn¨º§ 'œ¥¨‘ ùDÍ’îÆ ›Ùì„IûÅšäà}jVsŽ×S«î;‚ÍjÇî;¸5ܵ†f\Í$“?ÀXÁл~c·ÈBcx£•«%ð\Ý¢ý<Õ¢Â6I`Gw¬z95JŸ×JŸô¿a“ßuUé^ûp$_úôŽ”»ÉáRgõø±‘½R³Z¡sµ8yꌇ¡™.S77ê|hÚïR´z«täØ'ËÎ! I'R¦KeG6\XS8Œø«Üb3x#:»ê<öÞÛÁ·3TÖ±9>•DžÆŽôß&ÀŽ!,…›  ª}žŒ­qJYØ]_””ˉ ;qSÅZM"¾Ë5ÒÝÖϤ»h*®Á›íÉJ6¬þβ¹÷:ÒŸel›pÉ/Ø÷xu)Úo{åã'ˆ4Ú²†äîÄ\‡fŽÿަ®7Â’r;/òü˹}éh,(-N»!ÍRâ|:ú㩳/“ˆá¥ ×ñηs¬R?ÚNúT~ª?1|àãÂV2•ó2©Ý3”Ðγ°Ùᾡ°±®©ê¢Ëü¼ ¶¨3ʯQù=ŧâÇ0=4xÛ,O«ÉÒ‚‚½¦!ñ&,Z0Á„î7®)DÖ~Gït;]A:ÏÏSwýqû†·^Jrû.‰R› *Ì +MGäHáËÙ%»ûBãëmäQv¢¡‚§%…ñ‚MG9MÝ÷5L»„gX†¹á'à»ZÞ\™üdZÍß—šýÀi©seÝ¡7kÝüþe#¯¸¥¤©ÎFÕJ~Ú„3 Bê[8N=ÓoöìsýX^ežÌeDä•OJ5wÄnêäñGå³½FAE$–U¡E‘G§¾™xFçÍör‹¢òŠãM­R‡›ÌÎïúeÒ!âå'5Ot¶2{Ô¼®N«ýù¡©‰b=Õšú*§ž«vëùÜÌùUTsíbËü ¿‡‘søŽXíuXGŠÇÌϧL:^(xÕ«öꢫ~¤D¹—l̤x P ô¹ì•YI–øûÖïZfahEWŽ=EèQtì2ýò¡Í½à sž§žo»ñv¡jx?áJÕ-ï?=<{ÿZ ×yóXðŠh¬{!­½Ûc²¬ïÜz ¤¹"tmŠ5{tݹèÌcl¸oU˜ãäñò*eL“«`ð®þÊ«ïEh3ý”àCãl¶È“ÀƒS32 Fÿ±ø2=¼˜ré ¯²¹ëÃhŸ°ÄŠW9ëìW¢´})²šÓiœƒãøÒ 9¾,µkc'–SnÁÞº?Ö¤‘óœ *wˆteò„>›Déz,â=‹-_»mõàòJøÍ„þWúCkÕ+ ¾J1Aâñx.?)`/†øŠÑÛò‚³ëYåæÎ¼mhP~ååúìãöÞñ-æy {í§yO-þZÆUÑ^©EX¨iÁ<š0©™ƒE߯Ý÷ÑoJŽÖ”‘ý«¡G Ǻñž^oï‘6ýÕW¹ ø¯Ò~ÛÍû}vÞpL©øp›åYÝ@¬Ÿ‡Ù~Rœa<\L{±!sîsZñ¸¨08¸ïõ³çz*R§ãçêF"Ûp¦º®%…HNBTV_3Òî^Å1vv)zCMµÁãKù3‹‰³¿XF èIõñgýE*<Ûúèfa6쥬¨vd‡¥®û›ˆ[p[·ÀeB²éÞ?ÈD¬¼H­&¼¨=\òÉB»“Y«:0dc¡'bnþHeP8u”ìK°³ÀRw¥Ô¬ü&kë‹×´“ûð±äµÓ¡;ÿãïgµÈ-â‰×%µKM:.å°3í늼]…:óÏiJ½\ÉPϵ% /X5ckpå“™Gx‹å’y_S”³Wú½ÝÒªÅ{7ö\+ï¸wGâÅÒöVQ‰«‡¨ næÏ(»ø$'÷”¤=ýðŠ6Âql‹HÌä$ÖÅò&×-ˆð_ÙoöÆ¿«3îÄÁ©K º«÷züΓƒõWjoRÄ?ó¼¹6)·Ó¡}€4ÀÖØ¯FwÁ\>‡¸§$ô¯‹óž­8Ãyrk÷¸ÏkºâoS0U"Ükºð"Ôu§m·…4ôÌÙì»~m±¼Ûs>Îû ì?{ê9šSl˜¢gˆfu<7¹üˆT~'JYaù¤}),pW Š"ão'*/Ú>àÍçêÔJé¥Àš}Vܧò.Ô‚®]ŠYöFbŠr^ØaþN.é·œßûjz?‚M]\á±AÍÃ9‹]l}‹PÞíF|ªÊRš×f‘ç…ºS懶y*î:¨ÑïíÞ,Îqý$Ê?ªuuæÏlöé·uãéâ-TºÄ kØT|ä÷¦—IK@©Yì0âù€ÿŸàÿžàèLZŽ Ž¡ &¾õ ü_N›Ùãendstream endobj 9 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 46 /LastChar 115 /Widths 310 0 R /BaseFont /PHBSWM+NimbusSanL-ReguItal /FontDescriptor 7 0 R >> endobj 7 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 /FontName /PHBSWM+NimbusSanL-ReguItal /ItalicAngle -12 /StemV 88 /XHeight 523 /FontBBox [-178 -284 1108 953] /Flags 4 /CharSet (/period/zero/one/two/R/a/e/l/s) /FontFile 8 0 R >> endobj 310 0 obj [278 0 556 556 556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 722 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 0 0 0 556 0 0 0 0 0 0 222 0 0 0 0 0 0 500 ] endobj 5 0 obj << /Length1 1166 /Length2 9218 /Length3 544 /Length 10033 /Filter /FlateDecode >> stream xÚízeT\]¶-<\( ‡ÂÝà®Áª § ŠBƒÜ î®Á5¸'‚·àîäñußî~·û¾_ï߯êÇÙ{ÍuæÚkîyÎ8cœÃ@«¡Í.‚Z‚å¡N®ì\@a€š­£%®má¤Â®¶Fž‚|Ø :¶®àÿ€ŸØÂÕê$káú„ëØ ª07À óq=<ÿH„„0[G¨@ì †9Ø:=A²P+„#ØÉUáìì` iáPÌ @žVöŸU2PgO˜­µ+€IWKŸ™••í_.!!!€¥ç?€,nkíxó4p;@ÿªôD¡vÞ ú+Wb!²uý«]“««³0'§3Äüã€C8œÀ®œÌO •sÉ@ÿ"€cÿ¥™¬- lõÔ”'ç¿ëfïuwòþ0ÄÖ ô·–@gN]'[XIö¿’ŸBØÿŠYƒ]|@n v€=¬l8ÿ*©ãé þÈõWØÂ äãí u@,à`[øé€í ·p\a°÷ÿü÷6dkå °[?mÿ؟Â`Èß窮0[€1äÿúÿsdú´¡ ¨“ƒç¿ÒÕ,ÁNeyCeÖïýŸYÒÒÐ'Jv.^;· ß“Sž…øxþñŸZüC‡¿E5,lÿkÀQ*9A ¡¿·ó¤ã?ZrÃàOÞ0ýÍÆÌ€ÿίuµµ˜þe ðÉ5O®ÿÑRÿ ÿõï5äS…éïržô€T)â`ût G[Ïÿá„OÔÿÝýÿ%W [+)'k‡Êd —·õƒ4l]­lþn—¨ úÛuÖ€Âmÿº’ì\|\ÿ†éØØZÙ;áð§½øvý[I9'+(ÈÖÉ íúäJ 蟿`+ ö$Ïß6èéÜÌ!¶O ƒ=ÀVØ¿¦¡V"Av_‚Ú®«¥¨ÜÙçéá×½|DÐðbG: ¯s t«‘Û—Pñæ\&fÈjŒØˆW£ª¢"ÇPÉE ¸Û I·s`}$DQ £Üç¨UÆ=Ædúq졌 OÎÚ‘ñìW<¢-»4d—ùF¨ %ñ{um´µí¢þŒŠº,¯K}{šYˆô6àP]ÑÁWSøÙäP‡,Ð. $GùkÃø £²NÃþQE;¡ùÔt¯4Ÿßd°¶ë—cK*ÃáŽo_¹omJ[!·ÕCÎy|Ê<¦Îól}y€ð†›­úˆ_m¬ö¾/žÅ÷GÚàÀbæ )’Ö+Eé‰aþ×_gûq¤tµœñ7Tèôë¬+¦¦4.©{”݈yâWjUu;ÃAuQf4ãN¤ÍÖš”«:¼Wºí§úR±ë= Zá¶õ->óí¢·¶[/r;9õ1¶¡…Üãoâ>üì×ÒˆœkhÉ»)T­†g¸ITn´ÀFÒum¿èt{œ¬*˜Xòn‹ÿä‘{þ›‹«>È1‡§¯Éåí«=ÊÙ/Ó^ºí«x¹ x=»OSÞšÀbûæ¦+‚¦T€…Ạ“&ÕnÂçˆóNYfåïE¿¥Î :KRºNÅ-3ZÂ&˜'—†´“€Óâó¬’$›î¼B¾ã2‰½< ^(ÈýÕ—ZÕ|÷ÞMü?®º‘«f…õâL¼˜Rê,ë$cňïÃl½Å /Ú§rKÇ @Oý²ÕB>”Ó/ôB͸K–Ò¬ÍÙ6ÐGÕÏ8ƒ0¦0Á©`(<Û])(tÝ®²ÑÖŸ1fÖ”¾²öûÁ—!ôFÂ@\ÓiJÎ7¦¥šSsêmNtìfÈyQ.æ°ÙwÜ,‘Di.Ž9Qmv±o÷#z+"üó>:Ò¨ý>Åî,œp’%kSnÂîÈÝõ$vîÞÄ/XZ7XF’g‰V?âÇ|ÿ-S×™¶º# ½›Ò4<Šu×;aønR~Hú°åÅ­OÛ‹ïÁº_q}ûK]}¿T²Õ޲w ñéà®­Är‹ð_ê¤Ï'·ÞÏI§— Z50Ka~ÔÁ+ìM-öÄhÅèxÓ).`}õ;¯Á,Ûg©Üx†GÎÒ^K€ÝÏø{0pûœ=fúó J¤½'íËèVWU_±þ7¨³š>¶«åöו\„t ¬ù|ˆ¢ÔUÊH?Ð;ê¬ríúaV<‡·®vPU8 ¯ \䙈Ôjٌƚ ä~Mei2W$):.…9«ÒÙ†:_Z@¶I¸|xÂWÁ§.)XNîâ'«t¦•¢Ýð¯æÑ3Ëžõ‹»èƒ=ÓwÎd>”™%èPÜuÊz¾\Ϋ=W7­ž¼Ñ Õ{Á®bç*’™€‹^Ô¾’|­¯ÈVÜü:QSâkZàTdQþ»šÈ“]wŒ7˜*<7²™ŽÓ×Y§à×Úþ^Lv‘ù)á?zôKÜýÍŠP.ƒµò[v.±Ð|êË®¹QÙrnœt±P—Ó>ÄÜ<Þ~Ÿüˆî}ÑhÈ ŸA‘æ¢Òÿ`ƒ¹½Py‰ŠÄÉ<1âby¬L ëK2L2y!;p½óéGK cYW` õÚ˜üÀ»Œ—–Æ»9 ÖÏ:¾±Ý¦ÁÇ}1325WÒ?öµ-ÇM~e/ð˜õÖ‡ÍÇ}¡l7S&g¢·o³:yeö]!–èÉ–Þ»4öÚñ®uzCRîTøt4"Ü’:“ÛŃoh ë%-d4½ÿ@Û(Ji÷W¡·*M¹ñ:²(2êJ"Åñ{¿à*ÓŽ„?F€À¯&n.æöçÕ,+¶íÕ¨¶Í͘é£×øÐƼ×}EZyîR2 ïȈ:¶ÓþºÍýãTé쌳# _Çÿ‹rOºÇ§Hƒƒ;BÕ laÅ­Ã?aÓŠ^I¯±1‡I^§™ø ì¿ñ(žç ÉªDwþHÞméŽI·RQ!/¥iÀ]7ì·HA¤:2]ÔXgd%'8$¾ažêÎ8æQ°´Å>«ª%­ƒpÙoÃÔ—¤¿g‰“(:sPXû.oCw þü­¥µ¯ö4æŽ~Ñí²Æsß–üª¹‘\ˆ Dš¢Âe¨¶¥?L_Qp,DqÒ·ÕwuN˜]ú‘PŸ7$ »AyWÑäK‡pXª?Þ}ÙÖs½Û¢òÆôU¿PfQÏS|3‚?Ÿ9|„j«G·•ÓãR{€äöBO~&w£LSœ!øká©uƒvŒôk]@jè>K”¯9Ô]¿}‘À-íÇaªCü~ÎpEž@O7˜#™íÁpþ°_Éq5àúÚÚ… î'UB¸î{?´+îhh¨!œW—Í¬ŽøõL£¯eå[Õsš‡š¼=÷SK°°™<ždíÐ*ÄO\KByÎD~o³d0¿%Gó u~oÎvü­ªµzÑ$XψØ6ëíµ­—/éâŒYkË‘î ;¯2Žy0¶`ÒȯûЮ/šÊ] ZÏŸIå([@|½‘K4&Æòº}_=bÙE¤IŒ«ÍEï6¾4Ø SÑ5&Ó7~cg´¸bO$,È+¤—AÊß+9±Ìn/H•Žo6UÿΩD"WŒ]Gß.|ýôÞ§ÛN¿ŒUjº ¹§çÀ®;»Ñ»µü¦-TÕgÃÛ\–üåâ¥2­Xê)8R8çÞgÞ-ØL·×ÿ^M°T|žFÙ¦?ñ™¥J¼I Õ}Ë‹¬°Î/O(…¬›Åe×FE‹~\í}¬àùËŸaoØb-Hi?2› rÓah£Ý’¤VæQ¶þÞJÜØÎ´¸­;‚€ûcúáõ®|¿^¶ÅmM0ôŒÀÖ¨P¾·–²˜ 1ÖzÑ`fB"îj\ðùÒgsÞó†@ߟMBMUjþ ÙD|ˆ•HP¿jPª¯›brRN\Mœ;dlï:©gÔð‹S‚—)ã¹?é¹²FµÈ'ÞȆW_s¾›LÔ ´äò;2|dë´Bk$48ÞDHFÞ l¾Os-_&ÙŽMêŽ÷L¼¶'¶"ùHøZ«”ضºg~ËÊ$àbÏÄ ·;¤T‡ÁeG²U)q–}×%+„ãÄ"¼G;Ä8“؈­i:d&´¿FÑVC:´¯&ÏøyZPs‘©/QÍ“„"# *&í%ƺ˜ý»wI”PðÁ¤ã3%TZóÅŽÞ×=_s~9™ñ 1{›e1÷V÷öpÐß½§Gûâþ{?Á£6tÂËqŸ`3gÏ~GÕ¾™â74]Ú\ô˜ÚÑŒÔÚ@.VáM0ñjÿ|…s;³ÞZžŸWšºäŠ©Èî¦ècºR´³zC!÷Gbáì„k×Éz n"_x ¤.qYsM¤o¥+Œy…òÛÍ&É—{x4ï¨ޱ$øG^”:_Ñ‹Yá®÷ú»÷$ýØjë!]šÎt†6[åuydÇûg_ZŒ(¢Šô\øG+/ÞŽ1,¼p d€-ÿÆuS¢/—ýVŽ<®Û÷?5åÍqKI'ûs‚¼K9Ù šøÚ‚ŠBNã½k?­#6Ad›½ŒƒšêóÏ×w¢fäGWúárÙ\þ}¸¸g=_ªõœÉB{f ³€}b yŒ8Ï;X"çü.%Ü<¬‡DS¤›v­@³ï?‚ÊÌVÃØ1À÷Kï%Hü¾Ïäd›ÝãswXlÇ&kx7ñL&­ÑŒ¿vì¡™º™ Î`’ V¿çŠú­t(£y6PWk'{~Ø]AòM-ÅýfP”ö{Z &§çÁF©RñÜ¡>o?Þ;ûDú"¶nê¶®2o¯~–¢}ÓŸaWRÈñúÒ/ýdKÍ-pñ)ÙÒYeT4¢›­O™…<üïö÷çQvø}àe¦½ó‘áz\æ o½î•oj'p˜%M¶7.‘ÊŒH³ô¾‚M(¹â³Åíh1V¦é&àˆè¥îÑÁ‚Ý4¦„ô`öŸa§¨ EêÈjT Úrµß·¾IhDÂ&+:áÏQå”oÞî¾ÕZ5’KvÔ<-—¼ ^ÆÎ¨®|¶’ðelÀ‹Û9ûçÎ-<µdŒÃñþ·ÐâaÐHIßÕr5vÓ/:=çî ‡å©‹Ðv±ø—þ@cÄ3wZ¬V}ì/*S®˜ ¡~×Ü;qµÚ²sÇøz¹…š.½ô Š·ö«¾&â˜ýlѯtò½ñNx»HîT‹õý̹­Œ3 ¿Š×.áäLʇxŠÁvkŠ…øiSé-Å饽„Û0Ž ½<ày£ `oÒe? ßàBA@b³‰luðcä¥ÔÇ!ZÕ`=[ZãÖc…”ê^az~DŸG½°ÚðÓ \ðí’¸¯ñp«Y^ÎÎ÷‘7ä¡.ë_È}÷Å‚%²ê2Ç—YÔƸϘÙíÍsnä0n¥Å¬k¿ì¸µKiRIo:<é—[ýµ_F>ü-Ñf`»fN¨(ŠÜóãíÄv\ÿ˜ ^£ZDiª”㎋Ž^ÐdgWE oê-ÉW#\åÎ 6ÃZ;¢Ûp‘ýUpü¿¬4êx*—¹ßvyet3ÔoªŒ5\í Ç¥ÆV´UÒœ§/‘L¢+@ àPE$K¦Þ— ™¯âXXb«4ƒ…á̲WŽ@öÏh¯¹p]Þ¯°q©Ôn¾±Z}5è˜Ó(‹ Ó˜µy¦–»[Ï5_÷¶~6RÇ[}%xônIÌ™Š*®ÔÍ0 ?èY±Š˜Š¢ã¨MZïzE¬ÀÁìÀÝ^—"¶zy"›nÜÂà;ñ1,åXDTÈ]RæMJn²&Në½×¾;t7_F|úŠ(ŒùëŸYFuOþÕ|øÂ¡O6‘˜é”ŽÚßÈšvD%Z»yî¹Jí,ü»ãˆöËÉ„•¶… ªÁŠÒþ)’y†^aÓ–}pb¥ÀT‘•¬q¡Ú|óûŸ½àÈÚv¾g®Mp‹¯™Ÿ¢{7ù#"“†Ï'NfLÀp¦Ð‹ÐŸŒ²ËÉu7‰¤ÕúÍ‘¨ /º¢M†ð¾¥b¤ÃG’vIƒ ínLølëU›<÷(U_³ö35Ó~Œ[LuÜ?ô¡WÂÑÞÏ¿«Çïi>¬àF©GEÛÎd§él>+;ålCR.òl—Q4Í¿xèª<Ü)®Àý3ýëRV(y­ 5ÖAºô½qúÇ‹néØP&}Ⱦ¶±¼Áhâð°ïëXàñ”,±~€.øÕ*Õë¨ëZ’LJ H&²u»ÖwΔû4/%ÄÐym;ý­´ð\GîcÇŒ‰ ëˆØ‡lW9I}ÒD–Zî¾Ö ûeHvìá Üê2«¡fPÕsu“¨Rð !ð­ˆävßz%#·± ØPŽ|ólyïÍTžØò ßÓ&à÷N¼4”z‘NXMëñÂü"¼eµÑHä#ÓÌz«¸~p§Ô§ÓDSá­Εùbmõ©ç®£ƒ”éL«­òC16&&‚½Op½sH‘S2‘TüßJ¾ô´/ü–µ1´ít{Ø­`ÁJÞ–§oÇJ»]ÉhÙB¾4ÄWû¬J‘{cÍÃlW³k‡º/ð æ¡V‡½C˜çÜù ¯›ÊøÅ” èàn\äМöûƒ¨è£DÓäƒݵgA-¸KD§yÍ ˆô4‰ïaÊâß1òô-ià ŽWSÛgÛèñÒ°¸ÞmbA<EV÷MŽc«uæ‡Øê§ª2çóo• ·¯k†š%o¿+Åž]ÍŽ~џѽŠ]{æ#ýŽÈ`½}öå`ÁÓíˆï-¦7ßK ôÎÉ«þ½`p˜ÉK,HØJ„ÿß"M‚Ú«o$=‡Á’'bòb|Nä²ÿû‡.0$N *öiL©“X1Â'sð‰ñ@xµïÕhì¼ +7Ts»ú%“7â>baõ²^v§Êjñö´Æ ± ÜÿþÙ_,*¾£4‚,lEvè&ºëáÈ4)˜£AË=Zõ@V©'ím¡pX%e©~¶÷. žªC‡‰*®ÀcyPŸÅSNƪ„Ö§Ø!cÿµŒ.'@–y5|%ut‰’ú’¶Û% [~ k©¹õá}€’lltI¶˜v /®è`ãúªÊ,-ŸOӿΤ‹R{SÄîV^* oËÐ2ÍÉ/Ûš B±jÍ F¶ß´~È¢ÍýUEË„ìHòH;µCæÄéË=£u)GXy8â}fÕj=ø=+O‹ÝŸ[d6ѪuÅ=e̼Zý ƒÐóÐ+2¼Àz \ÜKתY}ÅÃÞôcÖñÿàU×ëdȯN§ô £-ç´ÇÎúåÒKÿ[öC] h¶o§Õ"À×!8›[õ õ3ì“ÅÅ„Iy,0ÝêÄî¤[»ñ«Ð’ …˜›ÌMïÖ¾,Q1XLž‡JÈ¢‘óÍù·sÙWT"äV¤ý> ·—›%Æ7 ¼ {³}ÉëùCêMN”÷YÖ+Òi¯¨çİYy³Þ¢Š[ j ),£B°þî£]IÆÎ:¢”õÞãD`û7Pf`‹ðKuUàv—cù/hßS ÞnÜ .kÃ|®¢·¬iO|1L5‹°É¶ôã›GaýÌ:œï“íºöBMVô‰º„pÛ³2Còùn„Ñ·¹ç?ÑÊg¦® øé_Ïe_–q׃Êõì<‹p´%»Q‰»@Ê7j³×‹ñGKn)ÿéd=¦"ñœ35Ør¦ú«š¡ Í»yï%‡âùÝÑåK›á¦wcÍ\‹ŒK> ö]rY34Õú<·8·áXîtü‹¿î÷ÑÝ-¥ˆíy}+ÑxÄNØÝ+¾!uŸ!&â[àgÕ«ã>áÌê2WQsö•ß3ËþÔ FñG:kZ½ˆûÉ‘žúv;j.îžû$7s°Â÷¡:ÿ¢ÿÅ\pÒÕÛ)†½Ý°×í›q[ÍÍJœ=„6eï#²^lO€G]¬í²Ôv+O>s&Óº}!¦ÑeÛ%¾Ñš­+(x\¯RO$ˆPH¦æY"“l(Ók(pv½Å{³>½œlÄI¼¹/!›NÂ!Ê1ã}VGlˆß¾ä®SÀhNˆ zqEà*ú€ånúªiÃ<œUà}Î1K›Ç%‘¥ÜBK'z.¨²¯;Y*cõÿM†m9<¾ò›O2;Ù.¿Çãû1 ÎÆ=ÓŠc ŒtÇi€”æa Eý·ëîðÚbñóœ—Æz‡ØîðlÇ ôãÕbzbµH"â°µKU!³ßÇ ¦ò·¦ä…oó!•¨ ´éŒG‘FûÔ$ÅØ€LÒ¯örM€!;*\¾ÁÙ?僧EŸÎ-5Š{û»A¿igªzÙ&aeÊ‹‡ Ÿ”LT|7áåjû"¬_´ÜZ_B[øEéfVœÚß µU ¤¾œG_‹ÁÉEìG„ª±¨ŸêXƉ´J|Z¢’­¡GïŠE`+rçÜ]÷¼îÖÄí¨@{ÍzL¹¼ŸVx/&Ϥì¡àÎÃûú°uâ4‹«Gʾ8À»J‘Èiƹyád «\¿5ñ•ÚÓˆÔ@ÄVÀ°ÑîªN;ÍÖ+N‡«èð…uYuâØµ½Ë_-ñ­“Ò§E˼Àz @S¢?ëøë- ”Ï •âß¾®aµ^ä=e?è"äíçŽx¼E+v³vÆ*Û{™‡P~È[ÔŸg6FrÙÓç¼^ÚwtnRïÓPŠRCÚà¶)‘ªðwLƒ=žSy3~Óßr¦wH¹{GÀ™w”ã„ý¤eSøKȳ(zŸ ¹«LÙvJ©mAPg†AÓó»RÆçºó}±fBÏO ”%=,½I7×(Äa°”s\ûË*dH°á"Iï„9ò€Û2YZÌŠaR·wŒ’îŠ9Ú2þû¸BLš½@¾Çôßš›5b¬Ç—k9¨m9Š\ªËàž)z†zYfŸ_R;ɦx!åLù"ØÓD*É3“xþ“©–Èz·¹•$¦ÁÍ? ŸáÎ`±IV”CLX\. )upÙð¢é‰†ç¨ÅŒ“ª®ñµè¹ÿ7Ï­RÇePC%fNNMÏÖ „ª¼{}Xxȇ¥óV!ž¬ÊòcóÈûEi2Fë¥Zt«ŸºÞ Ïœ1Ï>(F1Ûä»NjiñÄÀEdhú@{{D¹Ëég[]ÿÔ5(dÓÅ8’œ’6+R¬ÞÊ/ ÝÕê8Ç5’æ‚xÈ5¦~á;­õ?_@™2Hðz¬´mÕGù²Š1E‘tùt‰‚eu®@h¤hðúà0Èá”}wžüx,Vá!ßN§1ÂUùi%É#RÁ 7y¼bÛÔÝO¥Ï¨s0_™ ã÷ƪ~ÚMSÕÆuy¦»ÒÜ6¬v5z(cÜE¹µdúÈCŒ7SÓ7°åZÎø¿ <î£)EmEÁ³mòKgÄ"çæ®eÉ÷~âŽ3»|.*U˜£M² ¨na’ö?STvŒ<¿Åî|Déåu¯áNºz^z³ùö4•z¡é¸xŒ}ÜEêø`…õš\~ %hÎzy;:Uþ`§Ë~¨ô×$퇊W´â1å¿iXI[Ø*.u¯t:<³Áf„:¹:ûEs8¸œ<*79áT!êÎÍ€±È77Q÷ºO¢Æ¹>¿wéÙ€«åæè?ú¼á2×ôl§dN›.ŽYxe§\^t戭ã¶ÀÍ“ë}/º´åÏ[MœcäV+ò ¼Ì¯'ZÌóäw ô?Žë¤¬h¼4÷n"fŠS¸ÕÙ%|7ó†{be7hð œQþtÉ~?ß0]ŒrõR>ö™VÚVpÜÞ,ú–ðùf@/[奒ú`ª„)‘bÊp‚º¾ 0ÑÄþØ’$9·`)aUGfÕ‚v).ÒÝM4{ØëËè˜$ÂåñÏq•®3%cÜ}ïÎy32Ì(íz'¶\kÚ@-²ZtºTÄ@%òÆuW}°•!pÉáE;>ªâÂa ‡¬¡Û»ŽÕ¥Ž¼÷Z!­‹û*R†È¼ð©‡ÁºZ˜–%¼"tÝoOñ‚ë*›N+‰ÉÞÝEãÊ«•ò%–W×"¾A¡÷Çó Ë„¹kNÓÖÙg2]ÿDzi÷ˆËÄó|W —ï>°ýE@°wzÏ0…¶V}* M sØø*R{ræÆ?VnRrÞ«ÍÕCL?!ÿ¶ÕϺÚFëK¡Œ6\é·K«/}ŠâÍQ&.÷Q°°õ@Ìltâ5ô˜ÃXÑiºÊíûÒvY­©ç‘¹o/õ Ó³Ó"dôS"2ñºÆn‹ =šfFI›?°ËìŸèwC¹«|+ç3 û½¦;_~ˆ™ÍÞ”ACÌÛïû;WÊÞfüÇ:Œ÷ï+®¦‡wÝõÓÖãìQëtÌ\j+–3²ß)Å›ÿ/ØÿŸàÿ +°Ìêh³Çö†á®PØ_ß,bÿ/å[Ï“endstream endobj 6 0 obj << /Type /Font /Subtype /Type1 /Encoding 300 0 R /FirstChar 2 /LastChar 122 /Widths 311 0 R /BaseFont /GJFYLJ+NimbusSanL-Regu /FontDescriptor 4 0 R >> endobj 4 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 /FontName /GJFYLJ+NimbusSanL-Regu /ItalicAngle 0 /StemV 85 /XHeight 523 /FontBBox [-174 -285 1001 953] /Flags 4 /CharSet (/fi/quoteright/parenleft/parenright/comma/period/zero/one/two/three/four/five/six/seven/eight/nine/colon/at/A/B/C/D/E/F/G/H/I/J/L/M/N/O/P/R/S/T/U/W/X/Z/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 5 0 R >> endobj 311 0 obj [500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 222 333 333 0 0 278 0 278 0 556 556 556 556 556 556 556 556 556 556 278 0 0 0 0 0 1015 667 667 722 722 667 611 778 722 278 500 0 556 833 722 778 667 0 722 667 611 722 0 944 667 0 611 0 0 0 0 0 0 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556 556 556 333 500 278 556 500 722 500 500 500 ] endobj 13 0 obj << /Type /Pages /Count 6 /Parent 312 0 R /Kids [2 0 R 15 0 R 24 0 R 27 0 R 61 0 R 64 0 R] >> endobj 91 0 obj << /Type /Pages /Count 6 /Parent 312 0 R /Kids [81 0 R 93 0 R 96 0 R 100 0 R 105 0 R 109 0 R] >> endobj 118 0 obj << /Type /Pages /Count 6 /Parent 312 0 R /Kids [116 0 R 120 0 R 126 0 R 131 0 R 135 0 R 139 0 R] >> endobj 145 0 obj << /Type /Pages /Count 6 /Parent 312 0 R /Kids [142 0 R 147 0 R 150 0 R 154 0 R 157 0 R 161 0 R] >> endobj 168 0 obj << /Type /Pages /Count 4 /Parent 312 0 R /Kids [165 0 R 170 0 R 173 0 R 297 0 R] >> endobj 312 0 obj << /Type /Pages /Count 28 /Kids [13 0 R 91 0 R 118 0 R 145 0 R 168 0 R] >> endobj 313 0 obj << /Type /Outlines /First 177 0 R /Last 288 0 R /Count 7 >> endobj 294 0 obj << /Title 295 0 R /A 293 0 R /Parent 291 0 R >> endobj 291 0 obj << /Title 292 0 R /A 290 0 R /Parent 288 0 R /First 294 0 R /Last 294 0 R /Count -1 >> endobj 288 0 obj << /Title 289 0 R /A 287 0 R /Parent 313 0 R /Prev 270 0 R /First 291 0 R /Last 291 0 R /Count -1 >> endobj 285 0 obj << /Title 286 0 R /A 284 0 R /Parent 273 0 R /Prev 282 0 R >> endobj 282 0 obj << /Title 283 0 R /A 281 0 R /Parent 273 0 R /Prev 279 0 R /Next 285 0 R >> endobj 279 0 obj << /Title 280 0 R /A 278 0 R /Parent 273 0 R /Prev 276 0 R /Next 282 0 R >> endobj 276 0 obj << /Title 277 0 R /A 275 0 R /Parent 273 0 R /Next 279 0 R >> endobj 273 0 obj << /Title 274 0 R /A 272 0 R /Parent 270 0 R /First 276 0 R /Last 285 0 R /Count -4 >> endobj 270 0 obj << /Title 271 0 R /A 269 0 R /Parent 313 0 R /Prev 267 0 R /Next 288 0 R /First 273 0 R /Last 273 0 R /Count -1 >> endobj 267 0 obj << /Title 268 0 R /A 266 0 R /Parent 313 0 R /Prev 264 0 R /Next 270 0 R >> endobj 264 0 obj << /Title 265 0 R /A 263 0 R /Parent 313 0 R /Prev 252 0 R /Next 267 0 R >> endobj 261 0 obj << /Title 262 0 R /A 260 0 R /Parent 252 0 R /Prev 258 0 R >> endobj 258 0 obj << /Title 259 0 R /A 257 0 R /Parent 252 0 R /Prev 255 0 R /Next 261 0 R >> endobj 255 0 obj << /Title 256 0 R /A 254 0 R /Parent 252 0 R /Next 258 0 R >> endobj 252 0 obj << /Title 253 0 R /A 251 0 R /Parent 313 0 R /Prev 201 0 R /Next 264 0 R /First 255 0 R /Last 261 0 R /Count -3 >> endobj 249 0 obj << /Title 250 0 R /A 248 0 R /Parent 246 0 R >> endobj 246 0 obj << /Title 247 0 R /A 245 0 R /Parent 228 0 R /Prev 231 0 R /First 249 0 R /Last 249 0 R /Count -1 >> endobj 243 0 obj << /Title 244 0 R /A 242 0 R /Parent 231 0 R /Prev 240 0 R >> endobj 240 0 obj << /Title 241 0 R /A 239 0 R /Parent 231 0 R /Prev 237 0 R /Next 243 0 R >> endobj 237 0 obj << /Title 238 0 R /A 236 0 R /Parent 231 0 R /Prev 234 0 R /Next 240 0 R >> endobj 234 0 obj << /Title 235 0 R /A 233 0 R /Parent 231 0 R /Next 237 0 R >> endobj 231 0 obj << /Title 232 0 R /A 230 0 R /Parent 228 0 R /Next 246 0 R /First 234 0 R /Last 243 0 R /Count -4 >> endobj 228 0 obj << /Title 229 0 R /A 227 0 R /Parent 201 0 R /Prev 204 0 R /First 231 0 R /Last 246 0 R /Count -2 >> endobj 225 0 obj << /Title 226 0 R /A 224 0 R /Parent 222 0 R >> endobj 222 0 obj << /Title 223 0 R /A 221 0 R /Parent 204 0 R /Prev 213 0 R /First 225 0 R /Last 225 0 R /Count -1 >> endobj 219 0 obj << /Title 220 0 R /A 218 0 R /Parent 213 0 R /Prev 216 0 R >> endobj 216 0 obj << /Title 217 0 R /A 215 0 R /Parent 213 0 R /Next 219 0 R >> endobj 213 0 obj << /Title 214 0 R /A 212 0 R /Parent 204 0 R /Prev 207 0 R /Next 222 0 R /First 216 0 R /Last 219 0 R /Count -2 >> endobj 210 0 obj << /Title 211 0 R /A 209 0 R /Parent 207 0 R >> endobj 207 0 obj << /Title 208 0 R /A 206 0 R /Parent 204 0 R /Next 213 0 R /First 210 0 R /Last 210 0 R /Count -1 >> endobj 204 0 obj << /Title 205 0 R /A 203 0 R /Parent 201 0 R /Next 228 0 R /First 207 0 R /Last 222 0 R /Count -3 >> endobj 201 0 obj << /Title 202 0 R /A 200 0 R /Parent 313 0 R /Prev 177 0 R /Next 252 0 R /First 204 0 R /Last 228 0 R /Count -2 >> endobj 198 0 obj << /Title 199 0 R /A 197 0 R /Parent 177 0 R /Prev 195 0 R >> endobj 195 0 obj << /Title 196 0 R /A 194 0 R /Parent 177 0 R /Prev 183 0 R /Next 198 0 R >> endobj 192 0 obj << /Title 193 0 R /A 191 0 R /Parent 189 0 R >> endobj 189 0 obj << /Title 190 0 R /A 188 0 R /Parent 183 0 R /Prev 186 0 R /First 192 0 R /Last 192 0 R /Count -1 >> endobj 186 0 obj << /Title 187 0 R /A 185 0 R /Parent 183 0 R /Next 189 0 R >> endobj 183 0 obj << /Title 184 0 R /A 182 0 R /Parent 177 0 R /Prev 180 0 R /Next 195 0 R /First 186 0 R /Last 189 0 R /Count -2 >> endobj 180 0 obj << /Title 181 0 R /A 179 0 R /Parent 177 0 R /Next 183 0 R >> endobj 177 0 obj << /Title 178 0 R /A 176 0 R /Parent 313 0 R /Next 201 0 R /First 180 0 R /Last 198 0 R /Count -4 >> endobj 314 0 obj << /Names [(label-section:NC) 90 0 R (label-subsection: Modules) 102 0 R (label-subsection:MM) 124 0 R (label-subsubsection:complexType) 163 0 R (page001) 50 0 R (page002) 51 0 R (page003) 52 0 R (page004) 98 0 R (page005) 53 0 R (page006) 107 0 R (page007) 111 0 R (page008) 54 0 R (page009) 122 0 R (page010) 128 0 R (page011) 133 0 R (page012) 137 0 R (page013) 55 0 R (page014) 144 0 R (page015) 56 0 R (page016) 152 0 R (page017) 57 0 R (page018) 159 0 R (page019) 58 0 R (page020) 167 0 R (page021) 59 0 R (page022) 175 0 R (page023) 299 0 R] /Limits [(label-section:NC) (page023)] >> endobj 315 0 obj << /Kids [314 0 R] >> endobj 316 0 obj << /Dests 315 0 R >> endobj 317 0 obj << /Type /Catalog /Pages 312 0 R /Outlines 313 0 R /Names 316 0 R /PageMode /UseOutlines >> endobj 318 0 obj << /Producer (pdfeTeX-1.21a) /Author (Joshua Boverhof,, Charles Moad) /Title (ZSI: The Zolera Soap Infrastructure , User's Guide) /Creator (TeX) /CreationDate (D:20071101225915Z) /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref 0 319 0000000000 65535 f 0000000573 00000 n 0000000468 00000 n 0000000009 00000 n 0000167134 00000 n 0000156816 00000 n 0000166968 00000 n 0000156400 00000 n 0000152233 00000 n 0000156229 00000 n 0000151331 00000 n 0000133129 00000 n 0000151160 00000 n 0000167934 00000 n 0000004043 00000 n 0000003935 00000 n 0000000664 00000 n 0000132298 00000 n 0000116843 00000 n 0000132127 00000 n 0000116512 00000 n 0000115049 00000 n 0000116353 00000 n 0000004440 00000 n 0000004332 00000 n 0000004137 00000 n 0000008620 00000 n 0000005909 00000 n 0000004509 00000 n 0000006155 00000 n 0000006290 00000 n 0000006428 00000 n 0000006567 00000 n 0000006706 00000 n 0000006844 00000 n 0000114005 00000 n 0000095839 00000 n 0000113830 00000 n 0000006977 00000 n 0000007115 00000 n 0000007254 00000 n 0000007389 00000 n 0000007528 00000 n 0000007667 00000 n 0000007806 00000 n 0000007941 00000 n 0000008076 00000 n 0000008210 00000 n 0000008348 00000 n 0000008482 00000 n 0000012642 00000 n 0000016289 00000 n 0000017119 00000 n 0000019706 00000 n 0000025774 00000 n 0000033638 00000 n 0000034663 00000 n 0000035681 00000 n 0000038332 00000 n 0000040960 00000 n 0000009029 00000 n 0000008921 00000 n 0000008725 00000 n 0000012698 00000 n 0000011208 00000 n 0000009098 00000 n 0000095516 00000 n 0000089218 00000 n 0000095348 00000 n 0000088344 00000 n 0000070347 00000 n 0000088175 00000 n 0000011384 00000 n 0000011550 00000 n 0000011711 00000 n 0000011870 00000 n 0000012031 00000 n 0000012196 00000 n 0000012361 00000 n 0000012502 00000 n 0000016401 00000 n 0000015488 00000 n 0000012815 00000 n 0000015636 00000 n 0000015827 00000 n 0000015963 00000 n 0000016098 00000 n 0000069756 00000 n 0000058199 00000 n 0000069583 00000 n 0000016345 00000 n 0000168043 00000 n 0000017175 00000 n 0000017011 00000 n 0000016530 00000 n 0000017626 00000 n 0000017462 00000 n 0000017268 00000 n 0000017570 00000 n 0000019820 00000 n 0000019409 00000 n 0000017695 00000 n 0000019763 00000 n 0000019539 00000 n 0000021528 00000 n 0000021359 00000 n 0000019949 00000 n 0000021470 00000 n 0000023488 00000 n 0000023319 00000 n 0000021634 00000 n 0000023430 00000 n 0000057759 00000 n 0000050284 00000 n 0000057581 00000 n 0000025831 00000 n 0000025662 00000 n 0000023607 00000 n 0000168156 00000 n 0000029116 00000 n 0000028697 00000 n 0000025937 00000 n 0000029000 00000 n 0000028829 00000 n 0000029058 00000 n 0000030942 00000 n 0000030545 00000 n 0000029234 00000 n 0000030884 00000 n 0000030677 00000 n 0000032234 00000 n 0000032064 00000 n 0000031060 00000 n 0000032176 00000 n 0000032907 00000 n 0000032737 00000 n 0000032328 00000 n 0000032849 00000 n 0000033695 00000 n 0000033526 00000 n 0000033001 00000 n 0000034154 00000 n 0000033984 00000 n 0000033789 00000 n 0000034096 00000 n 0000168273 00000 n 0000034720 00000 n 0000034551 00000 n 0000034224 00000 n 0000035166 00000 n 0000034996 00000 n 0000034802 00000 n 0000035108 00000 n 0000035738 00000 n 0000035569 00000 n 0000035236 00000 n 0000036185 00000 n 0000036015 00000 n 0000035820 00000 n 0000036127 00000 n 0000038453 00000 n 0000038220 00000 n 0000036255 00000 n 0000038389 00000 n 0000038936 00000 n 0000038766 00000 n 0000038571 00000 n 0000038878 00000 n 0000168390 00000 n 0000041017 00000 n 0000040848 00000 n 0000039006 00000 n 0000043267 00000 n 0000043097 00000 n 0000041159 00000 n 0000043209 00000 n 0000043361 00000 n 0000172410 00000 n 0000043406 00000 n 0000043440 00000 n 0000172331 00000 n 0000043485 00000 n 0000043533 00000 n 0000172199 00000 n 0000043578 00000 n 0000043610 00000 n 0000172120 00000 n 0000043655 00000 n 0000043694 00000 n 0000172002 00000 n 0000043739 00000 n 0000043777 00000 n 0000171937 00000 n 0000043822 00000 n 0000043849 00000 n 0000171844 00000 n 0000043894 00000 n 0000043929 00000 n 0000171765 00000 n 0000043974 00000 n 0000044008 00000 n 0000171633 00000 n 0000044053 00000 n 0000044089 00000 n 0000171515 00000 n 0000044134 00000 n 0000044165 00000 n 0000171397 00000 n 0000044210 00000 n 0000044254 00000 n 0000171332 00000 n 0000044299 00000 n 0000044326 00000 n 0000171200 00000 n 0000044371 00000 n 0000044409 00000 n 0000171121 00000 n 0000044454 00000 n 0000044481 00000 n 0000171042 00000 n 0000044526 00000 n 0000044562 00000 n 0000170924 00000 n 0000044607 00000 n 0000044647 00000 n 0000170859 00000 n 0000044692 00000 n 0000044732 00000 n 0000170741 00000 n 0000044777 00000 n 0000044820 00000 n 0000170623 00000 n 0000044865 00000 n 0000044930 00000 n 0000170544 00000 n 0000044975 00000 n 0000045002 00000 n 0000170451 00000 n 0000045047 00000 n 0000045072 00000 n 0000170358 00000 n 0000045117 00000 n 0000045318 00000 n 0000170279 00000 n 0000045363 00000 n 0000045560 00000 n 0000170161 00000 n 0000045605 00000 n 0000045806 00000 n 0000170096 00000 n 0000045851 00000 n 0000045878 00000 n 0000169964 00000 n 0000045923 00000 n 0000045953 00000 n 0000169885 00000 n 0000045998 00000 n 0000046046 00000 n 0000169792 00000 n 0000046091 00000 n 0000046140 00000 n 0000169713 00000 n 0000046185 00000 n 0000046225 00000 n 0000169620 00000 n 0000046270 00000 n 0000046304 00000 n 0000169527 00000 n 0000046349 00000 n 0000046388 00000 n 0000169395 00000 n 0000046433 00000 n 0000046468 00000 n 0000169291 00000 n 0000046513 00000 n 0000046555 00000 n 0000169212 00000 n 0000046600 00000 n 0000046639 00000 n 0000169119 00000 n 0000046684 00000 n 0000046739 00000 n 0000169026 00000 n 0000046784 00000 n 0000046844 00000 n 0000168947 00000 n 0000046889 00000 n 0000046941 00000 n 0000168829 00000 n 0000046986 00000 n 0000047030 00000 n 0000168725 00000 n 0000047075 00000 n 0000047139 00000 n 0000168660 00000 n 0000047184 00000 n 0000048302 00000 n 0000048132 00000 n 0000047239 00000 n 0000048244 00000 n 0000048396 00000 n 0000058007 00000 n 0000070089 00000 n 0000088860 00000 n 0000095747 00000 n 0000114501 00000 n 0000116750 00000 n 0000116725 00000 n 0000132689 00000 n 0000151777 00000 n 0000156638 00000 n 0000167539 00000 n 0000168491 00000 n 0000168583 00000 n 0000172528 00000 n 0000173136 00000 n 0000173175 00000 n 0000173213 00000 n 0000173322 00000 n trailer << /Size 319 /Root 317 0 R /Info 318 0 R /ID [<1B542E5F0C77E439A0F308B315B47F2F> <1B542E5F0C77E439A0F308B315B47F2F>] >> startxref 173625 %%EOF ZSI-2.1-a1/doc/blank.png0000644000175100017510000000200710437331051013054 0ustar zsizsi‰PNG  IHDR D¤ŠÆPLTE 3f™Ìÿ333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌÿ3ÿfÿ™ÿÌÿÿÿ333f3™3Ì3ÿ333333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌffÿff™f3™ff™f™™fÌ™fÿ™fÌf3ÌffÌf™ÌfÌÌfÿÌfÿf3ÿffÿf™ÿfÌÿfÿÿf™3™f™™™Ì™ÿ™3™33™f3™™3™Ì3™ÿ3™f™3f™ff™™f™Ìf™ÿf™™™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌ™™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿ™Ì3ÌfÌ™ÌÌÌÿÌ3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌffÌ™fÌÌfÌÿfÌ™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÌÿ3ÿfÿ™ÿÌÿÿÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÿ™fÿÌfÿÿfÿ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿÿÿ3ÿÿfÿÿ™ÿÿÌÿÿÿÿÿâââãããäääåååæææçççèèèéééêêêëëëìììíííîîîïïïðððñññòòòóóóôôôõõõööö÷÷÷øøøùùùúúúûûûüüüýýýþþþÿÿÿCA×bKGDˆHIDATxÚc¸I0Œ*U0ª`¤*­d.¡ç®CtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com‘º!¸*tEXtSignature0ac660e469fb3b89a555665df224a4beó –ûtEXtPage32x32+0+0çS2ðIEND®B`‚ZSI-2.1-a1/ZSI.egg-info/0000755000175100017510000000000010712455110012651 5ustar zsizsiZSI-2.1-a1/ZSI.egg-info/top_level.txt0000644000175100017510000000000410712455110015375 0ustar zsizsiZSI ZSI-2.1-a1/ZSI.egg-info/PKG-INFO0000644000175100017510000000045210712455110013747 0ustar zsizsiMetadata-Version: 1.0 Name: ZSI Version: 2.1-a1 Summary: Zolera SOAP Infrastructure Home-page: http://pywebsvcs.sf.net/ Author: Rich Salz, et al Author-email: pywebsvcs-talk@lists.sf.net License: Python Description: For additional information, please see http://pywebsvcs.sf.net/ Platform: UNKNOWN ZSI-2.1-a1/ZSI.egg-info/entry_points.txt0000644000175100017510000000007310712455110016147 0ustar zsizsi[console_scripts] wsdl2py = ZSI.generate.commands:wsdl2py ZSI-2.1-a1/ZSI.egg-info/SOURCES.txt0000644000175100017510000002137710712455110014547 0ustar zsizsiCHANGES Copyright README setup.cfg setup.py ZSI/.cvsignore ZSI/LBNLCopyright ZSI/ServiceContainer.py ZSI/ServiceProxy.py ZSI/TC.py ZSI/TCapache.py ZSI/TCcompound.py ZSI/TCnumbers.py ZSI/TCtimes.py ZSI/__init__.py ZSI/address.py ZSI/auth.py ZSI/client.py ZSI/digest_auth.py ZSI/dispatch.py ZSI/fault.py ZSI/parse.py ZSI/resolvers.py ZSI/schema.py ZSI/typeinterpreter.py ZSI/version.py ZSI/writer.py ZSI.egg-info/PKG-INFO ZSI.egg-info/SOURCES.txt ZSI.egg-info/dependency_links.txt ZSI.egg-info/entry_points.txt ZSI.egg-info/top_level.txt ZSI/generate/__init__.py ZSI/generate/commands.py ZSI/generate/containers.py ZSI/generate/pyclass.py ZSI/generate/utility.py ZSI/generate/wsdl2dispatch.py ZSI/generate/wsdl2python.py ZSI/twisted/WSresource.py ZSI/twisted/WSsecurity.py ZSI/twisted/__init__.py ZSI/twisted/client.py ZSI/twisted/interfaces.py ZSI/twisted/reverse.py ZSI/twisted/wsgi.py ZSI/wstools/.cvsignore ZSI/wstools/Namespaces.py ZSI/wstools/TimeoutSocket.py ZSI/wstools/UserTuple.py ZSI/wstools/Utility.py ZSI/wstools/WSDLTools.py ZSI/wstools/XMLSchema.py ZSI/wstools/XMLname.py ZSI/wstools/ZPL ZSI/wstools/__init__.py ZSI/wstools/c14n.py ZSI/wstools/license.txt ZSI/wstools/logging.py ZSI/wstools/test/.cvsignore ZSI/wstools/test/README ZSI/wstools/test/__init__.py ZSI/wstools/test/config.txt ZSI/wstools/test/schema.tar.gz ZSI/wstools/test/test_t1.py ZSI/wstools/test/test_wsdl.py ZSI/wstools/test/test_wstools.py ZSI/wstools/test/test_wstools_net.py ZSI/wstools/test/xmethods.tar.gz doc/.cvsignore doc/blank.png doc/contents.png doc/guide.css doc/guide.html doc/guide.pdf doc/guide.ps doc/index.png doc/modules.png doc/next.png doc/previous.png doc/pyfav.png doc/up.png doc/zsi.css doc/zsi.html doc/zsi.pdf doc/zsi.ps doc/zsi.xsd doc/examples/client/receive_response/complex/binding.wsdl doc/examples/client/receive_response/complex/interface.wsdl doc/examples/client/receive_response/complex/types.xsd doc/examples/client/receive_response/complex/manual/.cvsignore doc/examples/client/receive_response/complex/manual/ComplexTypes.py doc/examples/client/receive_response/complex/manual/client.py doc/examples/client/receive_response/complex/server/.cvsignore doc/examples/client/receive_response/complex/server/server.py doc/examples/client/receive_response/complex/wsdl2py/.cvsignore doc/examples/client/receive_response/complex/wsdl2py/client.py doc/examples/client/receive_response/simple/binding.wsdl doc/examples/client/receive_response/simple/interface.wsdl doc/examples/client/receive_response/simple/ServiceProxy/client.py doc/examples/client/receive_response/simple/server/.cvsignore doc/examples/client/receive_response/simple/server/server.py doc/examples/client/receive_response/simple/wsdl2py/.cvsignore doc/examples/client/receive_response/simple/wsdl2py/README doc/examples/client/receive_response/simple/wsdl2py/client.py doc/examples/client/send_request/complex/binding.wsdl doc/examples/client/send_request/complex/interface.wsdl doc/examples/client/send_request/complex/types.xsd doc/examples/client/send_request/complex/manual/.cvsignore doc/examples/client/send_request/complex/manual/ComplexTypes.py doc/examples/client/send_request/complex/manual/client.py doc/examples/client/send_request/complex/server/.cvsignore doc/examples/client/send_request/complex/server/ComplexTypes.py doc/examples/client/send_request/complex/server/server.py doc/examples/client/send_request/complex/wsdl2py/.cvsignore doc/examples/client/send_request/complex/wsdl2py/client.py doc/examples/client/send_request/simple/README doc/examples/client/send_request/simple/binding.wsdl doc/examples/client/send_request/simple/interface.wsdl doc/examples/client/send_request/simple/Binding/client.py doc/examples/client/send_request/simple/ServiceProxy/client.py doc/examples/client/send_request/simple/server/.cvsignore doc/examples/client/send_request/simple/server/server.py doc/examples/client/send_request/simple/wsdl2py/.cvsignore doc/examples/client/send_request/simple/wsdl2py/README doc/examples/client/send_request/simple/wsdl2py/client.py doc/examples/server/receive_request/complex/binding.wsdl doc/examples/server/receive_request/complex/interface.wsdl doc/examples/server/receive_request/complex/types.xsd doc/examples/server/receive_request/complex/client/.cvsignore doc/examples/server/receive_request/complex/client/ComplexTypes.py doc/examples/server/receive_request/complex/client/client.py doc/examples/server/receive_request/complex/manual/.cvsignore doc/examples/server/receive_request/complex/manual/ComplexTypes.py doc/examples/server/receive_request/complex/manual/server.py doc/examples/server/receive_request/complex/wsdl2py/.cvsignore doc/examples/server/receive_request/complex/wsdl2py/server.py doc/examples/server/receive_request/simple/binding.wsdl doc/examples/server/receive_request/simple/interface.wsdl doc/examples/server/receive_request/simple/CGI/README doc/examples/server/receive_request/simple/CGI/cgi.py doc/examples/server/receive_request/simple/client/client.py doc/examples/server/receive_request/simple/mod_python/.cvsignore doc/examples/server/receive_request/simple/mod_python/MyHandler.py doc/examples/server/receive_request/simple/mod_python/README doc/examples/server/receive_request/simple/mod_python/mod_python.py doc/examples/server/receive_request/simple/standalone/.cvsignore doc/examples/server/receive_request/simple/standalone/README doc/examples/server/receive_request/simple/standalone/standalone.py doc/examples/server/send_response/complex/binding.wsdl doc/examples/server/send_response/complex/interface.wsdl doc/examples/server/send_response/complex/types.xsd doc/examples/server/send_response/complex/client/.cvsignore doc/examples/server/send_response/complex/client/client.py doc/examples/server/send_response/complex/manual/.cvsignore doc/examples/server/send_response/complex/manual/ComplexTypes.py doc/examples/server/send_response/complex/manual/server.py doc/examples/server/send_response/complex/wsdl2py/.cvsignore doc/examples/server/send_response/complex/wsdl2py/server.py doc/examples/server/send_response/simple/binding.wsdl doc/examples/server/send_response/simple/interface.wsdl doc/examples/server/send_response/simple/no_typecode/client.py doc/examples/server/send_response/simple/no_typecode/server.py doc/examples/server/send_response/simple/wsdl2py/.cvsignore doc/examples/server/send_response/simple/wsdl2py/README doc/examples/server/send_response/simple/wsdl2py/client.py doc/examples/server/send_response/simple/wsdl2py/server.py samples/README samples/WSGI/README samples/WSGI/SimpleEcho.wsdl samples/WSGI/echo_client.py samples/WSGI/echo_server.py samples/WSGI/echo_setup.py scripts/wsdl2dispatch scripts/wsdl2py test/.cvsignore test/README test/cgicli.py test/test_QName.py test/test_TCtimes.py test/test_URI.py test/test_callhome.py test/test_list.py test/test_rfc2617.py test/test_t1.py test/test_t2.py test/test_t3.py test/test_t4.py test/test_t5.py test/test_t6.py test/test_t7.py test/test_t8.py test/test_t9.py test/test_union.py test/test_zsi.py test/test_zsi_net.py test/tests_bad.py test/tests_good.py test/wsdl2py/.cvsignore test/wsdl2py/README test/wsdl2py/ServiceTest.py test/wsdl2py/config.txt test/wsdl2py/runTests.py test/wsdl2py/test_AWSECommerceService.py test/wsdl2py/test_AmazonS3.py test/wsdl2py/test_Attributes.py test/wsdl2py/test_BasicComm.py test/wsdl2py/test_Choice.py test/wsdl2py/test_Clearspace.py test/wsdl2py/test_DateService.py test/wsdl2py/test_DerivedTypes.py test/wsdl2py/test_Echo.py test/wsdl2py/test_EchoWSAddr200403.py test/wsdl2py/test_FinancialService.py test/wsdl2py/test_GoogleAdWords.py test/wsdl2py/test_InfoBil.py test/wsdl2py/test_Manufacturer.py test/wsdl2py/test_MapPoint.py test/wsdl2py/test_NVOAdmin.py test/wsdl2py/test_OpcDaGateway.py test/wsdl2py/test_Racing.py test/wsdl2py/test_Sabre.py test/wsdl2py/test_SquareService.py test/wsdl2py/test_SubstitutionGroup.py test/wsdl2py/test_TerraService.py test/wsdl2py/test_ThreatService.py test/wsdl2py/test_VIM.py test/wsdl2py/test_WSDLImport.py test/wsdl2py/test_WhiteMesa.py test/wsdl2py/test_XMethodsQuery.py test/wsdl2py/test_ZipCodeResolver.py test/wsdl2py/servers/BasicServer.py test/wsdl2py/servers/DateService.py test/wsdl2py/servers/EchoServer.py test/wsdl2py/servers/EchoWSAddr200403Server.py test/wsdl2py/servers/FinancialService.py test/wsdl2py/servers/SquareService.py test/wsdl2py/servers/WhiteMesa.py test/wsdl2py/wsdl/BasicComm.wsdl test/wsdl2py/wsdl/DateService.wsdl test/wsdl2py/wsdl/EchoWSAddr200403.wsdl test/wsdl2py/wsdl/FinancialService.wsdl test/wsdl2py/wsdl/ManufacturerImpl.wsdl test/wsdl2py/wsdl/Racing.wsdl test/wsdl2py/wsdl/SquareService.wsdl test/wsdl2py/wsdl/nvo-admin.wsdl test/wsdl2py/wsdl/test_Attributes.xsd test/wsdl2py/wsdl/test_Choice.xsd test/wsdl2py/wsdl/test_DerivedTypes.xsd test/wsdl2py/wsdl/test_SubstitutionGroup.xsd test/wsdl2py/wsdl/test_WSDLImport.wsdl test/wsdl2py/wsdl/test_WSDLImport2.wsdl test/wsdl2py/wsdl/vim.wsdl ZSI-2.1-a1/ZSI.egg-info/dependency_links.txt0000644000175100017510000000013510712455110016727 0ustar zsizsihttp://sourceforge.net/project/showfiles.php?group_id=6473&package_id=6541&release_id=286213 ZSI-2.1-a1/test/0000755000175100017510000000000010712455110011471 5ustar zsizsiZSI-2.1-a1/test/test_t7.py0000644000175100017510000000324110356606232013443 0ustar zsizsi#!/usr/bin/env python import unittest, sys from ZSI import * class t7TestCase(unittest.TestCase): "Test case wrapper for old ZSI t7 test case" def checkt7(self): ps = ParsedSoap(text) tcdict = TC.Apache.Map('c-gensym1') tclist = TC.Apache.Map('c-gensym1', aslist=1) d = tcdict.parse(ps.body_root, ps) self.assertEqual(d, { u'a':123, '\x00\x01':456 }) print 'as dictionary\n', d l = tclist.parse(ps.body_root, ps) self.assertEqual(l, [('\x00\x01', 456), (u'a', 123)]) print '\n', '=' * 30 print 'as list\n', l print '\n', '=' * 30 sw = SoapWriter() sw.serialize(d, tcdict) print >>sys.stdout, sw print '\n', '=' * 30 sw = SoapWriter() sw.serialize(l, tclist) print >>sys.stdout, sw def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t7TestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") text = ''' AAE= 456 a 123 ''' if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_t4.py0000644000175100017510000000362110700756665013453 0ustar zsizsi#!/usr/bin/env python import unittest, sys from ZSI import * from ZSI import resolvers OUT = sys.stdout IN=''' ''' class t4TestCase(unittest.TestCase): "Test case wrapper for old ZSI t4 test case" def checkt4(self): try: r = resolvers.NetworkResolver(['http:']) ps = ParsedSoap(IN, resolver=r.Resolve) except ParseException, e: print >>OUT, FaultFromZSIException(e).AsSOAP() self.fail() except Exception, e: # Faulted while processing; assume it's in the header. print >>OUT, FaultFromException(e, 1, sys.exc_info()[2]).AsSOAP() self.fail() print 'resolving' typecode = TC.Struct(None, [ TC.XML('xmltest'), TC.String('stringtest', resolver=r.Opaque), ]) try: dict = ps.Parse(typecode) except EvaluateException, e: print >>OUT, FaultFromZSIException(e).AsSOAP() self.fail() except Exception, e: # Faulted while processing; now it's the body print >>OUT, FaultFromException(e, 0, sys.exc_info()[2]).AsSOAP() self.fail() ##PrettyPrint(dict['xmltest']) print '**', dict['stringtest'], '**' def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t4TestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_list.py0000644000175100017510000000410210542054762014063 0ustar zsizsi#!/usr/bin/env python import unittest, time, datetime import ZSI from ZSI.writer import SoapWriter from ZSI import _get_element_nsuri_name from ZSI.schema import GED, TypeDefinition, ElementDeclaration from ZSI.parse import ParsedSoap from cStringIO import StringIO class TestList1_Def(ZSI.TC.List, TypeDefinition): itemType = (u'http://www.w3.org/2001/XMLSchema', u'dateTime') schema = "urn:test" type = (schema, "tUsage") def __init__(self, pname, **kw): ZSI.TC.List.__init__(self, pname, **kw) class TestList2_Def(ZSI.TC.List, TypeDefinition): itemType = ZSI.TC.gDateTime() schema = "urn:test" type = (schema, "tUsage") def __init__(self, pname, **kw): ZSI.TC.List.__init__(self, pname, **kw) class ListTestCase(unittest.TestCase): "test List TypeCode" def setUp(self): pass def tearDown(self): pass def check_list_defs(self): gl = globals() for klass in map(lambda h: gl[h], filter(lambda g: (g.startswith('TestList') and issubclass(gl[g],ZSI.TC.List)), gl)): typecode = klass('whatever', nillable=True) data = None for i in range(10): sw = SoapWriter() sw.serialize(data, typecode) s = str(sw) print s ps = ParsedSoap(s); pyobj = ps.Parse(typecode) assert pyobj == data, 'Data corruption expected "%s", got "%s"' %(str(data),str(pyobj)) if data is None: data = []; continue; # # cut last 3 fields off: weekday (0-6, Monday is 0), Julian day (day in the year, 1-366), # DST (Daylight Savings Time) flag (-1, 0 or 1) # utc = list(time.gmtime(i)[:-3]) + [999,0,0] data.append(tuple(utc)) def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ListTestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == '__main__': main() ZSI-2.1-a1/test/test_t6.py0000644000175100017510000001204110700756665013451 0ustar zsizsi#!/usr/bin/env python import unittest, sys, multifile, mimetools, base64 from ZSI import * from ZSI import resolvers try: import cStringIO as StringIO except ImportError: import StringIO class t6TestCase(unittest.TestCase): "Test case wrapper for old ZSI t6 test case" def checkt6(self): try: istr = StringIO.StringIO(intext) m = mimetools.Message(istr) cid = resolvers.MIMEResolver(m['content-type'], istr) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) except ParseException, e: print >>OUT, FaultFromZSIException(e).AsSOAP() self.fail() except Exception, e: # Faulted while processing; assume it's in the header. print >>OUT, FaultFromException(e, 1, sys.exc_info()[2]).AsSOAP() self.fail() try: dict = ps.Parse(typecode) except Exception, e: # Faulted while processing; now it's the body print >>OUT, FaultFromException(e, 0, sys.exc_info()[2]).AsSOAP() self.fail() self.failUnlessEqual(dict['stringtest'], strExtTest, "Failed to extract stringtest correctly") print base64.encodestring(cid['partii@zolera.com'].read()) v = dict['b64'] print type(v), 'is type(v)' self.failUnlessEqual(cid['partii@zolera.com'].getvalue(), v, "mismatch") print base64.encodestring(v) from ZSI.wstools.c14n import Canonicalize z = dict['xmltest'] print type(z), z print Canonicalize(z) def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t6TestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") OUT = sys.stdout typecode = TC.Struct(None, [ TC.String('b64'), TC.String('stringtest'), TC.XML('xmltest'), ]) intext='''Return-Path: Received: from zolera.com (os390.zolera.com [10.0.1.9]) by zolera.com (8.11.0/8.11.0) with ESMTP id f57I2sf00832 for ; Thu, 7 Jun 2001 14:02:54 -0400 Sender: rsalz@zolera.com Message-ID: <3B1FC1D1.FF6B21B4@zolera.com> Date: Thu, 07 Jun 2001 14:02:57 -0400 From: Rich Salz X-Mailer: Mozilla 4.72 [en] (X11; U; Linux 2.2.14-5.0 i686) X-Accept-Language: en MIME-Version: 1.0 To: rsalz@zolera.com Subject: mime with attachments Content-Type: multipart/mixed; boundary="------------68E4BAC5B266315E42428C64" Status: R This is a multi-part message in MIME format. --------------68E4BAC5B266315E42428C64 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit --------------68E4BAC5B266315E42428C64 Content-Type: text/plain; charset=us-ascii; name="abs.txt" Content-Transfer-Encoding: 7bit Content-ID: Content-Disposition: inline; filename="abs.txt" Digitial Signatures in a Web Services World An influential Forrestor report created the term inverted security: it's not about who you keep out, it's about who you let in. Customer portals, without a costly PKI deployment or application integration issues. --------------68E4BAC5B266315E42428C64 Content-Type: application/pdf; name="gmpharma.pdf" Content-Transfer-Encoding: base64 Content-ID: Content-Disposition: inline; filename="gmpharma.pdf" JVBERi0xLjINJeLjz9MNCjQzIDAgb2JqDTw8IA0vTGluZWFyaXplZCAxIA0vTyA0NSANL0gg WyAxMTQ0IDM5NiBdIA0vTCA2NjkwMiANL0UgMTAyODIgDS9OIDkgDS9UIDY1OTI0IA0+PiAN RB3nwVOQH9JpmFv6Ri2Zq7mlddSS2B5WcZwvAP+gy9QtuYlfqj1rsi9WqJOszzHXmXZ8fXxK XBBztIpgbkRrd+SGtY4QXo0fX0VN86uKXwtrkd7h1qiq2FUtXl6uNfnCoyX1Dve1O3RPRyhG sKn6fLMb+uSSIHPQkClRBwu5gechz/1PBUBSB34jXbPdMTIb+/wRP+pauSAhLBzFELDOgk5b PaIPAnIudFovQTc7Df2Ws9Atz4Bua+oINphIOojogG5LP3Tb3oNu8bsmuK+wFXEdbfgFIx+G gKULYx5A2WnaDXB5JeoRQg90S0HcX2dCPmRCqDXB/aX34KujsPwJ/UpRdxXPeAftDkQS6hag bh/yTOiUyqBz9CzxnyMYQGDO0jrUZ47kkWfmYvVg --------------68E4BAC5B266315E42428C64 Content-ID: <12@zolera.com> this is a foo redundnant ns decl b test --------------68E4BAC5B266315E42428C64-- ''' strExtTest = ''' Digitial Signatures in a Web Services World An influential Forrestor report created the term inverted security: it's not about who you keep out, it's about who you let in. Customer portals, without a costly PKI deployment or application integration issues. ''' if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_t9.py0000644000175100017510000006135710425515732013462 0ustar zsizsi#!/usr/bin/env python import unittest, sys, sha, base64 from ZSI import _get_element_nsuri_name from ZSI.parse import ParsedSoap from ZSI.wstools.c14n import Canonicalize from ZSI.wstools.Namespaces import WSA200403, SOAP from cStringIO import StringIO class CanonicalizeFromTestCase(unittest.TestCase): "c14n tests, this has nothing to do with ws-addressing." def setUp(self): self.ps = ParsedSoap(XML_INST1) self.el = filter(lambda el: _get_element_nsuri_name(el) == (WSA200403.ADDRESS, "From"), self.ps.header_elements)[0] def tearDown(self): del self.ps del self.el def check_c14n(self): """http://www.w3.org/TR/xml-c14n """ s = StringIO() Canonicalize(self.el, s, unsuppressedPrefixes=None) cxml = s.getvalue() d1 = base64.encodestring(sha.sha(C14N_INC1).digest()).strip() d2 = base64.encodestring(sha.sha(cxml).digest()).strip() self.assertEqual(d1, d2) self.assertEqual(d1, C14N_INC1_DIGEST) def check_c14n_exc(self): """http://www.w3.org/TR/xml-exc-c14n/ """ s = StringIO() Canonicalize(self.el, s, unsuppressedPrefixes=[]) cxml = s.getvalue() d1 = base64.encodestring(sha.sha(C14N_EXCL1).digest()).strip() d2 = base64.encodestring(sha.sha(cxml).digest()).strip() self.assertEqual(d1, C14N_EXCL1_DIGEST) self.assertEqual(d1, d2) def check_c14n_exc2_unsuppressed(self): """http://www.w3.org/TR/xml-exc-c14n/ The method of canonicalization described in this specification receives an InclusiveNamespaces PrefixList parameter, which lists namespace prefixes that are handled in the manner described by the Canonical XML Recommendation """ s = StringIO() Canonicalize(self.el, s, unsuppressedPrefixes=['xsi', 'xsd']) cxml = s.getvalue() d1 = base64.encodestring(sha.sha(C14N_EXCL2).digest()).strip() d2 = base64.encodestring(sha.sha(cxml).digest()).strip() self.assertEqual(d1, C14N_EXCL2_DIGEST) self.assertEqual(d1, d2) def check_c14n_exc3(self): """http://www.w3.org/TR/xml-exc-c14n/ tests if a namespace defined in a parent node to the top node to be canonicalized is added when discovered that this namespace is used. """ self.ps = ParsedSoap(XML_INST2) self.el = self.ps.body s = StringIO() Canonicalize(self.el, s, unsuppressedPrefixes=[]) cxml = s.getvalue() print cxml d1 = base64.encodestring(sha.sha(C14N_EXCL3).digest()).strip() d2 = base64.encodestring(sha.sha(cxml).digest()).strip() self.assertEqual(d1, C14N_EXCL3_DIGEST) self.assertEqual(d1, d2) def xcheck_c14n_exc4(self): RCVDIGEST = "jhTbi7gWlY9oLqsRr+EZ0bokRFA=" CALDIGEST = "IkMyI4zCDlK41qE7sZxvkFHJioU=" d1 = base64.encodestring(sha.sha(WRONG).digest()).strip() d2 = base64.encodestring(sha.sha(CORRECT).digest()).strip() ps = ParsedSoap(XML_INST4) el = filter(lambda el: _get_element_nsuri_name(el) == (WSA200403.ADDRESS, "MessageID"), ps.header_elements)[0] s = StringIO() Canonicalize(el, s, unsuppressedPrefixes=[]) cxml = s.getvalue() print "-- "*20 print cxml print "-- "*20 d3 = base64.encodestring(sha.sha(cxml).digest()).strip() self.assertEqual(d1, RCVDIGEST) self.assertEqual(d2, CALDIGEST) self.assertEqual(d3, CALDIGEST) def makeTestSuite(): suite = unittest.TestSuite() #suite.addTest(unittest.makeSuite(CanonicalizeFromTestCase, "check")) suite.addTest(unittest.makeSuite(CanonicalizeFromTestCase, "xcheck")) return suite C14N_EXCL1_DIGEST = "xSOXT+dlQwo5uT9PbK08of6W9PM=" C14N_EXCL1 = """http://bosshog.lbl.gov:9999/wsrf/services/SecureCounterService10577413""" C14N_INC1_DIGEST = "qdU4f7/+BeHV/JlVGIPM90fNeV8=" C14N_INC1 = """http://bosshog.lbl.gov:9999/wsrf/services/SecureCounterService10577413""" C14N_EXCL2_DIGEST = "+IEqF6DRo36Bh93A06S7C4Cmcuo=" C14N_EXCL2 = """http://bosshog.lbl.gov:9999/wsrf/services/SecureCounterService10577413""" C14N_EXCL3_DIGEST = "VJvTr+Mx3TeWsQY6iwGbhAJ9/eA=" C14N_EXCL3 = """http://131.243.2.147:8888/wsrf/services/DelegationService8adaa710-ba01-11da-bc99-cbed73daa755""" XML_INST1 = """ m9pihAqIBdcdk7ytDvccj89eWi8= ofD+Ket5kzR2u/5jWKbFTMtmigk= SoQ7RlJa3r94weDWBuWAg/BvydQ= z6sCEkkRJrCuY/C0S5b+46WfyMs= +IEqF6DRo36Bh93A06S7C4Cmcuo= NFltkKAJpmMkPbJQj5MW1qVceto= AAAAAAAAAAMAAAvZTrXlZjRSO7tP12tId+lehprEKgk= 3b1ef410-ab3d-11da-9436-88b687faed94uuid:3d592ca0-ab3d-11da-9436-88b687faed94http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymoushttp://counter.com/CounterPortType/addResponsehttp://bosshog.lbl.gov:9999/wsrf/services/SecureCounterService10577413uuid:1141449047.0513""" XML_INST2 = """ MIIGbDCCA6owggKSoAMCAQICAh07MA0GCSqGSIb3DQEBBQUAMGkxEzARBgoJkiaJk/IsZAEZFgNv cmcxGDAWBgoJkiaJk/IsZAEZFghET0VHcmlkczEgMB4GA1UECxMXQ2VydGlmaWNhdGUgQXV0aG9y aXRpZXMxFjAUBgNVBAMTDURPRUdyaWRzIENBIDEwHhcNMDUxMjIxMjExNzUzWhcNMDYxMjIxMjEx NzUzWjBfMRMwEQYKCZImiZPyLGQBGRYDb3JnMRgwFgYKCZImiZPyLGQBGRYIZG9lZ3JpZHMxDzAN BgNVBAsTBlBlb3BsZTEdMBsGA1UEAxMUTWF0dCBSb2RyaWd1ZXogODkzMzAwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCec6hEiQcu1lIa2pS/KxgmXbkfKLKrOm6AxPrfkht6Ja91+rdY TLQ4a21S792hglezFbylzLkDmCzYp43fH1xh0LlLea+YzUB7LoUnG29qv73CylSYqDnJWAU+sHhw fr3Hqpp6GxbxPqXJXcICs1lKbwinsgZQxMsml25O6ZF0x772b1kyiL4IsKwaS9/BQQCWCDA6vcMX 4cKx67EYtDqopRfMUf9Ne3MAOpsfp17U/yeznDemjuxL5Q+zI1Qbq3Kx1kpFcLXKlSNz258EPF/u /9sOLME3EVp/9n+MjvgHJsTXvlMahF6Ci1UF+clZgMLjEhDHaLghiaagt7t8tqVnAgMBAAGjZjBk MBEGCWCGSAGG+EIBAQQEAwIF4DAOBgNVHQ8BAf8EBAMCBPAwHwYDVR0jBBgwFoAUyhkdEo5upDhd QtQxDgjb2Y0XDV0wHgYDVR0RBBcwFYETTUtSb2RyaWd1ZXpAbGJsLmdvdjANBgkqhkiG9w0BAQUF AAOCAQEAgRZkSHe4Gn9djOBlkn+5iGL5fiWb9LbZDeomS9OzfFePAP9G/8ihl+RLBZXgSdLXZm9v d6Ep+yVD4YHs0cZzaFlPnPxv6h6yWva+nEsTKkbm70yJrv1nsWP1k+nuBY6U6OQsa6um6Z1OCU6H u6uPSlyuedV93Vf77THU/1nv6Awf9pFhKolQVlmtQ4zfS9M4WNlNIAZYGgldaFjHVYQYee07Mb4S Y5EIGUQ6XiabX5C1xbynxniNTL5p4beW/dPZ6w7znHxHpJScoqELAVg2WbQhlcKQaKZPOO1fHy0/ VM907Q1v541/FAhO1+5sTEYf1JPhsNYvNXMw+Z9ukb1PSzCCArowggGioAMCAQICBFSZyLUwDQYJ KoZIhvcNAQEEBQAwXzETMBEGCgmSJomT8ixkARkWA29yZzEYMBYGCgmSJomT8ixkARkWCGRvZWdy aWRzMQ8wDQYDVQQLEwZQZW9wbGUxHTAbBgNVBAMTFE1hdHQgUm9kcmlndWV6IDg5MzMwMB4XDTA2 MDMyMjE4NTQwOFoXDTA2MDMyMzA2NTkwOFowdDETMBEGCgmSJomT8ixkARkWA29yZzEYMBYGCgmS JomT8ixkARkWCGRvZWdyaWRzMQ8wDQYDVQQLEwZQZW9wbGUxHTAbBgNVBAMTFE1hdHQgUm9kcmln dWV6IDg5MzMwMRMwEQYDVQQDEwoxNDE5MzY0NTMzMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMpt 7hUlms1nmxRfeSlJQP7omyLujGCKkTTU0CAG2r40eKOqHNtCeFYCXT5/oCMrgB7YyEmxuUz57bJP sGPyHnsCAwEAAaMxMC8wDgYDVR0PAQH/BAQDAgSwMB0GCCsGAQUFBwEOAQH/BA4wDDAKBggrBgEF BQcVATANBgkqhkiG9w0BAQQFAAOCAQEALEPirNkcuhZB4/nouueISh/x+tD3GAgvAEERsVdJyWrF EceT9v0xN2FI00sk2U5yi5wCOhyCZfwN79/dVo0CGB8OqpG5rJ4GnhJ/eea8h98ZVqR0oRWb7IcG FhqU1ja930dCZGpoaBKjy39HHgzQTFuvwXjaWyoV6C7sAE1Aw3PSafMGaHxjJoK386KpolVxZbrq DpeKZoxPZKBC7+hyv4vO7KG6s9G/tmIkTroMKEtHHz7NhZHkv+h1aO8g8p57j9uZ8EvdUWUcnwiS EWXM9AMmho4Z5rex2cdE/s3d+Wa7IFhYoo61VW6v4amSHQH/o4Vdt0pN4hh+/9y32lp89g== xqoPUGjk97yY+StAheOFmeaHgbw= VJvTr+Mx3TeWsQY6iwGbhAJ9/eA= W1PrEK32GMCbF6FTEmlYiYwqAeQ= lWhqYlKqBnB4LwkRWyXMwHy18hc= 2Zjgz4McHaxMLfpBbqelAqWvRsU= knsi7QmfOvjrn5mWClmsbCpZ32A= /yBXQ0yxPqpgSGYym/DA08k0dXM= LuGNfoVBzUIoF0AU0lzJkH9kAOi+PQVG8hMrCIEjWh1lifSG/bquhu/qZVq78x3UR+tGK411hWuQ nGle1GvY0A== 2006-03-23T00:11:14Z2006-03-23T00:16:14Zuuid:8aec8160-ba01-11da-bc99-cbed73daa755http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymoushttp://www.globus.org/08/2004/delegationService/DelegationFactoryPortType/RequestSecurityTokenResponsehttp://bosshog.lbl.gov:8888/wsrf/services/DelegationFactoryServiceuuid:1143072675.25http://131.243.2.147:8888/wsrf/services/DelegationService8adaa710-ba01-11da-bc99-cbed73daa755""" CORRECT = """uuid:1143760705.98""" WRONG = """uuid:1143760705.98""" XML_INST4 = """ uuid:1143760705.98http://counter.com/CounterPortType/createCounterRequesthttp://131.243.2.159:9080/wsrf/services/SecureCounterServicehttp://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous IkMyI4zCDlK41qE7sZxvkFHJioU= DyEF6Pa7w3SSEVJ98LIoX2LW85k= p/2PhmYP+/1UPcpwsRcdlvLmOAg= KFLeYjf5ohGUIoPoZV/oew9SuUM= 7Gg0SC1wltHVAwiOfdgZsGM9W5g= AAAAAAAAAAEAAAdrBxzrHLZG4NglRglL9F3rKQu0658= 1000""" def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == '__main__': main() ZSI-2.1-a1/test/test_TCtimes.py0000644000175100017510000001221410517230410014447 0ustar zsizsi#!/usr/bin/env python import unittest, sys, tests_good, tests_bad, time from ZSI import * try: import cStringIO as StringIO except ImportError: import StringIO class TestCase(unittest.TestCase): '''Examples from "Definitive XML Schema, Priscilla Walmsley, p237-246 ''' def check_dateTime_local_offset(self): # UTC with local timezone offset # typecode = TC.gDateTime() off_hour = time.altzone/60/60 off_min = time.altzone%60 stamp_offset = '1968-04-02T13:20:00+%02d:%02d' %(off_hour,off_min) data = typecode.text_to_data(stamp_offset, None, None) stamp = typecode.get_formatted_content(data) correct = "1968-04-01T22:20:00Z" self.failUnless(stamp == correct, 'dateTime with local offset(%s), expecting "%s" got "%s"' %( stamp_offset, correct, stamp)) def check_valid_dateTime(self): typecode = TC.gDateTime() for i in ('1968-04-02T13:20:00', '1968-04-02T13:20:15.5', '1968-04-02T13:20:00-05:00', '1968-04-02T13:20:00Z'): data = typecode.text_to_data(i, None, None) text = typecode.get_formatted_content(data) def check_parse_microseconds(self): good = (1968, 4, 2, 13, 20, 15, 511, 0, 0) typecode = TC.gDateTime() data = typecode.text_to_data('1968-04-02T13:20:15.511', None, None) self.failUnless(data == good, 'did not parse something %s, not equal %s' %(data,good)) def check_serialize_microseconds(self): dateTime = '1968-04-02T13:20:15.511Z' typecode = TC.gDateTime() text = typecode.get_formatted_content((1968, 4, 2, 13, 20, 15, 511, 0, 0)) self.failUnless(text == dateTime, 'did not serialze correctly %s, not equal %s' %(text, dateTime)) def check_serialize_microseconds_1000(self): bad = (1968, 4, 2, 13, 20, 15, 1000, 0) typecode = TC.gDateTime() self.failUnlessRaises(ValueError, typecode.get_formatted_content, bad) def check_serialize_microseconds_lessZero(self): '''ignore negative microseconds ''' bad = (1968, 4, 2, 13, 20, 15, -1, 0) typecode = TC.gDateTime() text = typecode.get_formatted_content(bad) typecode.get_formatted_content(bad) def check_parse_microseconds2(self): good = (1968, 4, 2, 13, 20, 15, 500, 0, 0) typecode = TC.gDateTime() data = typecode.text_to_data('1968-04-02T13:20:15.5Z', None,None) self.failUnless(data == good, 'did not serialze correctly %s, not equal %s' %(data, good)) #text = typecode.get_formatted_content((1968, 4, 2, 13, 20, 15, 5, 0, 500)) #self.failUnless(text == dateTime, # 'did not serialze correctly %s, not equal %s' %(text, dateTime)) def check_invalid_dateTime(self): typecode = TC.gDateTime() def check_valid_time(self): typecode = TC.gTime() for i in ('13:20:00', '13:20:30.5555', '13:20:00Z'): data = typecode.text_to_data(i, None, None) text = typecode.get_formatted_content(data) def broke_valid_time(self): typecode = TC.gTime() data = typecode.text_to_data('13:20:00-05:00', None, None) def check_invalid_time(self): typecode = TC.gTime() for i in ('5:20:00', '13:20.5:00',): self.failUnlessRaises(Exception, typecode.text_to_data, i, None, None), def broke_invalid_time_no_seconds(self): typecode = TC.gTime() i = '13:20:' self.failUnlessRaises(Exception, typecode.text_to_data, i, None, None) def broke_invalid_time_bad_timeofday(self): typecode = TC.gTime() i = '13:65:00' self.failUnlessRaises(Exception, typecode.text_to_data, i, None, None) def check_valid_date(self): typecode = TC.gDate() for i in ('1968-04-02', '-0045-01-01', '11968-04-02', '1968-04-02+05:00', '1968-04-02Z'): data = typecode.text_to_data(i, None, None) text = typecode.get_formatted_content(data) def check_invalid_date(self): typecode = TC.gDate() for i in ('68-04-02', '1968-4-2', '1968/04/02', '04-02-1968',): self.failUnlessRaises(Exception, typecode.text_to_data, i, None, None), def broke_invalid_date_april31(self): # No checks for valid date April 30 days typecode = TC.gDate() self.failUnlessRaises(Exception, typecode.text_to_data, '1968-04-31', None, None), # # Creates permutation of test options: "check", "check_any", etc # _SEP = '_' for t in [i[0].split(_SEP) for i in filter(lambda i: callable(i[1]), TestCase.__dict__.items())]: test = '' for f in t: test += f if globals().has_key(test): test += _SEP; continue def _closure(): name = test def _makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCase, name)) return suite return _makeTestSuite globals()[test] = _closure() test += _SEP makeTestSuite = check def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/.cvsignore0000644000175100017510000000000607365336046013505 0ustar zsizsi*.pyc ZSI-2.1-a1/test/test_zsi.py0000644000175100017510000000110510643543564013722 0ustar zsizsi#!/usr/bin/env python import unittest import test_t1 import test_t2 import test_t3 import test_t5 import test_t6 import test_t7 import test_t8 import test_t9 import test_union import test_list import test_TCtimes import test_URI import test_rfc2617 import test_QName def makeTestSuite(): return unittest.TestSuite( map(lambda t: globals()[t].makeTestSuite(), filter(lambda g: g.startswith('test_') and True, globals())) ) def main(): unittest.main(defaultTest="makeTestSuite") suite = unittest.TestSuite() if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_t5.py0000644000175100017510000000265710700756665013464 0ustar zsizsi#!/usr/bin/env python import unittest, multifile, mimetools from ZSI import * from ZSI import resolvers from xml.dom import Node #from xml.dom.ext.reader import PyExpat from ZSI.parse import DefaultReader as Reader try: import cStringIO as StringIO except ImportError: import StringIO class t5TestCase(unittest.TestCase): "Test case wrapper for old ZSI t5 test case" def checkt5(self): istr = StringIO.StringIO(intext) m = mimetools.Message(istr) if m.gettype()[0:10] == "multipart/": cid = resolvers.MIMEResolver(m['content-type'], istr) xml = cid.GetSOAPPart() print 'xml=', xml.getvalue() for h,b in cid.parts: print h, b.read() dom = Reader.fromStream(xml) print dom def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t5TestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") intext = '''Content-Type: multipart/mixed; boundary="sep" Subject: testing skip this --sep Content-type: text/xml hello world --sep Content-Type: text/plain content-id: this is some plain text --sep content-type: application/skipme do not see this okay? --sep Content-Type: text/xml Content-ID: spoken --sep-- ''' if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_callhome.py0000644000175100017510000000113510632350511014666 0ustar zsizsi#!/usr/bin/env python import os,unittest from ZSI import version from ZSI.wstools.logging import gridLog os.environ['GRIDLOG_ON'] = '1' os.environ['GRIDLOG_DEST'] = "gridlog-udp://netlogger.lbl.gov:15100" class TestCase(unittest.TestCase): def ping(self): gridLog(event="zsi.test.test_callhome.ping", zsi="v%d.%d.%d" % version.Version, prog="test_callhome.py") def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCase, "ping")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == '__main__': main() ZSI-2.1-a1/test/test_URI.py0000644000175100017510000000430210557712453013555 0ustar zsizsi#!/usr/bin/env python import unittest, sys, tests_good, tests_bad, time from ZSI import * try: import cStringIO as StringIO except ImportError: import StringIO """Bug [ 1520092 ] URI Bug: urllib.quote escaping reserved chars From rfc2396: "If the data for a URI component would conflict with the reserved purpose, then the conflicting data must be escaped before forming the URI." reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," This implies that if ":" is used for a reserved purpose, if scheme is defined then append scheme to result append ":" to result , then it should not be escaped. """ class TestCase(unittest.TestCase): def check_uri_quoting(self): """ all reserved characters used for reserved purpose. """ sw1 = SoapWriter(envelope=False) tc1= TC.URI('sourceforge') orig = 'https://sourceforge.net/tracker/index.php?func=detail&aid=1520092&group_id=26590&atid=387667' sw1.serialize(orig, typecode=tc1, typed=False) s1 = str(sw1) sw2 = SoapWriter(envelope=False) tc2= TC.String('sourceforge') sw2.serialize(orig, typecode=tc2, typed=False) s2 = str(sw2) print s1 print s2 self.failUnless(s1 == s2, 'reserved characters used for reserved purpose should not be escaped.') ps = ParsedSoap(s2, envelope=False) pyobj = ps.Parse(tc2) self.failUnless(pyobj == orig, 'parsed object should be equivalent to original') # # Creates permutation of test options: "check", "check_any", etc # _SEP = '_' for t in [i[0].split(_SEP) for i in filter(lambda i: callable(i[1]), TestCase.__dict__.items())]: test = '' for f in t: test += f if globals().has_key(test): test += _SEP; continue def _closure(): name = test def _makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCase, name)) return suite return _makeTestSuite globals()[test] = _closure() test += _SEP makeTestSuite = check def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/README0000644000175100017510000000076110204466544012366 0ustar zsizsiThese tests are in the process of being incorporated in pyunit. Not all errors are currently being caught by pyunit, so it is still necessary to check the output of the code by hand. Two top level modules have been provided to run the tests. Use "test_zsi.py" to run all of the local tests, or "test_zsi_net.py" to run all of the zsi tests including those that require network access. Additional tests are located in the wsdl2py/ directory; see the README there for more information on those. ZSI-2.1-a1/test/test_t3.py0000644000175100017510000000164010356606232013440 0ustar zsizsi#!/usr/bin/env python import unittest from ZSI import * from ZSI.wstools.logging import setBasicLoggerDEBUG setBasicLoggerDEBUG() class t3TestCase(unittest.TestCase): "Test case wrapper for old ZSI t3 test case" def checkt3(self): a = None try: 3 / 0 except Exception, e: a = e f = FaultFromException(a, 0) text = f.AsSOAP() i = 0 for l in text.split('\n'): print i, l i += 1 ps = ParsedSoap(text) if ps.IsAFault(): f = FaultFromFaultMessage(ps) print f.AsSOAP() self.failUnless(f.AsSOAP().find(str(a)) > 0) print '--'*20 def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t3TestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/tests_good.py0000644000175100017510000000544107707636072014243 0ustar zsizsitest01 = ''' 34.5 ''' test02 = ''' 5 DEF ''' test03 = ''' DEF DEF Corp 34.1 ''' test04 = ''' 5 34.5 ''' test05 = ''' 34.5 10000 ''' test06 = ''' 34.5 ''' ZSI-2.1-a1/test/wsdl2py/0000755000175100017510000000000010712455110013075 5ustar zsizsiZSI-2.1-a1/test/wsdl2py/test_AWSECommerceService.py0000755000175100017510000011235010712156244020254 0ustar zsizsi#!/usr/bin/env python # -*- coding: utf-8 -* ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite, TestException from ZSI.schema import ElementDeclaration, GED from ZSI import ParsedSoap """ Unittest for contacting the Amazon ECommerce Service WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_')) return suite TargetNamespace = 'http://webservices.amazon.com/AWSECommerceService/2007-10-29' class AmazonTestCase(ServiceTestCase): """Test case for Amazon ECommerce Web service """ name = "test_AWSECommerceService" client_file_name = "AWSECommerceService_client.py" types_file_name = "AWSECommerceService_types.py" server_file_name = "AWSECommerceService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') self.wsdl2py_args.append('--lazy') def test_local_bug_1525567(self): element = GED(TargetNamespace, 'Items') # Make sure this is a GED self.failUnless(isinstance(element, ElementDeclaration), '"%s" not a GED' %element) def test_local_parse_ItemSearch(self): msg = self.client_module.ItemSearchResponseMsg() ps = ParsedSoap(ItemSearchResponseMsg) response = ps.Parse(msg.typecode) response.OperationRequest.Arguments for i in response.OperationRequest.Arguments.Argument: i.get_attribute_Name() i.get_attribute_Value() for i in response.OperationRequest.HTTPHeaders.Header or []: i.get_attribute_Name() i.get_attribute_Value() response.OperationRequest.RequestId response.OperationRequest.RequestProcessingTime for its in response.Items: self.failUnless(its.TotalResults == 61, '') self.failUnless(its.TotalPages == 7, '') for it in its.Item: it.ASIN; it.Accessories; #it.AlternateVersions; it.BrowseNodes #it.Collections; it.CustomerReviews ;it.DetailPageURL it.EditorialReviews; it.Errors; it.ImageSets; it.ItemAttributes it.LargeImage; it.ListmaniaLists; it.MediumImage; it.MerchantItemAttributes it.OfferSummary; it.Offers; #it.ParentASIN; it.SalesRank; it.SearchInside it.SimilarProducts; it.SmallImage; it.Subjects; it.Tracks; def test_net_ItemSearch(self): loc = self.client_module.AWSECommerceServiceLocator() port = loc.getAWSECommerceServicePort(**self.getPortKWArgs()) msg = self.client_module.ItemSearchRequestMsg() msg.SubscriptionId = '0HP1WHME000749APYWR2' request = msg.new_Request() msg.Request = [request] # request request.ItemPage = 1 request.SearchIndex = "Books" request.Keywords = 'Tamerlane' request.ResponseGroup = ['Medium',] response = port.ItemSearch(msg) response.OperationRequest self.failUnless(response.OperationRequest.Errors is None, 'ecommerce site reported errors') response.OperationRequest.Arguments for i in response.OperationRequest.Arguments.Argument: i.get_attribute_Name() i.get_attribute_Value() for i in response.OperationRequest.HTTPHeaders.Header or []: i.get_attribute_Name() i.get_attribute_Value() response.OperationRequest.RequestId response.OperationRequest.RequestProcessingTime for its in response.Items: for it in its.Item: it.ASIN; it.Accessories; #it.AlternateVersions; it.BrowseNodes #it.Collections; it.CustomerReviews ;it.DetailPageURL it.EditorialReviews; it.Errors; it.ImageSets; it.ItemAttributes it.LargeImage; it.ListmaniaLists; it.MediumImage; it.MerchantItemAttributes it.OfferSummary; it.Offers; #it.ParentASIN; it.SalesRank; it.SearchInside it.SimilarProducts; it.SmallImage; it.Subjects; it.Tracks; it.VariationSummary; it.Variations ItemSearchResponseMsg=""" """ %TargetNamespace + """

013FGTRCYPQV2EFA975Q0.353393793106079True1TamerlaneMediumBooks617030681465Xhttp://www.amazon.com/gp/redirect.html%3FASIN=030681465X%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/030681465X%253FSubscriptionId=0HP1WHME000749APYWR2262921http://ec1.images-amazon.com/images/P/030681465X.01._SCTHUMBZZZ_V66860320_.jpg7550http://ec1.images-amazon.com/images/P/030681465X.01._SCMZZZZZZZ_V66860320_.jpg160108http://ec1.images-amazon.com/images/P/030681465X.01._SCLZZZZZZZ_V66860320_.jpg500337http://ec1.images-amazon.com/images/P/030681465X.01._SCSWATCHZZ_V66860320_.jpg3020http://ec1.images-amazon.com/images/P/030681465X.01._SCTHUMBZZZ_V66860320_.jpg7550http://ec1.images-amazon.com/images/P/030681465X.01._SCMZZZZZZZ_V66860320_.jpg160108http://ec1.images-amazon.com/images/P/030681465X.01._SCLZZZZZZZ_V66860320_.jpg500337Justin MarozziHardcover9209780306814655New Ed030681465X2695USD$26.95Da Capo Press1368150904174640Book2006-02-22Da Capo PressDa Capo PressTamerlane: Sword of Islam, Conqueror of the World399USD$3.99399USD$3.992695USD$26.95312410Book DescriptionA powerful account of the life of Tamerlane the Great (1336-1405), the last great Mongol conqueror of Central Asia, ruler of a vast empire, and one of history's most brutal tyrants <P> Tamerlane, aka Temur-the Mongol successor to Genghis Khan-ranks with Alexander the Great as one of the world's great conquerors, yet the details of his life are scarcely known in the West. Born in obscurity and poverty, he rose to become a fierce tribal leader, and with that his dominion and power grew with astonishing speed. He blazed through Asia, razing cities to the ground. He tortured conquered inhabitants without mercy, sometimes ordering them buried alive, at other times decapitating them. Over the ruins of conquered Baghdad, Tamerlane had his soldiers erect a pyramid of 90,000 enemy heads. As he and his armies swept through Central Asia, sacking, and then rebuilding cities, Tamerlane gradually imposed an iron rule and a refined culture over a vast territory-from the steppes of Asia to the Syrian coastline. <P> Justin Marozzi traveled in the footsteps of this fearsome emperor of Samarkand (modern-day Uzbekistan) to write this book, which is part history, part travelogue. He carefully follows the path of this infamous and enigmatic conqueror, recounting the history and the story of this cruel, cultivated, and indomitable warrior.1851684573http://www.amazon.com/gp/redirect.html%3FASIN=1851684573%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/1851684573%253FSubscriptionId=0HP1WHME000749APYWR2567693http://ec1.images-amazon.com/images/P/1851684573.01._SCTHUMBZZZ_V63318467_.jpg7549http://ec1.images-amazon.com/images/P/1851684573.01._SCMZZZZZZZ_V63318467_.jpg160104http://ec1.images-amazon.com/images/P/1851684573.01._SCLZZZZZZZ_V63318467_.jpg500324http://ec1.images-amazon.com/images/P/1851684573.01._SCSWATCHZZ_V63318467_.jpg3020http://ec1.images-amazon.com/images/P/1851684573.01._SCTHUMBZZZ_V63318467_.jpg7549http://ec1.images-amazon.com/images/P/1851684573.01._SCMZZZZZZZ_V63318467_.jpg160104http://ec1.images-amazon.com/images/P/1851684573.01._SCLZZZZZZZ_V63318467_.jpg500324Robert RandPaperback958.7086978185168457118516845731495USD$14.95Oneworld Publications12246678454512Book2006-09-11Oneworld PublicationsOneworld PublicationsTamerlane's Children: Dispatches from Contemporary Uzbekistan708USD$7.08708USD$7.081495USD$14.9531910Book DescriptionIn the central park of Tashkent, in a place the Uzbeks call the square, a magnificent statue of a mounted warrior dominates the surroundings - Tamerlane - national hero of post-Soviet Uzbekistan. And yet how does this 14th century conqueror reflect one of the world's most diverse and politically intriguing countries?Having spent three years in the region, renowned journalist Robert Rand seeks to answer this question, covering an assortment of fascinating topics, ranging from the effect of 9/11 to the clash of culture in Uzbek pop music. Overflowing with charming anecdotes and loveable personalities, Rand gives the reader a real sense of the country's confused identity and the challenges which it and its people will face in generations to come.0521633842http://www.amazon.com/gp/redirect.html%3FASIN=0521633842%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/0521633842%253FSubscriptionId=0HP1WHME000749APYWR2584780http://ec1.images-amazon.com/images/P/0521633842.01._SCTHUMBZZZ_V1114821525_.jpg6039http://ec1.images-amazon.com/images/P/0521633842.01._SCMZZZZZZZ_V1114821525_.jpg14090http://ec1.images-amazon.com/images/P/0521633842.01._SCLZZZZZZZ_V1114821525_.jpg475306http://ec1.images-amazon.com/images/P/0521633842.01._SCSWATCHZZ_V1114821525_.jpg3019http://ec1.images-amazon.com/images/P/0521633842.01._SCTHUMBZZZ_V1114821525_.jpg6039http://ec1.images-amazon.com/images/P/0521633842.01._SCMZZZZZZZ_V1114821525_.jpg14090http://ec1.images-amazon.com/images/P/0521633842.01._SCLZZZZZZZ_V1114821525_.jpg475306Beatrice Forbes ManzPaperback950.29780521633840Reprint05216338422499USD$24.99Cambridge University Press12486785074562Book2002-10-26Cambridge University Press2002-10-26Cambridge University PressRise and Rule of Tamerlane, The (Canto original series)1950USD$19.50869USD$8.692499USD$24.99222320Book DescriptionThis is the first serious study of Tamerlane, the great nomad conqueror who rose to power in 1370 on the ruins of the Mongol Empire and led his armies on campaigns of unprecedented scope, ranging from Moscow to Delhi. As the last nomad ruler to unite the steppe regions of Eurasia, Tamerlane marks the transition from the era of nomad conquest and rule to the modern ascendency of the settled world.189226420Xhttp://www.amazon.com/gp/redirect.html%3FASIN=189226420X%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/189226420X%253FSubscriptionId=0HP1WHME000749APYWR2817168http://ec1.images-amazon.com/images/P/189226420X.01._SCTHUMBZZZ_V40073149_.jpg7550http://ec1.images-amazon.com/images/P/189226420X.01._SCMZZZZZZZ_V40073149_.jpg160107http://ec1.images-amazon.com/images/P/189226420X.01._SCLZZZZZZZ_V40073149_.jpg500333http://ec1.images-amazon.com/images/P/189226420X.01._SCSWATCHZZ_V40073149_.jpg3020http://ec1.images-amazon.com/images/P/189226420X.01._SCTHUMBZZZ_V40073149_.jpg7550http://ec1.images-amazon.com/images/P/189226420X.01._SCMZZZZZZZ_V40073149_.jpg160107http://ec1.images-amazon.com/images/P/189226420X.01._SCLZZZZZZZ_V40073149_.jpg500333Roy StierPaperback9309781892264206189226420X1200USD$12.00Timeless Voyager Press135679900115600Book2006-09-05Timeless Voyager Press2006-09-21Timeless Voyager PressTamerlane: The Ultimate Warrior- Map Edition832USD$8.32862USD$8.621200USD$12.0017810Book DescriptionTamerlane: The Ultimate Warrior- Map Edition (978-1-892264-20-6) In this Third Edition, little-known fourteenth century Muslim leader who inspired a vast army of Islamic followers to swarm through central and western Asia in a conquering wave, has been captured in the first complete history using narrative form by Roy Stier. Tamerlane, the Ultimate Warrior paints the violent and controversial true story of the swift horseman who threatened much of the Old World, crushing the Ottoman Empire and intimidating kings and emperors. A trail of devastation followed the ruthless conqueror from Delhi to Baghdad, yet incidents of mercy for his enemies revealed a benign side to Tamerlane. In the pageantry of rulers, Tamerlane found little recognition from the historians of later centuries. Killer? Demonic? ¿ or charismatic visionary with a flashing sword and a view of the world united under the banner of Islamic purity? Is there a message for moderns in the story of the military genius who scythed his way through a sizable part of the known world? The readers of this book think so. There are 9 illustrations and photographs, 28 new maps of the ancient world circa 1300 A.D., complete references for researchers, glossary of terms, four appendices, a complete chronology of events, and an index in the 354 page 6¿ X 9¿ book. Retail price: $21.95 plus S/H.B00087SKA2http://www.amazon.com/gp/redirect.html%3FASIN=B00087SKA2%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/B00087SKA2%253FSubscriptionId=0HP1WHME000749APYWR2955067Harold LambUnknown BindingBantam Books216Book1955Bantam BooksBantam BooksTamerlane: Conqueror of the earth795USD$7.9503000850459494http://www.amazon.com/gp/redirect.html%3FASIN=0850459494%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/0850459494%253FSubscriptionId=0HP1WHME000749APYWR2230563http://ec1.images-amazon.com/images/P/0850459494.01._SCTHUMBZZZ_V1128022797_.jpg7556http://ec1.images-amazon.com/images/P/0850459494.01._SCMZZZZZZZ_V1128022797_.jpg160119http://ec1.images-amazon.com/images/P/0850459494.01._SCLZZZZZZZ_V1128022797_.jpg500372http://ec1.images-amazon.com/images/P/0850459494.01._SCSWATCHZZ_V1128022797_.jpg3022http://ec1.images-amazon.com/images/P/0850459494.01._SCTHUMBZZZ_V1128022797_.jpg7556http://ec1.images-amazon.com/images/P/0850459494.01._SCMZZZZZZZ_V1128022797_.jpg160119http://ec1.images-amazon.com/images/P/0850459494.01._SCLZZZZZZZ_V1128022797_.jpg500372David NicollePaperbackAngus Mcbride978085045949408504594941595USD$15.95Osprey Publishing1481597836722Book1990-07-26Osprey Publishing1990-07-26Osprey PublishingThe Age of Tamerlane (Men-at-Arms)900USD$9.001200USD$12.004300Book DescriptionTamerlane or Timur-i-Lenk ('Timur the Lame') is one of the most extraordinary conquerors in history. In the late 14th century his armies seized huge territories from the borders of Mongolia to Palestine and Anatolia. His passage was marked by massacres that outdid even those of the Mongols for sheer savagery. Timur's career was unequalled since Alexander the Great in terms of constant battlefield success. Only in his youth, while recovering his family estates south of Samarqand, did he face occasional defeat. This title tells the remarkable story of Timur and details the organisation, tactics, arms and armour of his all-conquering army.1410222950http://www.amazon.com/gp/redirect.html%3FASIN=1410222950%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/1410222950%253FSubscriptionId=0HP1WHME000749APYWR2665664http://ec1.images-amazon.com/images/P/1410222950.01._SCTHUMBZZZ_V1120611566_.jpg7550http://ec1.images-amazon.com/images/P/1410222950.01._SCMZZZZZZZ_V1120611566_.jpg160107http://ec1.images-amazon.com/images/P/1410222950.01._SCLZZZZZZZ_V1120611566_.jpg500333http://ec1.images-amazon.com/images/P/1410222950.01._SCSWATCHZZ_V1120611566_.jpg3020http://ec1.images-amazon.com/images/P/1410222950.01._SCTHUMBZZZ_V1120611566_.jpg7550http://ec1.images-amazon.com/images/P/1410222950.01._SCMZZZZZZZ_V1120611566_.jpg160107http://ec1.images-amazon.com/images/P/1410222950.01._SCLZZZZZZZ_V1120611566_.jpg500333PaperbackDaniel L. BurghartTheresa Sabonis-helf327978141022295414102229503450USD$34.50University Press of the Pacific1504112900161600Book2005-05-31University Press of the PacificUniversity Press of the PacificIn the Tracks of Tamerlane: Central Asia's Path to the 21st Century2995USD$29.954062USD$40.62157001853141046http://www.amazon.com/gp/redirect.html%3FASIN=1853141046%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/1853141046%253FSubscriptionId=0HP1WHME000749APYWR2980362David NicolleRichard HookHardcover950.20922978185314104118531410462495USD$24.95Firebird1208100075160775Book1990-09FirebirdFirebirdThe Mongol Warlords: Ghengis Khan, Kublai Khan, Hulegu, Tamerlane (Heroes & Warriors)4700USD$47.0004000306815435http://www.amazon.com/gp/redirect.html%3FASIN=0306815435%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/0306815435%253FSubscriptionId=0HP1WHME000749APYWR2503889http://ec1.images-amazon.com/images/P/0306815435.01._SCTHUMBZZZ_V35579588_.jpg7550http://ec1.images-amazon.com/images/P/0306815435.01._SCMZZZZZZZ_V35579588_.jpg160107http://ec1.images-amazon.com/images/P/0306815435.01._SCLZZZZZZZ_V35579588_.jpg500333http://ec1.images-amazon.com/images/P/0306815435.01._SCSWATCHZZ_V35579588_.jpg3020http://ec1.images-amazon.com/images/P/0306815435.01._SCTHUMBZZZ_V35579588_.jpg7550http://ec1.images-amazon.com/images/P/0306815435.01._SCMZZZZZZZ_V35579588_.jpg160107http://ec1.images-amazon.com/images/P/0306815435.01._SCLZZZZZZZ_V35579588_.jpg500333Justin MarozziPaperback9209780306815430New Ed03068154351800USD$18.00Perseus Books Group1480Book2007-03-30Perseus Books GroupPerseus Books GroupTamerlane: Sword of Islam, Conqueror of the World1224USD$12.2410001885221770http://www.amazon.com/gp/redirect.html%3FASIN=1885221770%26tag=ws%26lcode=sp1%26cID=2025%26ccmID=165953%26location=/o/ASIN/1885221770%253FSubscriptionId=0HP1WHME000749APYWR21135641http://ec1.images-amazon.com/images/P/1885221770.01._SCTHUMBZZZ_V1056534986_.jpg6040http://ec1.images-amazon.com/images/P/1885221770.01._SCMZZZZZZZ_V1056534986_.jpg14093http://ec1.images-amazon.com/images/P/1885221770.01._SCLZZZZZZZ_V1056534986_.jpg475317http://ec1.images-amazon.com/images/P/1885221770.01._SCTHUMBZZZ_V1056534986_.jpg6040http://ec1.images-amazon.com/images/P/1885221770.01._SCMZZZZZZZ_V1056534986_.jpg14093http://ec1.images-amazon.com/images/P/1885221770.01._SCLZZZZZZZ_V1056534986_.jpg475317Roy StierPaperback920978188522177318852217701695USD$16.95Bookpartners13047990092606Book1998-09BookpartnersBookpartnersTamerlane: The Ultimate Warrior870USD$8.702295USD$22.950410Book DescriptionFrom humble beginnings, Tamerlane, the ancient Turki-Mongol conqueror, rose to become the scourge of his time and changed the course of history. <P>The name Tamerlane runs the gamut of human emotions, evoking in many a revulsion for the devil incarnate, in others, an appreciation for the benefactor of millions. <P>By using accounts from Tamerlane's detractors and his admirers, Roy Stier has captured an amazing story that gives credence to the old adage, "truth is stranger than fiction." <P>Tamerlane, the Ultimate Warrior is presented as a fascinating series of events and captures the reader in the first comprehensive view of this historical figure who dominated Asia and made Europe tremble.""" if __name__ == '__main__': main() ZSI-2.1-a1/test/wsdl2py/servers/0000755000175100017510000000000010712455110014566 5ustar zsizsiZSI-2.1-a1/test/wsdl2py/servers/DateService.py0000755000175100017510000000434110641306321017343 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, time from ZSI.ServiceContainer import AsServer from DateService_server import simple_Date_Service as _DateService class Service(_DateService): def soap_getCurrentDate(self, ps): request,response = _DateService.soap_getCurrentDate(self, ps) response.Today = today = response.new_today() request._input _SetCurrentDate(today) return request,response def soap_getDate(self, ps): request,response = _DateService.soap_getDate(self, ps) response.Day = day = response.new_day() _SetDay(day, offset=request.Offset, date=request.Someday) return request,response ## ADDED WORKER CODE def _SetCurrentDate(today): dt = time.localtime(time.time()) today.Year = dt[0] today.Month = dt[1] today.Day = dt[2] today.Hour = dt[3] today.Minute = dt[4] today.Second = dt[5] today.Weekday = dt[6] today.DayOfYear = dt[7] today.Dst = dt[8] def _SetDay(someDay, offset=None, date=None): sec = 3600 * 24 ## seconds/hour * 24h providedDate_tuple = (date._year, date._month, date._day, date._hour, date._minute, date._second, date._weekday, date._dayOfYear, date._dst) providedDate_sec = time.mktime(providedDate_tuple) offset_sec = sec * offset newDate_sec = providedDate_sec + offset_sec newDate_tuple = time.localtime(newDate_sec) if not offset: offset = 0 if not date: raise RuntimeError, "Date is required" someDay._year = newDate_tuple[0] someDay._month = newDate_tuple[1] someDay._day = newDate_tuple[2] someDay._hour = newDate_tuple[3] someDay._minute = newDate_tuple[4] someDay._second = newDate_tuple[5] someDay._weekday = newDate_tuple[6] someDay._dayOfYear = newDate_tuple[7] someDay._dst = newDate_tuple[8] return someDay if __name__ == "__main__" : port = int(sys.argv[1]) AsServer(port, (Service('test'),)) ZSI-2.1-a1/test/wsdl2py/servers/SquareService.py0000755000175100017510000000131110641306321017720 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys import SquareService_server as Square from ZSI.ServiceContainer import AsServer class Service(Square.SquareService): def soap_getSquare(self, ps): request,response = Square.SquareService.soap_getSquare(self, ps) response._return = self.getSquare(request._x) return request,response def getSquare(self, x): return x**2 if __name__ == "__main__" : port = int(sys.argv[1]) AsServer(port, (Service('test'),)) ZSI-2.1-a1/test/wsdl2py/servers/BasicServer.py0000644000175100017510000000134610641306321017354 0ustar zsizsi#!/usr/bin/env python import sys from ZSI.ServiceContainer import AsServer from BasicServer_server import BasicServer """ BasicServer example service WSDL: BasicComm.wsdl """ class Service(BasicServer): def soap_Basic(self, ps): request,response = BasicServer.soap_Basic(self, ps) response._BasicResult = request._BasicIn return request,response def soap_BasicOneWay(self, ps): request,response = BasicServer.soap_BasicOneWay(self, ps) if request._BasicIn == 'fault': # return a soap:fault raise RuntimeError, 'you wanted a fault?' return request,response if __name__ == "__main__" : port = int(sys.argv[1]) AsServer(port, (Service('test'),)) ZSI-2.1-a1/test/wsdl2py/servers/WhiteMesa.py0000755000175100017510000000403310641306321017031 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys from ZSI.ServiceContainer import AsServer from RPC_Literal_TestDefinitions_server import WhiteMesaSoapRpcLitTestSvc as WhiteMesa """ WhiteMesa web service for rpc/literal tests. WSDL: http://www.whitemesa.net/wsdl/test-rpc-lit.wsdl """ class Service(WhiteMesa): def soap_echoStruct(self, ps): request,response = WhiteMesa.soap_echoStruct(self, ps) return request,response def soap_echoStructArray(self, ps): request,response = WhiteMesa.soap_echoStructArray(self, ps) return request,response def soap_echoStructAsSimpleTypes(self, ps): request,response = WhiteMesa.soap_echoStructAsSimpleTypes(self, ps) return request,response def soap_echoSimpleTypesAsStruct(self, ps): request,response = WhiteMesa.soap_echoSimpleTypesAsStruct(self, ps) return request,response def soap_echoNestedStruct(self, ps): request,response = WhiteMesa.soap_echoNestedStruct(self, ps) return request,response def soap_echoNestedArray(self, ps): request,response = WhiteMesa.soap_echoNestedArray(self, ps) return request,response def soap_echoStringArray(self, ps): request,response = WhiteMesa.soap_echoStringArray(self, ps) return request,response def soap_echoIntegerArray(self, ps): request,response = WhiteMesa.soap_echoIntegerArray(self, ps) return request,response def soap_echoBoolean(self, ps): request,response = WhiteMesa.soap_echoBoolean(self, ps) response._return = request._inputBoolean return request,response def soap_echoString(self, ps): request,response = WhiteMesa.soap_echoString(self, ps) return request,response if __name__ == "__main__" : port = int(sys.argv[1]) AsServer(port, (Service('test'),)) ZSI-2.1-a1/test/wsdl2py/servers/FinancialService.py0000755000175100017510000000216710641306321020356 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys from FinancialService_server import * from ZSI.ServiceContainer import AsServer class Service(FinancialService): def soap_getPV(self, ps): request,response = FinancialService.soap_getPV(self, ps) args = request # Worker code: Actual present value calculation t = 0 PV = 0.0 for CF in args._CFSequence._CF: PV += (CF or 0.0) * ((args._irate / 100.0 + 1) ** (-t)) t += 1 #print "Present value is: ", PV # assign return values to response object #class SimpleTypeWrapper(float): typecode = getPVResponseWrapper() # WARNING specify value eg. SimpleTypeWrapper(1) #response = SimpleTypeWrapper(PV) response = response.__class__(PV) return request,response if __name__ == "__main__" : port = int(sys.argv[1]) AsServer(port, (Service('test'),)) ZSI-2.1-a1/test/wsdl2py/servers/EchoServer.py0000755000175100017510000000517710656174245017240 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys from ZSI import ServiceContainer, Fault from ZSI.ServiceContainer import AsServer, ServiceSOAPBinding from EchoServer_server import EchoServer from ZSI.fault import Fault, ZSIFaultDetail def WSDLFaultFromException(ex, inheader, tb=None, actor=None): '''Return a Fault object created from a Python exception. SOAP-ENV:Server Processing Failure ''' tracetext = None if tb: try: lines = '\n'.join(['%s:%d:%s' % (name, line, func) for name, line, func, text in traceback.extract_tb(tb)]) except: pass else: tracetext = lines exceptionName = "" try: exceptionName = ":".join([ex.__module__, ex.__class__.__name__]) except: pass if isinstance(ex, Fault): return ex elt = ZSIFaultDetail(string=exceptionName + "\n" + str(ex), trace=tracetext) if inheader: detail, headerdetail = None, elt else: detail, headerdetail = elt, None return Fault(Fault.Server, 'Processing Failure', actor, detail, headerdetail) ServiceContainer.FaultFromException = WSDLFaultFromException class Service(EchoServer): def soap_Echo(self, ps, **kw): request,response = EchoServer.soap_Echo(self, ps, **kw) response.EchoResult = request.EchoIn #return request,response #raise RuntimeError, 'hi' #raise Fault(911, "EMERGENCY", None, response) return request,response def twisted_main(port): from twisted.internet import reactor from twisted.application import service, internet from twisted.web.resource import Resource from twisted.web.server import Site root = Resource() root.putChild('test', Service()) reactor.listenTCP(port, Site(root)) def main(): port = int(sys.argv[1]) if issubclass(EchoServer, ServiceSOAPBinding): AsServer(port, (Service('test'),)) return #from ZSI.twisted.WSresource import WSResource #if issubclass(EchoServer, WSResource): from twisted.internet import reactor reactor.callWhenRunning(twisted_main, port) reactor.run() if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/servers/EchoWSAddr200403Server.py0000755000175100017510000000220210656174245020740 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys from ZSI.ServiceContainer import AsServer from EchoWSAddr200403Server_server import EchoWSAddr200403Server as EchoServer from ZSI.schema import GTD """ EchoServer example service WSDL: ../../samples/Echo/Echo.wsdl """ EndpointReferenceType = GTD('http://schemas.xmlsoap.org/ws/2004/03/addressing','EndpointReferenceType') class WSAService(EchoServer): def wsa_Echo(self, ps, address): request,response = EchoServer.wsa_Echo(self, ps, address) response.EchoResult = request.EchoIn if isinstance(response.EchoResult, EndpointReferenceType): addr1 = response.EchoResult for a in address.Any: if a not in addr1.ReferenceProperties.Any: raise RuntimeError, 'EPRs dont match' return request,response if __name__ == "__main__" : port = int(sys.argv[1]) AsServer(port, (WSAService('test'),)) ZSI-2.1-a1/test/wsdl2py/test_VIM.py0000644000175100017510000001046210647240777015166 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException, ParsedSoap, SoapWriter """ Unittest WSDL: wsdl/vim.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(VIMTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(VIMTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(VIMTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(VIMTestCase, 'test_')) return suite class VIMTestCase(ServiceTestCase): name = "test_VIM" client_file_name = "VIM_client.py" types_file_name = "VIM_types.py" server_file_name = "VIM_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('--lazy') self.wsdl2py_args.append('-b') def test_local_substitute_SessionManager(self): # BUG [ 1755740 ] Multiple calls to the same method MSG = """ group-d1 propertyCollector VMware VirtualCenter VMware VirtualCenter 2.0.1 build-32042 VMware, Inc. 2.0.1 32042 INTL 000 win32-x86 vpx VirtualCenter 2.0.0 VpxSettings UserDirectory SessionManager AuthorizationManager PerfMgr ScheduledTaskManager AlarmManager EventManager TaskManager CustomizationSpecManager CustomFieldsManager DiagMgr LicenseManager SearchIndex """ # Parse it out ps = ParsedSoap(MSG) pyobj = ps.Parse( self.client_module.RetrieveServiceContentResponseMsg.typecode ) sessionMgr = pyobj.Returnval.SessionManager # Serialize SessionManager in different context msg = self.client_module.LogoutRequestMsg() msg._this = sessionMgr SoapWriter().serialize(msg) # Parse it out: was failing # ZSI.EvaluateException: Element "__this" missing from complexType # [Element trace: /soapenv:Envelope/soapenv:Body/RetrieveServiceContentResponse/returnval] ps = ParsedSoap(MSG) pyobj = ps.Parse( self.client_module.RetrieveServiceContentResponseMsg.typecode ) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_TerraService.py0000755000175100017510000002266110057476476017142 0ustar zsizsi#!/usr/bin/env python ############################################################################ # David W. Robertson, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import ServiceTestCase, ServiceTestSuite import re from ZSI import EvaluateException """ Unittest for contacting the TerraService Web service. WSDL: http://terraservice.net/TerraService.asmx?WSDL """ CONFIG_FILE = 'config.txt' CONFIG_SECTION = 'complex_types' SERVICE_NAME = 'TerraService' PORT_NAME = 'TerraServiceSoap' EXCEPTION_STRING_SERIALIZE = r"Serializing ConvertPlaceToLonLatPt xmlns=\"http://terraserver-usa.com/terraserver/\"._place, Exception Serializing place xmlns=\"http://terraserver-usa.com/terraserver/\"._City, AttributeError 'int' object has no attribute \'replace\'" SERIALIZE_PATTERN = re.compile(EXCEPTION_STRING_SERIALIZE) class TerraServiceTest(ServiceTestCase): """Test case for TerraService Web service """ name = "test_TerraService" def test_ConvertPlaceToLonLatPt(self): operationName = 'ConvertPlaceToLonLatPt' request = self.getInputMessageInstance(operationName) request._place = self._moduleDict[self._typeModuleName].ns1.Place_Def() request._place._City = 'Oak Harbor' request._place._State = 'Washington' request._place._Country = 'United States' response = self.RPC(operationName, request) def test_ConvertLonLatPtToNearestPlace(self): operationName = 'ConvertLonLatPtToNearestPlace' request = self.getInputMessageInstance(operationName) request._place = self._moduleDict[self._typeModuleName].ns1.Place_Def() request._point = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._point._Lon = -122.643 request._point._Lat = 48.297 response = self.RPC(operationName, request) def test_ConvertLonLatPtToUtmPt(self): operationName = 'ConvertLonLatPtToUtmPt' request = self.getInputMessageInstance(operationName) request._point = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._point._Lon = -122.643 request._point._Lat = 48.297 response = self.RPC(operationName, request) def test_ConvertUtmPtToLonLatPt(self): operationName = 'ConvertUtmPtToLonLatPt' request = self.getInputMessageInstance(operationName) request._utm = self._moduleDict[self._typeModuleName].ns1.UtmPt_Def() request._utm._X = 526703.512403 request._utm._Y = 5348595.96493 request._utm._Zone = 10 response = self.RPC(operationName, request) def test_CountPlacesInRect(self): operationName = 'CountPlacesInRect' request = self.getInputMessageInstance(operationName) request._upperleft = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._upperleft._Lon = -122.647 request._upperleft._Lat = 48.293 request._lowerright = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._lowerright._Lon = request._upperleft._Lon + 1.0 request._lowerright._Lat = request._upperleft._Lon - 1.0 request._ptype = "HillMountain" response = self.RPC(operationName, request) def test_GetAreaFromPt(self): operationName = 'GetAreaFromPt' request = self.getInputMessageInstance(operationName) request._center = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._center._Lon = -122.647 request._center._Lat = 48.293 request._theme = 'Topo' request._scale = "Scale2m" request._displayPixWidth = 2 request._displayPixHeight = 2 response = self.RPC(operationName, request) def test_GetAreaFromRect(self): operationName = 'GetAreaFromRect' request = self.getInputMessageInstance(operationName) request._upperLeft = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._upperLeft._Lon = -122.647 request._upperLeft._Lat = 48.293 request._lowerRight = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._lowerRight._Lon = request._upperLeft._Lon + 1.0 request._lowerRight._Lat = request._upperLeft._Lat - 1.0 request._theme = 'Topo' request._scale = "Scale2m" response = self.RPC(operationName, request) def test_GetAreaFromTileId(self): operationName = 'GetAreaFromTileId' request = self.getInputMessageInstance(operationName) id = self._moduleDict[self._typeModuleName].ns1.TileId_Def() id._Theme = 'Topo' id._Scale = "Scale2m" id._Scene = 8 id._X = 20 id._y = 20 request._id = id request._displayPixWidth = 2 request._displayPixHeight = 2 response = self.RPC(operationName, request) def test_GetLatLonMetrics(self): operationName = 'GetLatLonMetrics' request = self.getInputMessageInstance(operationName) request._point = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._point._Lon = -122.647 request._point._Lat = 48.293 response = self.RPC(operationName, request) # derived type (enum) problem # skipping it for now # derived type (enum) problem # also inconsistent timeout problem for this call def test_GetPlaceListInRect(self): operationName = 'GetPlaceListInRect' request = self.getInputMessageInstance(operationName) request._upperleft = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._upperleft._Lon = -123.0 request._upperleft._Lat = 44.0 request._lowerright = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() # needs to be small, otherwise different items # returned each time request._lowerright._Lon = -122.8 request._lowerright._Lat = 43.8 request._ptype = "HillMountain" request._MaxItems = 3 response = self.RPC(operationName, request) def test_GetTheme(self): operationName = 'GetTheme' request = self.getInputMessageInstance(operationName) request._theme = 'Topo' response = self.RPC(operationName, request) def test_GetTile(self): operationName = 'GetTile' request = self.getInputMessageInstance(operationName) request._id = self._moduleDict[self._typeModuleName].ns1.TileId_Def() request._id._Theme = 'Topo' request._id._Scale = 'Scale2m' request._id._Scene = 8 request._id._X = 20 request._id._Y = 20 response = self.RPC(operationName, request) def test_GetTileMetaFromLonLatPt(self): operationName = 'GetTileMetaFromLonLatPt' request = self.getInputMessageInstance(operationName) request._theme = 'Topo' request._point = self._moduleDict[self._typeModuleName].ns1.LonLatPt_Def() request._point._Lon = -122.64 request._point._Lat = 48.29 request._scale = "Scale4m" response = self.RPC(operationName, request) def test_GetTileMetaFromTileId(self): operationName = 'GetTileMetaFromTileId' request = self.getInputMessageInstance(operationName) request._id = self._moduleDict[self._typeModuleName].ns1.TileId_Def() request._id._Theme = 'Topo' request._id._Scale = 'Scale2m' request._id._Scene = 8 request._id._X = 20 request._id._Y = 20 response = self.RPC(operationName, request) class TerraServiceTestFailures(ServiceTestCase): name = "test_TerraService" def test_ConvertPlaceToLonLatPt_x1(self): """ This test should fail """ operationName = 'ConvertPlaceToLonLatPt' request = self.getInputMessageInstance(operationName) request._place = self._moduleDict[self._typeModuleName].ns1.Place_Def() request._place._City = 1 request._place._State = 'Washington' request._place._Country = 'United States' try: response = self.RPC(operationName, request) except Exception, msg: exceptionString = str(msg) if SERIALIZE_PATTERN.match(exceptionString): pass else: raise def test_GetPlaceFacts(self): operationName = 'GetPlaceFacts' request = self.getInputMessageInstance(operationName) request._place = self._moduleDict[self._typeModuleName].ns1.Place_Def() request._place._City = 'Seattle' request._place._State = 'Washington' request._place._Country = 'United States' try: response = self.RPC(operationName, request) except EvaluateException, ex: pass def test_GetPlaceList(self): operationName = 'GetPlaceList' request = self.getInputMessageInstance(operationName) request._placeName = 'New York' request._MaxItems = 5 request._imagePresence = 0 try: response = self.RPC(operationName, request) except EvaluateException, ex: pass def makeTestSuite(): suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TerraServiceTest, 'test_')) suite.addTest(unittest.makeSuite(TerraServiceTestFailures, 'test_')) return suite if __name__ == "__main__" : unittest.TestProgram(defaultTest="makeTestSuite") ZSI-2.1-a1/test/wsdl2py/runTests.py0000755000175100017510000000667210622665373015332 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See Copyright for copyright notice! ########################################################################### import unittest, warnings, os from ZSI import version from ZSI.wstools.logging import gridLog from ServiceTest import main, CONFIG_PARSER, DOCUMENT, LITERAL, BROKE, TESTS os.environ['GRIDLOG_ON'] = '1' os.environ['GRIDLOG_DEST'] = "gridlog-udp://portnoy.lbl.gov:15100" # General targets def dispatch(): """Run all dispatch tests""" return _dispatchTestSuite(broke=False) def local(): """Run all local tests""" return _localTestSuite(broke=False) def net(): """Run all network tests""" return _netTestSuite(broke=False) def all(): """Run all tests""" return _allTestSuite(broke=False) # Specialized binding targets def docLitTestSuite(): """Run all doc/lit network tests""" return _netTestSuite(broke=False, document=True, literal=True) def rpcLitTestSuite(): """Run all rpc/lit network tests""" return _netTestSuite(broke=False, document=False, literal=True) def rpcEncTestSuite(): """Run all rpc/enc network tests""" return _netTestSuite(broke=False, document=False, literal=False) # Low level functions def _allTestSuite(document=None, literal=None, broke=None): return _makeTestSuite('all', document, literal, broke) def _netTestSuite(document=None, literal=None, broke=None): return _makeTestSuite('net', document, literal, broke) def _localTestSuite(document=None, literal=None, broke=None): return _makeTestSuite('local', document, literal, broke) def _dispatchTestSuite(document=None, literal=None, broke=None): return _makeTestSuite('dispatch', document, literal, broke) def _makeTestSuite(test, document=None, literal=None, broke=None): """Return a test suite containing all test cases that satisfy the parameters. None means don't check. Parameters: test -- "net" run network tests, "local" run local tests, "dispatch" run dispatch tests, "all" run all tests. document -- None, True, False literal -- None, True, False broke -- None, True, False """ assert test in ['net', 'local', 'dispatch', 'all'],( 'test must be net, local, dispatch, or all') cp = CONFIG_PARSER testSections = [] sections = [\ 'rpc_encoded' , 'rpc_encoded_broke', 'rpc_literal', 'rpc_literal_broke', 'rpc_literal_broke_interop', 'doc_literal', 'doc_literal_broke', 'doc_literal_broke_interop', ] boo = cp.getboolean for s,d,l,b in map(\ lambda sec: \ (sec, (None,boo(sec,DOCUMENT)), (None,boo(sec,LITERAL)), (None,boo(sec,BROKE))), sections): if document in d and literal in l and broke in b: testSections.append(s) suite = unittest.TestSuite() for section in testSections: moduleList = cp.get(section, TESTS).split() for module in map(__import__, moduleList): def _warn_empty(): warnings.warn('"%s" has no test "%s"' %(module, test)) return unittest.TestSuite() s = getattr(module, test, _warn_empty)() suite.addTest(s) return suite if __name__ == "__main__": gridLog(prog="runTests.py", zsi="v%d.%d.%d" % version.Version, event="zsi.test.wsdl2py.runTests.ping") main() ZSI-2.1-a1/test/wsdl2py/test_BasicComm.py0000644000175100017510000001002310557721300016343 0ustar zsizsi#!/usr/bin/env python import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException, Fault from ConfigParser import ConfigParser, NoSectionError, NoOptionError """ Unittest WSDL: BasicComm.wsdl """ CONFIG_FILE = 'config.txt' CONFIG_PARSER = ConfigParser() SECTION_DISPATCH = 'dispatch' CONFIG_PARSER.read(CONFIG_FILE) # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(BasicCommTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(BasicCommTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(BasicCommTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(BasicCommTestCase, 'test_')) return suite class BasicCommTestCase(ServiceTestCase): name = "test_BasicComm" client_file_name = "BasicServer_client.py" types_file_name = "BasicServer_types.py" server_file_name = "BasicServer_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_Basic(self): msg = self.client_module.BasicRequest() rsp = self.client_module.BasicResponse() def test_dispatch_Basic(self): loc = self.client_module.BasicServerLocator() port = loc.getBasicServer(**self.getPortKWArgs()) msg = self.client_module.BasicRequest() msg._BasicIn = 'bla bla bla' rsp = port.Basic(msg) self.failUnless(rsp._BasicResult == msg._BasicIn, "Bad Echo") # test whether we get an HTTP response on a message with # no soap response. import httplib msg = u""" bla bla bla """.encode('utf-8') headers = {"Content-type": 'text/xml; charset="utf-8"', 'Content-Length': str(len(msg))} host = CONFIG_PARSER.get(SECTION_DISPATCH, 'host') port = CONFIG_PARSER.get(SECTION_DISPATCH, 'port') path = CONFIG_PARSER.get(SECTION_DISPATCH, 'path') conn = httplib.HTTPConnection("%s:%s" % (host, port)) conn.request('POST', '/' + path, msg, headers) try: response = conn.getresponse() except httplib.BadStatusLine: conn.close() self.fail('No HTTP Response') conn.close() self.failUnless(response.status == 200, 'Wrong HTTP Result') def test_dispatch_BasicOneWay(self): loc = self.client_module.BasicServerLocator() port = loc.getBasicServer(**self.getPortKWArgs()) msg = self.client_module.BasicOneWayRequest() msg.BasicIn = 'bla bla bla' rsp = port.BasicOneWay(msg) self.failUnless(rsp == None, "Bad One-Way") def test_dispatch_BasicOneWay_fault(self): """server will send back a soap:fault """ loc = self.client_module.BasicServerLocator() port = loc.getBasicServer(**self.getPortKWArgs()) msg = self.client_module.BasicOneWayRequest() msg.BasicIn = 'fault' self.failUnlessRaises(FaultException, port.BasicOneWay, msg) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_FinancialService.py0000755000175100017510000000406010551530755017730 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! # Tests for Holger's Square Service # ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite, TestException """ Unittest for contacting the SquareService rpc/literal tests. From the paper "Interoperable WSDL/SOAP web services introduction: Python ZSI, Excel XP, gSOAP C/C++ & Applix SS", Holger Joukl WSDL: SquareService.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_')) return suite class Test(ServiceTestCase): """Test case for Holger's SquareService """ name = "test_FinancialService" client_file_name = "FinancialService_client.py" types_file_name = "FinancialService_types.py" server_file_name = "FinancialService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_dispatch_getPV(self): loc = self.client_module.FinancialServiceLocator() port = loc.getFinancialService_Port(**self.getPortKWArgs()) msg = self.client_module.getPVRequest() msg.Irate = 4 msg.CFSequence = cfs = msg.new_CFSequence() cfs.CF = [100.0,5.0,5.0,105.0] rsp = port.getPV(msg) self.failUnless(rsp == 202.775091, "Received %d" %rsp) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_AmazonS3.py0000755000175100017510000000444010547037605016161 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest, time from ServiceTest import main, ServiceTestCase, ServiceTestSuite, TestException from ZSI.schema import ElementDeclaration, GED from ZSI import ParsedSoap """ Unittest for contacting the Amazon ECommerce Service WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AmazonTestCase, 'test_')) return suite class AmazonTestCase(ServiceTestCase): """Test case for AmazonS3 web service """ name = "test_AmazonS3" client_file_name = "AmazonS3_client.py" types_file_name = "AmazonS3_types.py" server_file_name = "AmazonS3_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') self.wsdl2py_args.append('--lazy') def test_local_import(self): pass def test_net_CreateBucket(self): loc = self.client_module.AmazonS3Locator() port = loc.getAmazonS3(**self.getPortKWArgs()) msg = self.client_module.CreateBucketRequest() #msg.SubscriptionId = '0HP1WHME000749APYWR2' msg.Bucket = "HoneyPot" acl = msg.AccessControlList = msg.new_AccessControlList() grant = acl.new_Grant() acl.Grant = [grant] grant.Grantee = grant.new_Grantee() grant.Permission = grant.new_Permission("YES") msg.AWSAccessKeyId = '0HP1WHME000749APYWR2' msg.Timestamp = time.gmtime() msg.Signature = 'whatever' rsp = port.CreateBucket(msg) if __name__ == '__main__': main() ZSI-2.1-a1/test/wsdl2py/test_Sabre.py0000644000175100017510000001111110547037605015550 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException """ Unittest for contacting WSDL: http://webservices.sabre.com/wsdl/sabreXML1.0.00/res/SessionCreateRQ.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_')) return suite class ServiceTest(ServiceTestCase): """Test case for Sabre Web service """ name = "test_Sabre" client_file_name = "SessionCreateRQService_client.py" types_file_name = "SessionCreateRQService_types.py" server_file_name = "SessionCreateRQService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_net_SessionCreate(self): """ _________________________________ Mon Jan 2 13:41:22 2006 REQUEST: _________________________________ Mon Jan 2 13:41:22 2006 RESPONSE: Server: Netscape-Enterprise/6.0 Date: Mon, 02 Jan 2006 21:41:21 GMT Content-Length: 1568 Content-Type: text/xml; charset="utf-8" Soapaction: "" soap-env:Client.ConversationIdRequiredConversation id requiredcom.sabre.universalservices.base.session.SessionException: errors.session.USG_CONVERSATION_ID_REQUIRED at com.sabre.universalservices.gateway.control.SecurityInterceptor.executeOnRequest(SecurityInterceptor.java:111) at com.sabre.universalservices.base.interceptor.Interceptor.execute(Interceptor.java:113) at com.sabre.universalservices.base.interceptor.InterceptorChain.applyInterceptors(InterceptorChain.java:32) at com.sabre.universalservices.base.interceptor.InterceptorManager.process(InterceptorManager.java:116) at com.sabre.universalservices.gateway.control.WSGateway.onMessage(WSGateway.java:297) at com.sabre.universalservices.gateway.control.WSGateway.handleRequest(WSGateway.java:208) at com.sabre.universalservices.gateway.control.WSGateway.doPost(WSGateway.java:156) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.iplanet.server.http.servlet.NSServletRunner.invokeServletService(NSServletRunner.java:919) at com.iplanet.server.http.servlet.NSServletRunner.Service(NSServletRunner.java:483) E """ loc = self.client_module.SessionCreateRQServiceLocator() port = loc.getSessionCreatePortType(**self.getPortKWArgs()) msg = self.client_module.GetSessionCreateInput() msg.POS = msg.new_POS() msg.POS.Source = msg.POS.new_Source() msg.POS.Source.set_attribute_PseudoCityCode("SF") self.failUnlessRaises(FaultException, port.SessionCreateRQ, msg) #response = self._ports[0].SessionCreateRQ(msg) #response.Success #response.Warnings #response.ConversationId #response.Errors if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_DateService.py0000755000175100017510000000567010551530755016731 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! # Tests for Holger's DateService ########################################################################### import sys, unittest, time from ServiceTest import main, ServiceTestCase, ServiceTestSuite, TestException """ Unittest for contacting the DateService rpc/literal tests. From the paper "Interoperable WSDL/SOAP web services introduction: Python ZSI, Excel XP, gSOAP C/C++ & Applix SS", Holger Joukl WSDL: DateService.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_')) return suite class Test(ServiceTestCase): """Test case for Holger's DateService """ name = "test_DateService" client_file_name = "DateService_client.py" types_file_name = "DateService_types.py" server_file_name = "DateService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') #def test_local_getDate(self): # from ZSI.writer import SoapWriter def test_dispatch_getCurrentDate_getDate(self): offset = 9 loc = self.client_module.simple_Date_ServiceLocator() port = loc.getDateService_Port(**self.getPortKWArgs()) print "START" msg = self.client_module.getCurrentDateRequest() msg.Input = "Test" rsp = port.getCurrentDate(msg) today = rsp.Today today.Month today.Day today.Hour today.Minute today.Second today.Weekday today.DayOfYear today.Dst dateRequest = self.client_module.getDateRequest() # We use the current date as input to getDate dateRequest.Someday = today dateRequest.Offset = offset date = port.getDate(dateRequest) print '\n\nRESULT' print '%10s = %s' % ('today', _make_asctime(today)) print '%6s + %d = %s' % ('today', dateRequest.Offset, _make_asctime(date.Day)) def _make_asctime(date_object): timeTuple = (date_object._year, date_object._month, date_object._day, date_object._hour, date_object._minute, date_object._second, date_object._weekday, date_object._dayOfYear, date_object._dst ) return time.asctime(timeTuple) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/.cvsignore0000644000175100017510000000000610204473151015072 0ustar zsizsistubs ZSI-2.1-a1/test/wsdl2py/test_NVOAdmin.py0000644000175100017510000000645510622701303016131 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import SoapWriter, ParsedSoap, TC, FaultException from ZSI import _child_elements, _get_element_nsuri_name, _is_element from ZSI.schema import ElementDeclaration from ZSI.wstools.Namespaces import SCHEMA from xml.dom.ext.reader import PyExpat from xml.dom import Node """ Unittest for NVO Admin. WSDL: """ #from ZSI.wstools.logging import setBasicLoggerDEBUG; setBasicLoggerDEBUG() class schema(ElementDeclaration, TC.XML): """Create an element for dealing with """ schema = SCHEMA.XSD3 literal = "schema" def __init__(self, *args, **kw): # minOccurs=1, maxOccurs=1, nillable=False, encoded=kw.get("encoded") TC.XML.__init__(self, pname=(SCHEMA.XSD3, "schema"), wrapped=False, **kw) # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_')) return suite class NVOAdmin(ServiceTestCase): """Test case for NVO Admin """ name = "test_NVOAdmin" client_file_name = "RegistryAdmin_client.py" types_file_name = "RegistryAdmin_types.py" #server_file_name = "RegistryAdmin_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_serialize_schema(self): from ZSI import SoapWriter from ZSI import _child_elements from xml.dom.ext.reader import PyExpat msg = self.client_module.DSQueryRegistrySoapOut() msg.DSQueryRegistryResult = msg.new_DSQueryRegistryResult() msg.DSQueryRegistryResult.Any = 'hi' input = open('wsdl/nvo-admin.wsdl').read() reader = PyExpat.Reader() dom = reader.fromString(input) dnode = _child_elements(dom)[0] tnode = _child_elements(dnode)[0] snode = _child_elements(tnode)[0] msg.DSQueryRegistryResult.Schema = snode sw = SoapWriter() sw.serialize(msg) soap = str(sw) print soap ps = ParsedSoap(soap) pyobj = ps.Parse(msg.typecode) self.failUnlessEqual(pyobj.DSQueryRegistryResult.Any, msg.DSQueryRegistryResult.Any) self.failUnless(_is_element(pyobj.DSQueryRegistryResult.Schema)) print _get_element_nsuri_name(pyobj.DSQueryRegistryResult.Schema) self.failUnlessEqual(_get_element_nsuri_name(pyobj.DSQueryRegistryResult.Schema), (u'http://www.w3.org/2001/XMLSchema', u'schema')) ServiceTest = NVOAdmin if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_SquareService.py0000755000175100017510000000415410551530755017310 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! # Tests for Holger's Square Service # ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite, TestException """ Unittest for contacting the SquareService rpc/literal tests. From the paper "Interoperable WSDL/SOAP web services introduction: Python ZSI, Excel XP, gSOAP C/C++ & Applix SS", Holger Joukl WSDL: SquareService.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(Test, 'test_')) return suite class Test(ServiceTestCase): """Test case for Holger's SquareService """ name = "test_SquareService" client_file_name = "SquareService_client.py" types_file_name = "SquareService_types.py" server_file_name = "SquareService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_getSquare(self): from ZSI.writer import SoapWriter def test_dispatch_getSquare(self): loc = self.client_module.SquareServiceLocator() port = loc.getSquarePort(**self.getPortKWArgs()) msg = self.client_module.getSquareRequest() msg.X = 4.0 rsp = port.getSquare(msg) self.failUnless(rsp.Return == msg.X**2, "Square Failed: got %d, expecting %d" %(rsp.Return,msg.X**2)) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/README0000644000175100017510000000625710441105105013762 0ustar zsizsi############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### Note that since all services are not always available, connection timeouts and HTTP errors are not treated as test failures. Client and Server stubs will be generated for each test, but the Server stubs will are runtime tested only if "dispatch" is specified and an executable is provided via the "servers" section. To run all "working" tests: %./runTests.py To run only "local" tests: %./runTests.py local To run only "network" tests: %./runTests.py net To run only tests against the wsdl2dispatch tool: %./runTests.py dispatch Convention Modules: All test modules should define these targets: "all" -- run all tests "dispatch" -- run only "test_dispatch*" tests "local" -- run only "test_local*" tests "net" -- run only "test_net*" tests Convention TestCase: All TestCases should adhere to these conventions. methods: "test_net*" -- only tests run against a network available endpoint, which is specified in the WSDL location address information item. "test_local*" -- only local tests, no networking. "test_dispatch*" -- only tests run against a local endpoint, this is configured and forked by the unittest framework. Will override the WSDL location address information item with information from the dispatch configuration section. class attributes: client_file_name -- if specified, "client_module" attribute will reference module. types_file_name -- if specified, "types_module" attribute will reference module. server_file_name -- if specified, "server_module" attribute will reference module. Directories: "stubs" -- Generated code, regenerated everytime a test is run. "servers" -- Server code, this is an implemenation of service and must be an executable. It is also hand coded. Used for "dispatch" tests. Configuration: Edit "config.txt", short descriptions are provided inline. [configuration] The "configuation" section for global configuration. "tracefile" -- show XML of individual messages as serialized/parsed. "debug" -- turn on verbose debugging information. "skip" -- skip generation (wsdl2py and wsdl2dispatch) "twisted" -- use twisted.web.client [dispatch] The "configuration" section for dispatch tests. "host" -- for local tests the hostname where server will be ran. "port" -- for local tests the port where server will be ran. "path" -- path where service is located "other items" -- executable "ServiceContainer" which is configured with the required service instance. [rpc_encoded],[rpc_encoded_broke],[doc_encoded],[doc_encoded_broke] [rpc_literal],[rpc_literal_broke],[doc_literal],[doc_literal_broke] Sections to categorize all tests... All these sections contain a "test" option, this is a whitespace separated list of all the tests that belong in a particular section. [WSDL] URL to WSDL for particular service. ZSI-2.1-a1/test/wsdl2py/test_InfoBil.py0000644000175100017510000000277510547037605016056 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException """ Unittest WSDL: http://javatest2.infodata.se/webservices/services/Infobil?wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_')) return suite class TestCase(ServiceTestCase): name = "test_InfoBil" client_file_name = "InfoBilServiceService_client.py" types_file_name = "InfoBilServiceService_types.py" server_file_name = "InfoBilServiceService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_import(self): pass if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_SubstitutionGroup.py0000644000175100017510000000464210566713527020265 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest, time from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException from ZSI.TC import _get_global_element_declaration as GED from ZSI.writer import SoapWriter from ZSI.parse import ParsedSoap """ Unittest for substitutionGroup [ ] XSD: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_')) return suite class SubstitutionGroupTestCase(ServiceTestCase): name = "test_SubstitutionGroup" types_file_name = "test_SubstitutionGroup_xsd_types.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') self.wsdl2py_args.append('-x') def test_local_attribute1(self): """ """ self.types_module xml = """ from base from basefrom child""" ps = ParsedSoap(xml, envelope=False) p1 = ps.Parse(GED("urn:subGroup:types", "holder")) b1 = p1.BaseElt[0] c1 = p1.BaseElt[1] sw = SoapWriter(envelope=False) sw.serialize(p1) ps = ParsedSoap(str(sw), envelope=False) p2 = ps.Parse(GED("urn:subGroup:types", "holder")) b2 = p2.BaseElt[0] c2 = p2.BaseElt[1] self.failUnlessEqual(b1.Base, b2.Base) self.failUnlessEqual(c1.Base, c2.Base) self.failUnlessEqual(c1.Child, c2.Child) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_Echo.py0000644000175100017510000000354510547037605015406 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException """ Unittest WSDL: ../../samples/Echo/Echo.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_')) return suite class EchoTestCase(ServiceTestCase): name = "test_Echo" client_file_name = "EchoServer_client.py" types_file_name = "EchoServer_types.py" server_file_name = "EchoServer_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_Echo(self): msg = self.client_module.EchoRequest() rsp = self.client_module.EchoResponse() def test_dispatch_Echo(self): loc = self.client_module.EchoServerLocator() port = loc.getEchoServer(**self.getPortKWArgs()) msg = self.client_module.EchoRequest() msg.EchoIn = 'bla bla bla' rsp = port.Echo(msg) self.failUnless(rsp.EchoResult == msg.EchoIn, "Bad Echo") if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/ServiceTest.py0000644000175100017510000003001510656174245015724 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### from compiler.ast import Module import StringIO, copy, getopt import os, sys, unittest, urlparse, signal, time, warnings, subprocess from ConfigParser import ConfigParser, NoSectionError, NoOptionError from ZSI.wstools.TimeoutSocket import TimeoutError from ZSI.generate import commands """Global Variables: CONFIG_FILE -- configuration file CONFIG_PARSER -- ConfigParser instance DOCUMENT -- test section variable, specifying document style. LITERAL -- test section variable, specifying literal encodings. BROKE -- test section variable, specifying broken test. TESTS -- test section variable, whitespace separated list of modules. SECTION_CONFIGURATION -- configuration section, turn on/off debuggging. TRACEFILE -- file class instance. TOPDIR -- current working directory MODULEDIR -- stubs directory PORT -- port of local container HOST -- address of local container SECTION_SERVERS -- services to be tested, values are paths to executables. """ CONFIG_FILE = 'config.txt' CONFIG_PARSER = ConfigParser() DOCUMENT = 'document' LITERAL = 'literal' BROKE = 'broke' TESTS = 'tests' SECTION_CONFIGURATION = 'configuration' SECTION_DISPATCH = 'dispatch' TRACEFILE = sys.stdout TOPDIR = os.getcwd() MODULEDIR = os.path.join(TOPDIR, 'stubs') SECTION_SERVERS = 'servers' CONFIG_PARSER.read(CONFIG_FILE) DEBUG = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'debug') SKIP = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'skip') TWISTED = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'twisted') LAZY = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'lazy') OUTPUT = CONFIG_PARSER.get(SECTION_CONFIGURATION, 'output') or sys.stdout if DEBUG: from ZSI.wstools.logging import setBasicLoggerDEBUG setBasicLoggerDEBUG() sys.path.append('%s/%s' %(os.getcwd(), 'stubs')) ENVIRON = copy.copy(os.environ) ENVIRON['PYTHONPATH'] = ENVIRON.get('PYTHONPATH', '') + ':' + MODULEDIR def _SimpleMain(): """Gets tests to run from configuration file. """ unittest.TestProgram(defaultTest="all") main = _SimpleMain def _TwistedMain(): """Gets tests to run from configuration file. """ from twisted.internet import reactor reactor.callWhenRunning(_TwistedTestProgram, defaultTest="all") reactor.run(installSignalHandlers=0) if TWISTED: main = _TwistedMain def _LaunchContainer(cmd): ''' Parameters: cmd -- executable, sets up a ServiceContainer or ? ''' host = CONFIG_PARSER.get(SECTION_DISPATCH, 'host') port = CONFIG_PARSER.get(SECTION_DISPATCH, 'port') try: process = subprocess.Popen(['python', cmd, port], env=ENVIRON) except: print >>sys.stderr, 'error executing: %s' %cmd raise time.sleep(3) return process class _TwistedTestProgram(unittest.TestProgram): def runTests(self): from twisted.internet import reactor if self.testRunner is None: self.testRunner = unittest.TextTestRunner(verbosity=self.verbosity) result = self.testRunner.run(self.test) reactor.stop() return result.wasSuccessful() class ConfigException(Exception): """Exception thrown when configuration settings arent correct. """ pass class TestException(Exception): """Exception thrown when test case isn't correctly set up. """ pass class ServiceTestCase(unittest.TestCase): """Conventions for method names: test_net* -- network tests test_local* -- local tests test_dispatch* -- tests that use the a spawned local container class attributes: Edit/Override these in the inheriting class as needed out -- file descriptor to write output to name -- configuration item, must be set in class. url_section -- configuration section, maps a test module name to an URL. client_file_name -- types_file_name -- server_file_name -- """ out = OUTPUT name = None url_section = 'WSDL' client_file_name = None types_file_name = None server_file_name = None def __init__(self, methodName): """ parameters: methodName -- instance variables: client_module types_module server_module processID done """ self.methodName = methodName self.url = None self.wsdl2py_args = [] self.wsdl2dispatch_args = [] self.portkwargs = {} self.client_module = self.types_module = self.server_module = None self.done = False if TWISTED: self.wsdl2py_args.append('--twisted') if LAZY: self.wsdl2py_args.append('--lazy') unittest.TestCase.__init__(self, methodName) write = lambda self, arg: self.out.write(arg) if sys.version_info[:2] >= (2,5): _exc_info = unittest.TestCase._exc_info else: _exc_info = unittest.TestCase._TestCase__exc_info def __call__(self, *args, **kwds): self.run(*args, **kwds) def run(self, result=None): if result is None: result = self.defaultTestResult() result.startTest(self) testMethod = getattr(self, self.methodName) try: try: self.setUp() except KeyboardInterrupt: raise except: result.addError(self, self._exc_info()) return ok = False try: t1 = time.time() pyobj = testMethod() t2 = time.time() ok = True except self.failureException: result.addFailure(self, self._exc_info()) except KeyboardInterrupt: raise except: result.addError(self, self._exc_info()) try: self.tearDown() except KeyboardInterrupt: raise except: result.addError(self, self._exc_info()) ok = False if ok: result.addSuccess(self) print>>self print>>self, "|"+"-"*60 print>>self, "| TestCase: %s" %self.methodName print>>self, "|"+"-"*20 print>>self, "| run time: %s ms" %((t2-t1)*1000) print>>self, "| return : %s" %pyobj print>>self, "|"+"-"*60 finally: result.stopTest(self) def getPortKWArgs(self): kw = {} if CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'tracefile'): kw['tracefile'] = TRACEFILE kw.update(self.portkwargs) return kw def _setUpDispatch(self): """Set this test up as a dispatch test. url -- """ host = CONFIG_PARSER.get(SECTION_DISPATCH, 'host') port = CONFIG_PARSER.get(SECTION_DISPATCH, 'port') path = CONFIG_PARSER.get(SECTION_DISPATCH, 'path') scheme = 'http' netloc = '%s:%s' %(host, port) params = query = fragment = None self.portkwargs['url'] = \ urlparse.urlunparse((scheme,netloc,path,params,query,fragment)) _wsdl = {} def _generate(self): """call the wsdl2py and wsdl2dispatch scripts and automatically add the "-f" or "-u" argument. Other args can be appended via the "wsdl2py_args" and "wsdl2dispatch_args" instance attributes. """ url = self.url if os.path.isfile(url): url = os.path.abspath(url) if SKIP: ServiceTestCase._wsdl[url] = True return ServiceTestCase._wsdl[url] = False try: os.mkdir(MODULEDIR) except OSError, ex: pass os.chdir(MODULEDIR) if MODULEDIR not in sys.path: sys.path.append(MODULEDIR) try: commands.wsdl2py([url] + self.wsdl2py_args) ServiceTestCase._wsdl[url] = True finally: os.chdir(TOPDIR) _process = None _lastToDispatch = None def setUp(self): """Generate types and services modules once, then make them available thru the *_module attributes if the *_file_name attributes were specified. """ section = self.url_section name = self.name if not section or not name: raise TestException, 'section(%s) or name(%s) not defined' %( section, name) if not CONFIG_PARSER.has_section(section): raise TestException,\ 'No such section(%s) in configuration file(%s)' %( self.url_section, CONFIG_FILE) self.url = CONFIG_PARSER.get(section, name) status = ServiceTestCase._wsdl.get(self.url) if status is False: self.fail('generation failed for "%s"' %self.url) if status is None: self._generate() # Check for files tfn = self.types_file_name cfn = self.client_file_name sfn = self.server_file_name files = filter(lambda f: f is not None, [cfn, tfn,sfn]) if None is cfn is tfn is sfn: return for n,m in map(lambda i: (i,__import__(i.split('.py')[0])), files): if tfn is not None and tfn == n: self.types_module = m elif cfn is not None and cfn == n: self.client_module = m elif sfn is not None and sfn == n: self.server_module = m else: self.fail('Unexpected module %s' %n) # DISPATCH PORTION OF SETUP if not self.methodName.startswith('test_dispatch'): return self._setUpDispatch() if ServiceTestCase._process is not None: return try: expath = CONFIG_PARSER.get(SECTION_DISPATCH, name) except (NoSectionError, NoOptionError), ex: self.fail('section dispatch has no item "%s"' %name) if ServiceTestCase._lastToDispatch == expath: return if ServiceTestCase._lastToDispatch is not None: ServiceTestCase.CleanUp() ServiceTestCase._lastToDispatch = expath ServiceTestCase._process = \ _LaunchContainer(os.path.join(os.path.abspath(TOPDIR), *expath.split('/'))) def CleanUp(cls): """call this when dispatch server is no longer needed, maybe another needs to be started. Assumption that a single "Suite" uses the same server, once all the tests are run in that suite do a cleanup. """ if cls._process is None: return os.kill(cls._process.pid, signal.SIGKILL) cls._process = None CleanUp = classmethod(CleanUp) class ServiceTestSuite(unittest.TestSuite): """A test suite is a composite test consisting of a number of TestCases. For use, create an instance of TestSuite, then add test case instances. When all tests have been added, the suite can be passed to a test runner, such as TextTestRunner. It will run the individual test cases in the order in which they were added, aggregating the results. When subclassing, do not forget to call the base class constructor. """ def __init__(self, tests=()): unittest.TestSuite.__init__(self, tests) def __call__(self, result): # for python2.4 return self.run(result) def addTest(self, test): unittest.TestSuite.addTest(self, test) def run(self, result): for test in self._tests: if result.shouldStop: break test(result) ServiceTestCase.CleanUp() return result ZSI-2.1-a1/test/wsdl2py/test_EchoWSAddr200403.py0000644000175100017510000001156510560302574017120 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException, TC from ZSI.schema import GED, GTD """ Unittest WSDL: ../../samples/Echo/Echo.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(EchoTestCase, 'test_')) return suite class EchoTestCase(ServiceTestCase): name = "test_EchoWSAddr200403" client_file_name = "EchoWSAddr200403Server_client.py" types_file_name = "EchoWSAddr200403Server_types.py" server_file_name = "EchoWSAddr200403Server_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-ab') def getPortKWArgs(self): kw = ServiceTestCase.getPortKWArgs(self) kw['wsAddressURI'] = 'http://schemas.xmlsoap.org/ws/2004/03/addressing' return kw def test_local_Echo(self): msg = self.client_module.EchoRequest() rsp = self.client_module.EchoResponse() def test_dispatch_Echo(self): loc = self.client_module.EchoWSAddr200403ServerLocator() port = loc.getport(**self.getPortKWArgs()) msg = self.client_module.EchoRequest() msg.EchoIn = 'bla bla bla' rsp = port.Echo(msg) self.failUnless(rsp.EchoResult == msg.EchoIn, "Bad Echo") def test_dispatch_Echo_MIH_EPR(self): epr = GED('http://schemas.xmlsoap.org/ws/2004/03/addressing','EndpointReference').pyclass() epr.Address = 'urn:whatever' loc = self.client_module.EchoWSAddr200403ServerLocator() port = loc.getport(endPointReference=epr, **self.getPortKWArgs()) msg = self.client_module.EchoRequest() msg.EchoIn = 1 rsp = port.Echo(msg) self.failUnless(rsp.EchoResult == msg.EchoIn, "Bad Echo") def test_dispatch_Echo_MIH_EPR2(self): epr = GED('http://schemas.xmlsoap.org/ws/2004/03/addressing','EndpointReference').pyclass() epr.Address = 'urn:whatever' epr.ReferenceProperties = epr.new_ReferenceProperties() loc = self.client_module.EchoWSAddr200403ServerLocator() port = loc.getport(endPointReference=epr, **self.getPortKWArgs()) msg = self.client_module.EchoRequest() msg.EchoIn = 1 rsp = port.Echo(msg) self.failUnless(rsp.EchoResult == msg.EchoIn, "Bad Echo") def test_dispatch_Echo_MIH_EPR3_BadHeader(self): """Unqualified element "mystr" in Header """ epr = GED('http://schemas.xmlsoap.org/ws/2004/03/addressing','EndpointReference').pyclass() epr.Address = 'urn:whatever' epr.ReferenceProperties = epr.new_ReferenceProperties() class Xstr(str): typecode = TC.String('mystr') epr.ReferenceProperties.Any = [Xstr('whatever'),] loc = self.client_module.EchoWSAddr200403ServerLocator() self._setUpDispatch() port = loc.getport(endPointReference=epr, **self.getPortKWArgs()) msg = self.client_module.EchoRequest() self.failUnlessRaises(FaultException, port.Echo,msg) def test_dispatch_Echo_MIH_EPR3(self): epr = GED('http://schemas.xmlsoap.org/ws/2004/03/addressing','EndpointReference').pyclass() epr.Address = 'urn:whatever' epr.ReferenceProperties = epr.new_ReferenceProperties() class Xstr(str): typecode = TC.String(('urn:josh','mystr')) epr.ReferenceProperties.Any = [Xstr('whatever'),] loc = self.client_module.EchoWSAddr200403ServerLocator() self._setUpDispatch() port = loc.getport(endPointReference=epr, **self.getPortKWArgs()) msg = self.client_module.EchoRequest() epr2 = GTD('http://schemas.xmlsoap.org/ws/2004/03/addressing','EndpointReferenceType')(None).pyclass() epr2.Address = epr.Address epr2.ReferenceProperties = epr.ReferenceProperties msg.EchoIn = epr2 rsp = port.Echo(msg) self.failUnless(rsp.EchoResult.Address == msg.EchoIn.Address, "Bad Echo") self.failUnless(rsp.EchoResult.ReferenceProperties.Any == msg.EchoIn.ReferenceProperties.Any, "Bad Echo") if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_XMethodsQuery.py0000755000175100017510000000645510551530755017316 0ustar zsizsi#!/usr/bin/env python ############################################################################ # David W. Robertson, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite """ Unittest for contacting the XMethodsQuery Web service. WSDL: http://www.xmethods.net/wsdl/query.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(XMethodsQueryTest, 'test_dispatch', suiteClass=ServiceTestSuite)) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(XMethodsQueryTest, 'test_local', suiteClass=ServiceTestSuite)) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(XMethodsQueryTest, 'test_net', suiteClass=ServiceTestSuite)) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(XMethodsQueryTest, 'test_', suiteClass=ServiceTestSuite)) return suite class XMethodsQueryTest(ServiceTestCase): """Test case for XMethodsQuery Web service """ name = "test_XMethodsQuery" client_file_name = "XMethodsQuery_client.py" types_file_name = "XMethodsQuery_types.py" server_file_name = "XMethodsQuery_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_net_getAllServiceNames(self): loc = self.client_module.XMethodsQueryLocator() port = loc.getXMethodsQuerySoap(**self.getPortKWArgs()) msg = self.client_module.getAllServiceNames2SoapIn() rsp = port.getAllServiceNames(msg) return rsp def test_net_getAllServiceSummaries(self): loc = self.client_module.XMethodsQueryLocator() port = loc.getXMethodsQuerySoap(**self.getPortKWArgs()) msg = self.client_module.getAllServiceSummaries1SoapIn() rsp = port.getAllServiceSummaries(msg) return rsp def test_net_getServiceDetail(self): loc = self.client_module.XMethodsQueryLocator() port = loc.getXMethodsQuerySoap(**self.getPortKWArgs()) msg = self.client_module.getServiceDetail4SoapIn() msg._id = 'uuid:A29C0D6C-5529-0D27-A91A-8E02D343532B' rsp = port.getServiceDetail(msg) return rsp def test_net_getServiceNamesByPublisher(self): loc = self.client_module.XMethodsQueryLocator() port = loc.getXMethodsQuerySoap(**self.getPortKWArgs()) msg = self.client_module.getServiceNamesByPublisher3SoapIn() msg._publisherID = 'xmethods.net' rsp = port.getServiceNamesByPublisher(msg) return rsp def test_net_getServiceSummariesByPublisher(self): loc = self.client_module.XMethodsQueryLocator() port = loc.getXMethodsQuerySoap(**self.getPortKWArgs()) msg = self.client_module.getServiceSummariesByPublisher0SoapIn() msg._publisherID = 'xmethods.net' rsp = port.getServiceSummariesByPublisher(msg) return rsp if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_ThreatService.py0000755000175100017510000000363510551530755017302 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite """ Unittest for contacting the threatService Web service. WSDL: http://www.boyzoid.com/threat.cfc?wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(HomelandTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(HomelandTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(HomelandTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(HomelandTestCase, 'test_')) return suite class HomelandTestCase(ServiceTestCase): """Test case for ZipCodeResolver Web service """ name = "test_ThreatService" client_file_name = "Current_Homeland_Security_Threat_Level_client.py" types_file_name = "Current_Homeland_Security_Threat_Level_types.py" server_file_name = None def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_net_threatLevel(self): loc = self.client_module.Current_Homeland_Security_Threat_LevelLocator() port = loc.getthreat_cfc(**self.getPortKWArgs()) msg = self.client_module.threatLevelRequest() rsp = port.threatLevel(msg) for item in rsp.ThreatLevelReturn.Item: item.Key item.Value if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_WSDLImport.py0000644000175100017510000000312210567133042016455 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest, time from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException from ZSI.TC import _get_global_element_declaration as GED from ZSI.writer import SoapWriter from ZSI.parse import ParsedSoap """ Unittest for Bug Report [ ] test_WSDLImport.wsdl test_WSDLImport2.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WSDLImportTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WSDLImportTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WSDLImportTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WSDLImportTestCase, 'test_')) return suite class WSDLImportTestCase(ServiceTestCase): name = "test_WSDLImport" types_file_name = "OutSchemaTest_client.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_attribute1(self): """ """ return if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_WhiteMesa.py0000755000175100017510000000446210551530755016417 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite, TestException """ Unittest for contacting the WhiteMesa web service for rpc/literal tests. WSDL: http://www.whitemesa.net/wsdl/test-rpc-lit.wsdl """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WhiteMesaTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WhiteMesaTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WhiteMesaTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(WhiteMesaTest, 'test_')) return suite class WhiteMesaTest(ServiceTestCase): """Test case for ZipCodeResolver Web service """ name = "test_WhiteMesa" client_file_name = "RPC_Literal_TestDefinitions_client.py" types_file_name = "RPC_Literal_TestDefinitions_types.py" server_file_name = "RPC_Literal_TestDefinitions_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_EchoBoolean(self): from ZSI.writer import SoapWriter msg = self.client_module.echoBooleanRequest() msg._inputBoolean = True sw = SoapWriter() sw.serialize(msg) def test_net_EchoBoolean(self): msg = self.client_module.echoBooleanRequest() msg._inputBoolean = True loc = self.client_module.WhiteMesaSoapRpcLitTestSvcLocator() port = loc.getSoap11TestRpcLitPort(**self.getPortKWArgs()) rsp = port.echoBoolean(msg) self.failUnless(msg._inputBoolean == rsp._return, "EchoBoolean Failed") def test_dispatch_EchoBoolean(self): self.test_net_EchoBoolean() if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_OpcDaGateway.py0000644000175100017510000001166510547037605017042 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite import ZSI from ZSI import FaultException """ Unittest for contacting the OPC XML-DA Service. WSDL: http://tswinc.us/XMLDADemo/ts_sim/OpcDaGateway.asmx?WSDL """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(OPCServiceTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(OPCServiceTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(OPCServiceTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(OPCServiceTest, 'test_')) return suite class OPCServiceTest(ServiceTestCase): """Test case for OPCService Web service def GetProperties(self, request): def Subscribe(self, request): def SubscriptionPolledRefresh(self, request): def SubscriptionCancel(self, request): def GetStatus(self, request): def Browse(self, request): def Read(self, request): def Write(self, request): """ name = "test_OpcDaGateway" client_file_name = "OpcXmlDaSrv_client.py" types_file_name = "OpcXmlDaSrv_types.py" server_file_name = "OpcXmlDaSrv_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_anyType(self): """serialize an int via anyType, then parse it back. """ import time pyobj = self.client_module.ReadSoapOut() pyobj.RItemList = pyobj.new_RItemList() item = pyobj.RItemList.new_Items() pyobj.RItemList.Items = [item,] item.typecode.ofwhat[1].processContents = 'lax' item.Value = 123 s = str(ZSI.SoapWriter().serialize(pyobj)) ps = ZSI.ParsedSoap(s) pyobj = ps.Parse(pyobj.typecode) for item in pyobj.RItemList.Items: item.Value def test_net_Browse(self): """FaultException: The item path is not known to the server. """ loc = self.client_module.OpcXmlDaSrvLocator() port = loc.getOpcXmlDaSrvSoap(**self.getPortKWArgs()) msg = self.client_module.BrowseSoapIn() msg._PropertyNames=['Static'] msg._attrs = {'ItemPath':'Static'} self.failUnless(\ getattr(msg.typecode, 'attribute_typecode_dict', None) is not None, ) self.failUnlessRaises(FaultException, port.Browse, msg) # def hangs_test_net_Read(self): # """FaultException: The item path is not known to the server. # """ # msg = self.getInputMessageInstance('Read') # # #msg = ReadSoapIn() # op = msg.new_Options() # msg.Options = op # op.set_attribute_ReturnItemTime(True) # op.set_attribute_ReturnItemName(True) # op.set_attribute_ClientRequestHandle("") # op.set_attribute_LocaleID('en-us') # # item_list = msg.new_ItemList() # msg.ItemList = item_list # item_list.set_attribute_MaxAge(1000) # # item = item_list.new_Items() # item_list.Items = item # item.set_attribute_ItemPath("") # item.set_attribute_ItemName("Staic.Analog Types.Int") # item.set_attribute_ClientItemHandle("") # # self.failUnless(\ # getattr(msg.typecode, 'attribute_typecode_dict', None) is not None, # ) # # self._ports[0].Read(msg) # # def hangs_test_net_GetProperties(self): # """sending an empty GetProperties request, # receiving empty response. # # # """ # operationName = 'GetProperties' # msg = self.getInputMessageInstance(operationName) # msg._ItemIDs # msg._PropertyNames # response = self._ports[0].GetProperties(msg) # result = response._GetPropertiesResult # # # not sure these attributes are required but check for them. # self.failUnless(isinstance(getattr(result, '_attrs', None), dict)) # for k in ['RcvTime','ReplyTime','RevisedLocaleID','ServerState']: # self.failUnless(result._attrs.has_key(k)) # # self.failUnless(len(response._PropertyLists) == 0) # self.failUnless(len(response._Errors) == 0) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_MapPoint.py0000644000175100017510000000441310551530755016251 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI.auth import AUTH """ Unittest for contacting the Map Point Service. WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(MapPointTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(MapPointTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(MapPointTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(MapPointTest, 'test_')) return suite class MapPointTest(ServiceTestCase): """Test case for OPCService Web service """ name = "test_MapPoint" client_file_name = "CommonService_client.py" types_file_name = "CommonService_types.py" server_file_name = "CommonService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_net_GetVersionInfo(self): """expect this to fail cause i'm not doing http authentication. """ loc = self.client_module.CommonServiceLocator() kw = self.getPortKWArgs() #port = loc.getCommonServiceSoap(auth=(AUTH.httpdigest, "USERNAME", "PASSWORD"), **kw) port = loc.getCommonServiceSoap(**kw) msg = self.client_module.GetVersionInfoSoapIn() try: rsp = port.GetVersionInfo(msg) except RuntimeError: # RuntimeError: HTTP Digest Authorization Failed pass port.binding.SetAuth(AUTH.httpdigest, user="USERNAME", password="PASSWORD") print ">> DIGEST AUTH" try: rsp = port.GetVersionInfo(msg) except RuntimeError: pass if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_ZipCodeResolver.py0000755000175100017510000000632110547037605017605 0ustar zsizsi#!/usr/bin/env python ############################################################################ # David W. Robertson, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite """ Unittest for contacting the ZipCodeResolver Web service. WSDL: http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ZipCodeResolverTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ZipCodeResolverTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ZipCodeResolverTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ZipCodeResolverTest, 'test_')) return suite class ZipCodeResolverTest(ServiceTestCase): """Test case for ZipCodeResolver Web service """ name = "test_ZipCodeResolver" client_file_name = "ZipCodeResolver.py" types_file_name = "ZipCodeResolver_types.py" #server_file_name = "ZipCodeResolver_server.py" def test_net_CorrectedAddressHtml(self): loc = self.client_module.ZipCodeResolverLocator() port = loc.getZipCodeResolverSoap(**self.getPortKWArgs()) msg = self.client_module.CorrectedAddressHtmlSoapIn() msg._address = '636 Colusa Avenue' msg._city = 'Berkeley' msg._state = 'California' rsp = port.CorrectedAddressHtml(msg) def test_net_CorrectedAddressXml(self): loc = self.client_module.ZipCodeResolverLocator() port = loc.getZipCodeResolverSoap(**self.getPortKWArgs()) msg = self.client_module.CorrectedAddressXmlSoapIn() msg._address = '636 Colusa Avenue' msg._city = 'Berkeley' msg._state = 'California' rsp = port.CorrectedAddressXml(msg) def test_net_FullZipCode(self): loc = self.client_module.ZipCodeResolverLocator() port = loc.getZipCodeResolverSoap(**self.getPortKWArgs()) msg = self.client_module.FullZipCodeSoapIn() msg._address = '636 Colusa Avenue' msg._city = 'Berkeley' msg._state = 'California' rsp = port.FullZipCode(msg) def test_net_ShortZipCode(self): loc = self.client_module.ZipCodeResolverLocator() port = loc.getZipCodeResolverSoap(**self.getPortKWArgs()) msg = self.client_module.ShortZipCodeSoapIn() msg._address = '636 Colusa Avenue' msg._city = 'Berkeley' msg._state = 'California' rsp = port.ShortZipCode(msg) def test_net_VersionInfo(self): loc = self.client_module.ZipCodeResolverLocator() port = loc.getZipCodeResolverSoap(**self.getPortKWArgs()) msg = self.client_module.VersionInfoSoapIn() rsp = port.VersionInfo(msg) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/wsdl/0000755000175100017510000000000010712455110014046 5ustar zsizsiZSI-2.1-a1/test/wsdl2py/wsdl/vim.wsdl0000644000175100017510000356405110647240777015574 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/DateService.wsdl0000644000175100017510000000615710604520230017144 0ustar zsizsi Date Web Service ZSI-2.1-a1/test/wsdl2py/wsdl/test_SubstitutionGroup.xsd0000644000175100017510000000214110604520230021350 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/BasicComm.wsdl0000644000175100017510000000476510604520230016606 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/ManufacturerImpl.wsdl0000644000175100017510000000245110604520230020215 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/FinancialService.wsdl0000644000175100017510000000503210604520230020142 0ustar zsizsi Financial Web Service. Methods: -getPV(irate, CFSequence): Return present value for given interest rate and Cash Flows. ZSI-2.1-a1/test/wsdl2py/wsdl/SquareService.wsdl0000644000175100017510000000346710604520230017530 0ustar zsizsi the square method Returns x^2 (x**2, square(x)) for a given float x ZSI-2.1-a1/test/wsdl2py/wsdl/test_WSDLImport2.wsdl0000644000175100017510000000337010604520230020025 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/test_Choice.xsd0000644000175100017510000000127110604520230017014 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/EchoWSAddr200403.wsdl0000644000175100017510000000410610604520230017332 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/nvo-admin.wsdl0000644000175100017510000034136610622701303016644 0ustar zsizsi Create or update each of the given resources Update or insert record - if it exist PassPhrase must match Input WHERE predicate for SQL Query like e.g. MAXSR > 1 and ResourceType like 'CONE' Input SQL Query Harvest OAI repository given URL Harvest Vizier with optional ResumptionTokenID, e.g. !!!ivo_vor!100 Harvest Single OAI Record Harvest from Astrogrid Registry Delete an individual record - return number of rows deleted searches registry for keyword. To AND keywords, set andKeys true otherwise OR'd return string list of searchable columns Retrieve All Records from Registry, returns SimpleResources Retrieve All VOResources from Registry Returns VOResources: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns VOResources with status=1 and 3: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns OAI_DC: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns custom simplified Resources: Input WHERE predicate for SQL Query like e.g. ResourceType like 'CONE' Returns SimpleResource (backward compatibility for DATASCOPE): Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' searches registry for keyword returns cvs verions of classes in this service Update or insert record - if it exist PassPhrase must match Input WHERE predicate for SQL Query like e.g. MAXSR > 1 and ResourceType like 'CONE' Input SQL Query Harvest OAI repository given URL Harvest Vizier with optional ResumptionTokenID, e.g. !!!ivo_vor!100 Harvest Single OAI Record Harvest from Astrogrid Registry Delete an individual record - return number of rows deleted searches registry for keyword. To AND keywords, set andKeys true otherwise OR'd return string list of searchable columns Retrieve All Records from Registry, returns SimpleResources Retrieve All VOResources from Registry Returns VOResources: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns VOResources with status=1 and 3: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns OAI_DC: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns custom simplified Resources: Input WHERE predicate for SQL Query like e.g. ResourceType like 'CONE' Returns SimpleResource (backward compatibility for DATASCOPE): Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' searches registry for keyword returns cvs verions of classes in this service Update or insert record - if it exist PassPhrase must match Input WHERE predicate for SQL Query like e.g. MAXSR > 1 and ResourceType like 'CONE' Input SQL Query Harvest OAI repository given URL Harvest Vizier with optional ResumptionTokenID, e.g. !!!ivo_vor!100 Harvest Single OAI Record Harvest from Astrogrid Registry Delete an individual record - return number of rows deleted searches registry for keyword. To AND keywords, set andKeys true otherwise OR'd return string list of searchable columns Retrieve All Records from Registry, returns SimpleResources Retrieve All VOResources from Registry Returns VOResources: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns VOResources with status=1 and 3: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns OAI_DC: Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' Returns custom simplified Resources: Input WHERE predicate for SQL Query like e.g. ResourceType like 'CONE' Returns SimpleResource (backward compatibility for DATASCOPE): Input WHERE predicate for SQL Query like e.g. maxSearchRadius > 1 and ResourceType like 'CONE' searches registry for keyword returns cvs verions of classes in this service ZSI-2.1-a1/test/wsdl2py/wsdl/test_WSDLImport.wsdl0000644000175100017510000000045310604520230017742 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/test_DerivedTypes.xsd0000644000175100017510000000315610604520230020235 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/test_Attributes.xsd0000644000175100017510000000311210604520230017744 0ustar zsizsi ZSI-2.1-a1/test/wsdl2py/wsdl/Racing.wsdl0000644000175100017510000007752210604520230016155 0ustar zsizsi Meeting Summary :- Provides a list of all Meeting Identifiers for either the current or a nominated day and the Race Identifiers for each Meeting Identifier returned. In addition, summary meeting level information is provided. Next Event :- Provides all meeting, race, runner, pool and odds information for the next event to jump. Next Ten Events :- Provides the Race Identifiers and summary race details for the next 10 races to jump. Summary Meeting Information :- Provides the Meeting level information including multi-leg pools for a specified meeting. Event Summary Race Information :- Provides the details of all races, including pools, for a specified meeting. Event Summary Runner Information :- Provides runner information including the name of the jockey (Galloping), driver (Harness) and trainer (Greyhounds) including amendments, barrier and handicap for all races at a specified meeting. Event Summary (Jockey, Driver, Trainer) :- Provides jockey (Galloping), driver (Harness), trainer (Greyhounds) information, listed alphabetically by surname, including name, racenumber and runner number, for all races at a specified meeting. Event Summary :- Provides a combination of the information in the Summary Meeting Information, Event Summary Race Information and the Event Summary Runner Information services for a specified meeting. Event :- Provides all information, including meeting information, pools, runners, approximate dividends, results and final dividends, for a specified race. Event Race Information :- Provides a combination of the information in the Summary Meeting Information, Event Summary Race Information and Event Summary Runner Information for a specified race. Event Runner Information :- Provides runner information including the name of the jockey (Galloping), driver (Harness) and trainer (Greyhounds) including amendments, barrier and handicap for a specified race. Event Approximates :- Provides the latest Win and Place approximate dividends and all pool values for a specified race. Event Quinella Approximates :- Provides a maximum of 60 combinations and associated approximate dividends for the Quinella pool of a specified race. Event Exacta Approximates :- Provides a maximum of 60 combinations and associated approximate dividends for the Exacta pool of a specified race. Event Results Dividends :- Provides the results and all dividends for a specified race. ZSI-2.1-a1/test/wsdl2py/test_Manufacturer.py0000644000175100017510000000270310556000365017150 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException, ParsedSoap """ Unittest WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_')) return suite class TestCase(ServiceTestCase): name = "test_Manufacturer" client_file_name = "ManufacturerService_client.py" types_file_name = "ManufacturerService_types.py" server_file_name = "ManufacturerService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_(self): pass if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_DerivedTypes.py0000644000175100017510000002245510547037605017140 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import EvaluateException, FaultException from ZSI.writer import SoapWriter from ZSI.parse import ParsedSoap from ZSI.TC import _get_type_definition as GTD from ZSI.TC import _get_global_element_declaration as GED """ Unittest WSDL: derivedTypes. """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(DTTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(DTTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(DTTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(DTTestCase, 'test_')) return suite class DTTestCase(ServiceTestCase): name = "test_DerivedTypes" client_file_name = None types_file_name = "test_DerivedTypes_xsd_types.py" server_file_name = None def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-x') self.wsdl2py_args.append('-b') def test_local_ged_substitution(self): """This test is designed to fail, trying to dump a GED in via type substitution. """ self.types_module pyobj = GED('urn:test', 'test').pyclass() # use GED of a derived type pyobj.Actor = sub = GED('urn:test', 'MiddleActor').pyclass() sub.Element1 = 'foo' sub.Element2 = 'bar' sw = SoapWriter() self.failUnlessRaises(TypeError, sw.serialize, pyobj) def test_local_type_substitution_test2(self): """test extension of extension""" attr1 = 'aone' attr2 = 'atwo' attr3 = 'athree' self.types_module pyobj = GED('urn:test', 'test2').pyclass() # Test maxOccurs>1 for substitution # pyobj.Actor = [GTD('urn:test', 'TopActor')(None).pyclass()] sub1 = pyobj.Actor[0] sub1.Element1 = 'one' sub1.Element2 = 'two' sub1.Element3 = 'three' sub1.set_attribute_attr1(attr1) sub1.set_attribute_attr2(attr2) sub1.set_attribute_attr3(attr3) sw = SoapWriter() sw.serialize(pyobj) xml = str(sw) ps = ParsedSoap(xml) pyobj2 = ps.Parse(pyobj.typecode) sub2 = pyobj2.Actor[0] self.failUnless(sub2.get_attribute_attr1() == attr1, 'bad attribute 1') self.failUnless(sub2.get_attribute_attr2() == attr2, 'bad attribute 2') self.failUnless(sub2.get_attribute_attr3() == attr3, 'bad attribute 3') self.failUnless(sub2.Element1 == sub1.Element1, 'bad element 1') self.failUnless(sub2.Element2 == sub1.Element2, 'bad element 2') self.failUnless(sub2.Element3 == sub1.Element3, 'bad element 3') # check parsed out correct type self.failUnless(isinstance(sub2.typecode, sub1.typecode.__class__), 'local element actor "%s" must be an instance of "%s"'% (sub2.typecode, sub1.typecode.__class__)) # check local element is derived from base base = GTD('urn:test', 'BaseActor') self.failUnless(isinstance(sub2.typecode, base), 'local element actor must be a derived type of "%s"'% base) def test_local_type_substitution2(self): """test extension of extension""" attr1 = 'aone' attr2 = 'atwo' attr3 = 'athree' self.types_module pyobj = GED('urn:test', 'test').pyclass() # [ 1489129 ] Unexpected subsitution error message # try to parse before type ever initialized """ ps = ParsedSoap(MSG1) pyobj0 = ps.Parse(pyobj.typecode) sub0 = pyobj0.Actor self.failUnless(sub0.get_attribute_attr1() == attr1, 'bad attribute1') self.failUnless(sub0.get_attribute_attr2() == attr2, 'bad attribute2') """ # [ 1489090 ] Derived type attributes don't populate the attr dictionary # [ 1489677 ] Derivation from derived type missing derived element # pyobj.Actor = sub1 = GTD('urn:test', 'TopActor')(None).pyclass() sub1.Element1 = 'one' sub1.Element2 = 'two' sub1.Element3 = 'three' sub1.set_attribute_attr1(attr1) sub1.set_attribute_attr2(attr2) sub1.set_attribute_attr3(attr3) sw = SoapWriter() sw.serialize(pyobj) xml = str(sw) ps = ParsedSoap(xml) pyobj2 = ps.Parse(pyobj.typecode) sub2 = pyobj2.Actor self.failUnless(sub2.get_attribute_attr1() == attr1, 'bad attribute 1') self.failUnless(sub2.get_attribute_attr2() == attr2, 'bad attribute 2') self.failUnless(sub2.get_attribute_attr3() == attr3, 'bad attribute 3') self.failUnless(sub2.Element1 == sub1.Element1, 'bad element 1') self.failUnless(sub2.Element2 == sub1.Element2, 'bad element 2') self.failUnless(sub2.Element3 == sub1.Element3, 'bad element 3') # check parsed out correct type self.failUnless(isinstance(sub2.typecode, sub1.typecode.__class__), 'local element actor "%s" must be an instance of "%s"'% (sub2.typecode, sub1.typecode.__class__)) # check local element is derived from base base = GTD('urn:test', 'BaseActor') self.failUnless(isinstance(sub2.typecode, base), 'local element actor must be a derived type of "%s"'% base) def test_local_parse_missing_type_substitution(self): """attempt to substitute an unregistered/unknown type """ attr1 = 'myclass' attr2 = 'whatever' self.types_module pyobj = GED('urn:test', 'test').pyclass() ps = ParsedSoap(NO_SUB_MSG) self.failUnlessRaises(EvaluateException, ps.Parse, pyobj.typecode) def test_local_type_substitution1(self): """test extension. Parse known instance, serialize an equivalent, Parse it back. """ attr1 = 'myclass' attr2 = 'whatever' self.types_module pyobj = GED('urn:test', 'test').pyclass() # [ 1489129 ] Unexpected subsitution error message # try to parse before type ever initialized ps = ParsedSoap(MSG1) pyobj0 = ps.Parse(pyobj.typecode) sub0 = pyobj0.Actor self.failUnless(sub0.get_attribute_attr1() == attr1, 'bad attribute1') self.failUnless(sub0.get_attribute_attr2() == attr2, 'bad attribute2') # [ 1489090 ] Derived type attributes don't populate the attr dictionary # pyobj.Actor = sub1 = GTD('urn:test', 'MiddleActor')(None).pyclass() sub1.Element1 = 'foo' sub1.Element2 = 'bar' sub1.set_attribute_attr1(attr1) sub1.set_attribute_attr2(attr2) sw = SoapWriter() sw.serialize(pyobj) xml = str(sw) ps = ParsedSoap(xml) pyobj2 = ps.Parse(pyobj.typecode) sub2 = pyobj2.Actor self.failUnless(sub2.get_attribute_attr1() == attr1, 'bad attribute class') self.failUnless(sub2.get_attribute_attr2() == attr2, 'bad attribute name') # check parsed out correct type self.failUnless(isinstance(sub2.typecode, sub1.typecode.__class__), 'local element actor "%s" must be an instance of "%s"'% (sub2.typecode, sub1.typecode.__class__)) # check local element is derived from base base = GTD('urn:test', 'BaseActor') self.failUnless(isinstance(sub2.typecode, base), 'local element actor must be a derived type of "%s"'% base) MSG1 = """foobar""" NO_SUB_MSG = """foobar""" if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/config.txt0000644000175100017510000001434310700311160015101 0ustar zsizsi############################################################################ # Joshua R. Bovernof, LBNL # See Copyright for copyright notice! # # CONFIGURATION SECTIONS # [configuration] - global configuration of service tests. # tracefile -- trace soap messages # debug -- turn on debugging # skip -- skip generation steps, code generated don't generate again # twisted -- Use twisted web client # lazy -- use lazy typecode evaluation # output -- file name where output will be stored, if unspecified test output goes to stdout # # [dispatch] -- configuration for test_dispatch* tests # host -- address of local container # port -- port of local container # path -- path of service # twisted -- Use twisted web resource # ########################################################################## [configuration] tracefile = True debug = False skip = False twisted = False lazy = False output = [dispatch] host = localhost port = 9080 path = test twisted = False test_WhiteMesa = servers/WhiteMesa.py test_Echo = servers/EchoServer.py test_BasicComm = servers/BasicServer.py test_SquareService = servers/SquareService.py test_DateService = servers/DateService.py test_FinancialService = servers/FinancialService.py test_EchoWSAddr200403 = servers/EchoWSAddr200403Server.py ########################################################################## # URL SECTIONS: All SOAP-1.1 # document -- document style True/False # literal -- literal encoding True/False # broke -- broke True/False # tests -- whitespace separated list of test modules, referenced in # section WSDL. # # [rpc_encoded] -- these are rpc/encoded services that WORK. # [rpc_encoded_broke] -- these are rpc/encoded services that DONT WORK. # # [doc_encoded] -- these are document/encoded services that WORK. # [doc_encoded_broke] -- these are document/encoded services that DONT WORK. # # [rpc_literal] -- these are rpc/literal services that WORK. # [rpc_literal_broke] -- these are rpc/literal services that DONT WORK. # [rpc_literal_broke_interop] -- these are broke BP-1.0 compliant rpc/literal services. # # [doc_literal] -- these are doc/literal services that WORK. # [doc_literal_broke] -- these are doc/literal services that DONT WORK. # [doc_literal_broke_interop] -- these are broke BP-1.0 compliant doc/literal services. # ########################################################################## ########################## RPC/ENCODED ################################### # # Broken: # # ########################################################################## [rpc_encoded] document = False literal = False broke = False tests = test_XMethodsQuery test_ThreatService [rpc_encoded_broke] document = False literal = False broke = True tests = ########################## RPC/LITERAL ################################### # # Broken: # # ########################################################################## [rpc_literal] document = False literal = True broke = False tests = test_WhiteMesa test_SquareService test_DateService [rpc_literal_broke] document = False literal = True broke = True tests = [rpc_literal_broke_interop] document = False literal = True broke = True tests = ########################## DOCUMENT/LITERAL ############################## # # Broken: # test_TerraService -- wsdl2python Not supporting content # # ########################################################################## [doc_literal] document = True literal = True broke = False tests = test_MapPoint test_Echo test_AWSECommerceService test_FinancialService test_BasicComm test_Manufacturer test_Racing test_Attributes test_Choice test_DerivedTypes test_EchoWSAddr200403 test_SubstitutionGroup test_VIM [doc_literal_broke] document = True literal = True broke = True tests = [doc_literal_broke_interop] document = True literal = True broke = True tests = ########################################################################## # SECTION [WSDL] - test name(equivalent to module name) and URL. # ########################################################################## [WSDL] test_AWSECommerceService = http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl test_AmazonS3 = http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl test_TemperatureService = http://www.xmethods.net/sd/2001/TemperatureService.wsdl test_WorldTimeService = http://ws.digiposs.com/WorldTime.jws?wsdl test_BFGraphLib = http://bfo.co.uk/products/graph/docs/bfograph-2.1.wsdl test_XMethodsQuery = http://www.xmethods.net/wsdl/query.wsdl test_ZipCodeResolver = http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL test_WhiteMesa = http://www.whitemesa.net/wsdl/test-rpc-lit.wsdl test_OpcDaGateway = http://tswinc.us/XMLDADemo/ts_sim/OpcDaGateway.asmx?WSDL test_MapPoint = http://staging.mappoint.net/standard-30/mappoint.wsdl test_Sabre = http://webservices.sabre.com/wsdl/sabreXML1.0.00/res/SessionCreateRQ.wsdl test_Echo = ../../samples/Echo/Echo.wsdl test_BasicComm = wsdl/BasicComm.wsdl test_Choice = wsdl/test_Choice.xsd test_Attributes = wsdl/test_Attributes.xsd test_DerivedTypes = wsdl/test_DerivedTypes.xsd test_SubstitutionGroup = wsdl/test_SubstitutionGroup.xsd test_WSDLImport = wsdl/test_WSDLImport.wsdl test_SquareService = wsdl/SquareService.wsdl test_DateService = wsdl/DateService.wsdl test_FinancialService = wsdl/FinancialService.wsdl test_ThreatService = http://www.boyzoid.com/threat.cfc?wsdl test_TerraService = http://terraservice.net/TerraService.asmx?WSDL test_InfoBil = http://javatest2.infodata.se/webservices/services/Infobil?wsdl test_EchoWSAddr200403 = wsdl/EchoWSAddr200403.wsdl # Google AdWords #test_GoogleAdWords = https://sandbox.google.com/api/adwords/v8/TrafficEstimatorService?wsdl test_GoogleAdWords = https://adwords.google.com:443/api/adwords/v10/TrafficEstimatorService?wsdl # TODO: These aren't finished #test_GoogleAdWords_CS = https://sandbox.google.com/api/adwords/v8/CampaignService?wsdl test_GoogleAdWords_CS = https://adwords.google.com:443/api/adwords/v10/CampaignService?wsdl test_Manufacturer = wsdl/ManufacturerImpl.wsdl test_Racing = wsdl/Racing.wsdl test_NVOAdmin = wsdl/nvo-admin.wsdl test_Clearspace = http://eval.jivesoftware.com/clearspace/rpc/soap/BlogService?wsdl test_VIM = wsdl/vim.wsdl ZSI-2.1-a1/test/wsdl2py/test_Racing.py0000644000175100017510000001060210566713527015730 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException, ParsedSoap, SoapWriter """ Unittest WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(TestCase, 'test_')) return suite class TestCase(ServiceTestCase): name = "test_Racing" client_file_name = "Racing_client.py" types_file_name = "Racing_types.py" server_file_name = "Racing_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def test_local_anyType(self): """rpc/lit, testing if lax content handling should get back dicts and strings """ ps = ParsedSoap(MSG) pyobj = ps.Parse(self.client_module.EventApproximatesSoapOut.typecode) any = {'PoolTotals': {'Pool': {'Total': u'4117.66', 'ENumbers': None, 'JackpotNet': None}}, 'Approximates': {'Pool': {'Win': u'3.90,0.00,10.40,11.80,4.70,29.50,29.90,2.40,19.80,0.00', 'Place': u'1.04,0.00,2.80,5.90,2.00,5.20,7.40,1.04,4.00,0.00'}}} self.failUnless(pyobj.EventApproximatesResult.Any == any, 'Failed match:\n %s\n\n%s' %( pyobj.EventApproximatesResult.Any, any)) pyobj.EventApproximatesResult.Any = dict(pyobj.EventApproximatesResult.Any) sw = SoapWriter() sw.serialize(pyobj) print str(sw) ps2 = ParsedSoap(str(sw)) pyobj2 = ps.Parse(self.client_module.EventApproximatesSoapOut.typecode) print "EAR: ", pyobj2.EventApproximatesResult print "Any: ", pyobj2.EventApproximatesResult.Any self.failUnless(pyobj.EventApproximatesResult.Any == pyobj2.EventApproximatesResult.Any, 'Failed match:\n %s\n\n%s' %(pyobj.EventApproximatesResult.Any, pyobj2.EventApproximatesResult.Any)) MSG=""" 3.90,0.00,10.40,11.80,4.70,29.50,29.90,2.40,19.80,0.00 1.04,0.00,2.80,5.90,2.00,5.20,7.40,1.04,4.00,0.00 451.00 1001.00 1750.59 6052.50 05 06 07 08 865.00 21.50 2575.50 4117.66 """ if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_GoogleAdWords.py0000644000175100017510000000614410700311160017204 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException """ Unittest for contacting google adwords WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_')) return suite class TrafficEstimatorServiceTest(ServiceTestCase): """Test case for Google AdWords, sandbox v8 Reads header information from a file "adwords.properties", need to format this for ConfigParser [test_GoogleAdWords] email = password = useragent = applicationtoken = """ name = "test_GoogleAdWords" client_file_name = "TrafficEstimatorService_client.py" types_file_name = "TrafficEstimatorService_types.py" server_file_name = "TrafficEstimatorService_server.py" header_info = os.path.join(os.getenv('HOME'), 'adwords.properties') def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def _get_soap_headers(self): from ConfigParser import ConfigParser cp = ConfigParser(); cp.read(self.header_info) p,e,a,u = map(lambda var: cp.get(self.__class__.name, var), 'password email applicationtoken useragent'.split()) tns,GED = "https://adwords.google.com/api/adwords/v10", self.client_module.GED password = GED(tns, "password").pyclass(p) email = GED(tns, "email").pyclass(e) atoken = GED(tns, "applicationToken").pyclass(a) useragent = GED(tns, "useragent").pyclass(u) # google sandbox uses these conventions... dtoken = GED(tns, "developerToken").pyclass('%s++USD' %e) ## v8 sandbox syntax isnt working for v10 cemail = GED(tns, "clientEmail").pyclass('client_1+'+e) return (email, password, useragent, dtoken, atoken, cemail) def test_net_KeywordEstimate(self): loc = self.client_module.TrafficEstimatorServiceLocator() port = loc.getTrafficEstimatorService(**self.getPortKWArgs()) msg = self.client_module.estimateKeywordListRequest() kwd = msg.new_keywordRequests() kwd.Text = "flowers" kwd.MaxCpc = 50000L kwd.Type = "Broad" msg.KeywordRequests = [ kwd ] rsp = port.estimateKeywordList(msg, soapheaders=self._get_soap_headers()) ServiceTest = TrafficEstimatorServiceTest if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_Attributes.py0000644000175100017510000001242510547037605016653 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest, time from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException from ZSI.TC import _get_global_element_declaration as GED from ZSI.writer import SoapWriter from ZSI.parse import ParsedSoap """ Unittest for Bug Report [ ] XSD: test_Attributes.xsd """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AttributeTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AttributeTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AttributeTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(AttributeTestCase, 'test_')) return suite class AttributeTestCase(ServiceTestCase): name = "test_Attributes" types_file_name = "test_Attributes_xsd_types.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') self.wsdl2py_args.append('-x') def test_local_attribute1(self): """ """ myDouble = 4.5 myInt = 9 myFloat = 3.0001 myDecimal = 8.999 myGDateTime = time.gmtime() myAnyURI = "urn:whatever" myQName = ("urn:test", "qbert") myString = "whatever" myHexBinary = hex(888) pyobj = GED("urn:example", "Test1").pyclass() # Test serialize/parse pyobj.set_attribute_myDecimal(myDecimal) pyobj.set_attribute_myDouble(myDouble) pyobj.set_attribute_myFloat(myFloat) pyobj.set_attribute_myInt(myInt) pyobj.set_attribute_myDateTime(myGDateTime) pyobj.set_attribute_myGDay(myGDateTime) pyobj.set_attribute_myGMonth(myGDateTime) pyobj.set_attribute_myGYear(myGDateTime) pyobj.set_attribute_myGYearMonth(myGDateTime) pyobj.set_attribute_myDate(myGDateTime) pyobj.set_attribute_myTime(myGDateTime) pyobj.set_attribute_myAnyURI(myAnyURI) pyobj.set_attribute_myString(myString) pyobj.set_attribute_myHexBinary(myHexBinary) pyobj.set_attribute_myDuration(myGDateTime) # Problems parsings pyobj.set_attribute_myQName(myQName) pyobj.set_attribute_myGMonthDay(myGDateTime) #TODO: #pyobj.set_attribute_myBase64Binary("") #pyobj.set_attribute_myNOTATION("NOT") sw = SoapWriter() sw.serialize(pyobj) soap = str(sw) ps = ParsedSoap(soap) pyobj2 = ps.Parse(pyobj.typecode) test = pyobj2.get_attribute_myInt() self.failUnlessEqual(myInt, test) test = pyobj2.get_attribute_myDouble() self.failUnlessEqual(myDouble, test) test = pyobj2.get_attribute_myFloat() self.failUnlessEqual(myFloat, test) test = pyobj2.get_attribute_myDecimal() self.failUnlessEqual(myDecimal, test) test = pyobj2.get_attribute_myAnyURI() self.failUnlessEqual(myAnyURI, test) test = pyobj2.get_attribute_myQName() self.failUnlessEqual(myQName, test) test = pyobj2.get_attribute_myString() self.failUnlessEqual(myString, test) test = pyobj2.get_attribute_myHexBinary() self.failUnlessEqual(myHexBinary, test) # DateTime stuff test = pyobj2.get_attribute_myDateTime() self.failUnlessEqual(myGDateTime[:-3], test[:-3]) test = pyobj2.get_attribute_myDate() self.failUnlessEqual(myGDateTime[:3], test[:3]) test = pyobj2.get_attribute_myTime() self.failUnlessEqual(myGDateTime[4:5], test[4:5]) test = pyobj.get_attribute_myDuration() self.failUnlessEqual(myGDateTime, test) # Bug [ 1453421 ] Incorrect format for type gDay test = pyobj2.get_attribute_myGDay() self.failUnlessEqual(myGDateTime[2], test[2]) test = pyobj2.get_attribute_myGMonth() self.failUnlessEqual(myGDateTime[1], test[1]) test = pyobj2.get_attribute_myGYear() self.failUnlessEqual(myGDateTime[0], test[0]) test = pyobj2.get_attribute_myGYearMonth() self.failUnlessEqual(myGDateTime[:2], test[:2]) # hmm? negated? #test = pyobj2.get_attribute_myGMonthDay() #self.failUnlessEqual(myGDateTime[1:3], test[1:3]) def test_local_empty_attribute(self): # [ 1452752 ] attribute with empty value doesn't appear in parsed object myString = "" pyobj = GED("urn:example", "Test1").pyclass() pyobj.set_attribute_myString(myString) sw = SoapWriter() sw.serialize(pyobj) soap = str(sw) print soap ps = ParsedSoap(soap) pyobj2 = ps.Parse(pyobj.typecode) test = pyobj2.get_attribute_myString() self.failUnlessEqual(myString, str(test)) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_Choice.py0000644000175100017510000000413710556451671015723 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException from ZSI.TC import _get_global_element_declaration as GED from ZSI.writer import SoapWriter """ Unittest for Bug Report [ 1441574 ] ZSI assumes minOccurs(1) for all parts WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ChoiceTestCase, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ChoiceTestCase, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ChoiceTestCase, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ChoiceTestCase, 'test_')) return suite class ChoiceTestCase(ServiceTestCase): name = "test_Choice" types_file_name = "test_Choice_xsd_types.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') self.wsdl2py_args.append('-x') def test_local_choice_default_facets_legal1(self): """ """ pyobj = GED("urn:example", "Easy").pyclass() pyobj.Rank = 1 sw = SoapWriter() sw.serialize(pyobj) print str(sw) def test_local_choice_maxOccurs_unbounded(self): """ """ pyobj = GED("urn:example", "Hard").pyclass() pyobj.Name = ["steve", "mark"] pyobj.Any = ["whatever"] pyobj.Rank = [2,3,4] sw = SoapWriter() sw.serialize(pyobj) print str(sw) if __name__ == "__main__" : main() ZSI-2.1-a1/test/wsdl2py/test_Clearspace.py0000644000175100017510000000623510645017634016570 0ustar zsizsi#!/usr/bin/env python ############################################################################ # Joshua R. Boverhof, LBNL # See LBNLCopyright for copyright notice! ########################################################################### import os, sys, unittest from ServiceTest import main, ServiceTestCase, ServiceTestSuite from ZSI import FaultException """ Unittest for contacting Clearspace blog webservice WSDL: """ # General targets def dispatch(): """Run all dispatch tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_dispatch')) return suite def local(): """Run all local tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_local')) return suite def net(): """Run all network tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_net')) return suite def all(): """Run all tests""" suite = ServiceTestSuite() suite.addTest(unittest.makeSuite(ServiceTest, 'test_')) return suite # NEED TO CREATE WSSE typecodes from ZSI.generate.commands import wsdl2py if not os.path.isdir('stubs'): os.makedirs('stubs') wsdl2py(['--complexType', '--schema','--output-dir=stubs', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd']) class BlogServiceTest(ServiceTestCase): """Test case for Clearspace sandbox, example how to use client WSSE:Security UsernameToken Profile admin password """ name = "test_Clearspace" client_file_name = "BlogService_client.py" types_file_name = "BlogService_types.py" server_file_name = "BlogService_server.py" def __init__(self, methodName): ServiceTestCase.__init__(self, methodName) self.wsdl2py_args.append('-b') def _get_soap_headers(self): import oasis_200401_wss_wssecurity_secext_1_0_xsd_types from ZSI.schema import GED security = GED("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security").pyclass() token = GED("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "UsernameToken").pyclass() security.Any = [token] token.Username = 'billy' klass = GED("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Password").pyclass token.Any = [klass('guest'),] return (security,) def test_net_Blogcount(self): loc = self.client_module.BlogServiceLocator() msg = self.client_module.getBlogCountRequest() port = loc.getBlogServiceHttpPort(**self.getPortKWArgs()) rsp = port.getBlogCount(msg, soapheaders=self._get_soap_headers(),) def test_local_(self): import oasis_200401_wss_wssecurity_secext_1_0_xsd_types return ServiceTest = BlogServiceTest if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_rfc2617.py0000644000175100017510000000333410556234235014210 0ustar zsizsi#!/usr/bin/env python """ RFC2617 HTTP Authentication: Basic and Digest Access Authentication """ import unittest from ZSI import digest_auth from ZSI.wstools.logging import setBasicLoggerDEBUG setBasicLoggerDEBUG() class DATestCase(unittest.TestCase): "test Union TypeCode" def check_challenge_single_www_authenticate_header(self): challenge='Basic realm="WallyWorld"' print "=="*30 print challenge print "=="*30 cd = digest_auth.fetch_challenge(challenge) expect = {'challenge': 'Basic', 'realm': 'WallyWorld'} self.failUnless(cd == expect, 'Expected equivalent') def check_challenge_single_www_authenticate_header2(self): challenge='Basic realm="Wally World"' cd = digest_auth.fetch_challenge(challenge) expect = {'challenge': 'Basic', 'realm': 'Wally World'} self.failUnless(cd == expect, 'Expected equivalent') def check_challenge_single_www_authenticate_header3(self): challenge = '''Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"''' cd = digest_auth.fetch_challenge(challenge) expect = {'nonce': 'dcd98b7102dd2f0e8b11d0f600bfb0c093', 'challenge': 'Digest', 'opaque': '5ccc069c403ebaf9f0171e9517f40e41', 'realm': 'testrealm@host.com', 'qop': 'auth,auth-int'} self.failUnless(cd == expect, 'Expected equivalent') def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(DATestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == '__main__': main() ZSI-2.1-a1/test/test_t1.py0000644000175100017510000002267510647242563013457 0ustar zsizsi#!/usr/bin/env python import unittest, sys, tests_good, tests_bad, time from ZSI import * try: import cStringIO as StringIO except ImportError: import StringIO class t1TestCase(unittest.TestCase): "Test case wrapper for old ZSI t1 test case" def setUp(self): self.goodTests = [] self.badTests = [] for key,val in tests_good.__dict__.items(): try: if key[0:4] == "test" and int(key[4:]) > 0: self.goodTests.append((key,val)) except: pass for key,val in tests_bad.__dict__.items(): try: if key[0:4] == "test" and int(key[4:]) > 0: self.badTests.append((key,val)) except: pass self.goodTests.sort(lambda a,b: cmp(a[0], b[0])) self.badTests.sort(lambda a,b: cmp(a[0], b[0])) def check_bug1724481(self): # [ 1724481 ] Error handling of enum serialization broken" enum = TC.Enumeration(['Red', 'Blue', 'Green'], 'color') sw = SoapWriter() self.assertRaises(EvaluateException, sw.serialize,'ddd', enum) def checkt1(self): for key,val in self.badTests: print "\n", "." * 60, key self.failUnlessRaises(ParseException, ParsedSoap, val) for key,val in self.goodTests: print "\n", "." * 60, key ps = ParsedSoap(val) ps = ParsedSoap(datatest) elts = ps.data_elements self.failUnlessEqual(TC.Integer(None, nillable=True).parse(elts[10], ps), None) self.failUnlessEqual(TC.Ibyte(None, nillable=True).parse(elts[10], ps), None) B = [ TC.Integer('Price'), TC.Integer('p2'), TC.String(unique=1) ] self.failUnlessEqual(TC.Integer(('test-uri', 'Price')).parse(elts[0], ps), 34) self.failUnlessEqual(B[0].parse(elts[0], ps), 34) self.failUnlessEqual(B[1].parse(elts[1], ps), 44) self.failUnlessEqual(B[2].parse(elts[2], ps), u"This is the name") self.failUnlessEqual(TC.HexBinaryString().parse(elts[9], ps), "? A") self.failUnlessEqual(TC.String('Name').parse(elts[2], ps), u"This is the name") self.failUnlessEqual(TC.Any('Price').parse(elts[0], ps), 34) self.failUnlessEqual(TC.Any('n3').parse(elts[4], ps), u"The value of n3") TC.XML('n2').parse(elts[3], ps) nodelist = TC.XML('a2').parse(elts[7], ps) self.failUnlessEqual(TC.String('n3').parse(elts[4], ps), u"The value of n3") self.failUnlessEqual(TC.Base64String('n64').parse(elts[5], ps), u"hello") self.failUnlessEqual(TC.String('n64').parse(elts[5], ps), u"a GVsbG8=") enum = TC.Enumeration(['Red', 'Blue', 'Green'], 'color') self.failUnlessEqual(enum.parse(elts[6], ps), u'Red') self.failUnlessEqual(TC.IEnumeration([44,46,47]).parse(elts[1],ps), 44) S = TC.Struct(None, [TC.String('t'), TC.Integer('i')], inorder=0) pyobj = S.parse(elts[8], ps) S2 = TC.Struct(myclass, [TC.IunsignedShort('i'), TC.String('q:z', minOccurs=0), TC.String('t')], 'a2', typed=0) pyobj2 = S2.parse(elts[8], ps) self.failUnlessEqual(TC.URI().parse(elts[12], ps), u'"http://foo.com/~salz"') self.failUnlessEqual(pyobj["i"], pyobj2.i) self.failUnlessEqual(pyobj["t"], pyobj2.t) tcary = TC.Array('SOAP-ENC:int', TC.Integer()) nsa = tcary.parse(elts[14],ps) self.failUnlessEqual(nsa, [None, None, None, 12, 13, 14, 15, 16, 17]) tcary.sparse = 1 sa = tcary.parse(elts[14],ps) self.failUnlessEqual(sa, [(3, 12), (4, 13), (5, 14), (6, 15), (7, 16), (8, 17)]) """ mychoice = TC.Choice([ TC.String('n3'), TC.URI('uri'), TC.Integer('Price'), ]) b = mychoice.parse(elts[0], ps) self.failUnlessEqual(b[0], 'Price') self.failUnlessEqual(b[1], 34) b = mychoice.parse(elts[12], ps) self.failUnlessEqual(b[0], 'uri') self.failUnlessEqual(b[1], u'"http://foo.com/~salz"') b = mychoice.parse(elts[4], ps) self.failUnlessEqual(b[0], 'n3') self.failUnlessEqual(b[1], u'The value of n3') """ self.failUnlessEqual(TC.Array(('test-uri','x'), TC.Any()).parse(elts[15], ps), [u'The value of n3', u'rich salz', 13]) self.failUnlessEqual(TC.Struct(None,(TC.FPfloat('a'), TC.Decimal('b'), TC.FPdouble('c'))).parse(elts[13],ps), {'a': 6.9000000000000004, 'c': TC._make_inf(), 'b': 0.0}) nsdict = ps.GetElementNSdict(ps.header) nsdict[''] = "http://www.zolera.com/ns/" nsdict['q'] = 'q-namespace-uri' sio = StringIO.StringIO() z = SoapWriter(sio, header=ps.header_elements, nsdict=nsdict) z.serialize(pyobj2, S2) S2.inline = 1 S2.typed = 0 tc = TC.gDateTime('dt') z.serialize(pyobj2, S2) z.serialize(pyobj, S) #z.serialize(('n3', '******this is the value of a union'), mychoice) z.serialize('uri:some/place/special', TC.XML('foo', nsdict=nsdict)) tcary.sparse = False z.serialize(nsa, tcary, childnames='tt') tcary.sparse = True z.serialize(sa, tcary, name='MYSPARSEARRAY') z.serialize(time.time(), tc) z.serialize(time.time(), TC.gTime('monthday')) z.serialize('$$$$$foo<', TC.String(textprotect=0)) self.failUnlessEqual(TC.Any().parse(elts[11], ps), {'urt-i': 12, 'urt-t': u'rich salz'}) try: a = bar() except Exception, e: f = FaultFromException(e, 0, sys.exc_info()[2]) print f.AsSOAP() print print print FaultFromNotUnderstood('myuri', 'dalocalname', actor='cher').AsSOAP() print print print FaultFromActor('actor:i:dont:understand').AsSOAP() def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t1TestCase, "check")) return suite ## exceptions def foo(): '''dummy''' return 3 / 0 def bar(): return foo() + 2 class zParseException: pass class myclass: def __init__(self, name=None): self.name = name or id(self) self.z = 'z value' def __str__(self): return 'myclass-%s-(%d,"%s")' % (self.name, self.i, self.t) + \ str(self.z) datatest = ''' you must grok sometag 34 44 This is the name Hello]]> a GVsbG8= Red 12rich salz 3F2041 12 rich salz "http://foo.com/%7Esalz" 6.9 -0 INF 12 13 14 15 16 17 //sarray The value of n3 content ond ''' def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/cgicli.py0000755000175100017510000000403307427543543013321 0ustar zsizsi#! /usr/bin/env python import getopt, socket, sys try: (opts, args) = getopt.getopt(sys.argv[1:], 'h:p:s', ( 'host=', 'port=', 'statusonly', 'help')) except getopt.GetoptError, e: print >>sys.stderr, sys.argv[0] + ': ' + str(e) sys.exit(1) if args: print sys.argv[0] + ': Usage error; try --help.' sys.exit(1) hostname, portnum, verbose = 'localhost', 80, 1 for opt, val in opts: if opt in [ '--help' ]: print '''Options include: --host HOST (-h HOST) Name of server host --port PORT (-p PORT) Port server is listening on --statusonly (-s) Do not output reply packets; just status code Default is -h%s -p%d -t%s''' % \ (hostname, portnum, ','.join([str(x) for x in tests])) sys.exit(0) if opt in [ '-h', '--host' ]: hostname = val elif opt in [ '-p', '--port' ]: portnum = int(val) elif opt in [ '-s', '--statusonly' ]: verbose = 0 IN = ''' ''' IN = ''' 1 2 ''' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((hostname, portnum)) f = s.makefile('r+') f.write('POST /cgi-bin/x HTTP/1.0\r\n') f.write('Content-type: text/xml; charset="utf-8"\r\n') f.write('Content-Length: %d\r\n\r\n' % len(IN)) f.write(IN) f.flush() status = f.readline() print status, while 1: l = f.readline() if l == '': break if verbose: print l, f.close() ZSI-2.1-a1/test/test_t8.py0000644000175100017510000001412510641306321013440 0ustar zsizsi#!/usr/bin/env python import unittest, sys, types, time from ZSI import TC, SoapWriter, ParsedSoap, EvaluateException from ZSI.wstools.Namespaces import SCHEMA, SOAP NSDICT = {'tns':'xmlns:tns="urn:a"', 'xsi':'xmlns:xsi="%s"' %SCHEMA.XSI3, 'xsd':'xmlns:xsd="%s"' %SCHEMA.XSD3, 'soap':'xmlns:SOAP-ENC="%s"' %SOAP.ENC, } class AnyTestCase(unittest.TestCase): "Test Any serialize and parse" def check_empty_array(self): """Empty Array returned as list() """ data = [] s = str(SoapWriter().serialize(data,TC.Any(aslist=True))) p = ParsedSoap(s).Parse(TC.Any()) self.failUnless(data==p, 'expecting "%s", got "%s"' %(data,p)) def check_empty_struct(self): """Empty Struct is None, maybe dict() makes more sense, but this is fairly hard to determine if not typed (which is the norm). """ data = {} s = str(SoapWriter().serialize(data,TC.Any())) p = ParsedSoap(s).Parse(TC.Any()) self.failUnless(p==None, 'expecting "%s", got "%s"' %(None,p)) def check_parse_empty_all(self): # None skip = [TC.FPEnumeration, TC.Enumeration, TC.IEnumeration, TC.List, TC.Integer] for typeclass in filter(lambda c: type(c) in [types.ClassType,type] and not issubclass(c, TC.String) and issubclass(c, TC.SimpleType), TC.__dict__.values()): if typeclass in skip: continue tc = typeclass() sw = SoapWriter() sw.serialize(None, typecode=tc, typed=True) soap = str(sw) ps = ParsedSoap(soap) parsed = ps.Parse(TC.Any()) self.assertEqual(None, parsed) def check_parse_empty_string(self): # Empty String typecodes = TC.Any.parsemap.values() for tc in filter(lambda c: isinstance(c, TC.String), TC.Any.parsemap.values()): sw = SoapWriter() sw.serialize("", typecode=tc, typed=True) soap = str(sw) ps = ParsedSoap(soap) parsed = ps.Parse(TC.Any()) self.assertEqual("", parsed) def check_builtins(self): myInt,myLong,myStr,myDate,myFloat = 123,2147483648,\ u"hello", time.gmtime(), 1.0001 orig = [myInt,myLong,myStr,myDate,myFloat] sw = SoapWriter() sw.serialize(orig, typecode=TC.Any(pname="builtins", aslist=True)) ps = ParsedSoap(str(sw)) parsed = ps.Parse(TC.Any()) self.assertEqual(len(orig), len(parsed)) self.assertEqual(myInt, parsed[0]) self.assertEqual(myLong, parsed[1]) self.assertEqual(myStr, parsed[2]) self.assertEqual(myDate[0:6], parsed[3][0:6]) self.assertEqual(myFloat, parsed[4]) self.assertEqual(type(myInt), type(parsed[0])) self.assertEqual(type(myLong), type(parsed[1])) self.assertEqual(str, type(parsed[2])) self.assertEqual(tuple, type(parsed[3])) self.assertEqual(type(myFloat), type(parsed[4])) def check_any_nill(self): result = ['23', {'a' : None, 'b': 5}] soap = str(SoapWriter().serialize(result, TC.Any(pname="NilRequest", nillable=True, aslist=True))) ps = ParsedSoap(soap) tc = TC.Any(nillable=True) pyobj = ps.Parse(tc) def check_any_compound(self): # from zsi developer's guide xml = """ 12 Hello world """ %NSDICT ps = ParsedSoap(xml, envelope=False) self.failUnless(ps.Parse(TC.Any()) == {'i': 12, 'name': 'Hello world'}) self.failUnless(ps.Parse(TC.Any(aslist=True)) == [12, 'Hello world']) def check_any_typed_soap_integer(self): # from zsi developer's guide value = 12 d = dict(value=value) d.update(NSDICT) xml = """%(value)d""" %d ps = ParsedSoap(xml, envelope=False) self.failUnless(ps.Parse(TC.Any()) == value) def check_any_typed_xsd_int(self): # from zsi developer's guide value = 12 d = dict(value=value) d.update(NSDICT) xml = """%(value)d""" %d ps = ParsedSoap(xml, envelope=False) self.failUnless(ps.Parse(TC.Any()) == value) def check_any_typed_nonNegativeInteger(self): # from zsi developer's guide value = 12 d = dict(value=value) d.update(NSDICT) xml = """%(value)d""" %d ps = ParsedSoap(xml, envelope=False) self.failUnless(ps.Parse(TC.Any()) == value) def check_any_untyped_int(self): # from zsi developer's guide d = dict(value=12) d.update(NSDICT) xml = """12""" %NSDICT ps = ParsedSoap(xml, envelope=False) self.failUnless(int(ps.Parse(TC.Any())) == 12) def check_any_dict_list_rpcenc(self): sw = SoapWriter() testObj = [{"a":1,"b":2}, {"d":4,"e":5}, {"f":{"x":9}, "g":[6,7.0]}] typecode = TC.Any(aslist=True) sw.serialize(testObj, typecode=typecode) xml = str(sw) ps = ParsedSoap(xml) result = TC.Any().parse(ps.body_root, ps) self.failUnless(result == testObj) # # Creates permutation of test options: "check", "check_any", etc # _SEP = '_' for t in [i[0].split(_SEP) for i in filter(lambda i: callable(i[1]), AnyTestCase.__dict__.items())]: test = '' for f in t: test += f if globals().has_key(test): test += _SEP; continue def _closure(): name = test def _makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(AnyTestCase, name)) return suite return _makeTestSuite globals()[test] = _closure() test += _SEP makeTestSuite = check def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_QName.py0000644000175100017510000000372510643543564014130 0ustar zsizsi#!/usr/bin/env python import unittest, sys, tests_good, tests_bad, time from ZSI import * try: import cStringIO as StringIO except ImportError: import StringIO """Bug [ 1520092 ] URI Bug: urllib.quote escaping reserved chars """ class TestCase(unittest.TestCase): def check_soapfault_faultcode(self): """ Typecode QName when default namespace is not declared, should specify the empty namespace. """ msg = """ ServerFaultCode Operation failed since VMware tools are not running in this virtual machine. """ from ZSI import ParsedSoap, FaultFromFaultMessage ps = ParsedSoap(msg) fault = FaultFromFaultMessage(ps) self.failUnless(fault.code == ('','ServerFaultCode'), 'faultcode should be (namespace,name) tuple') # # Creates permutation of test options: "check", "check_any", etc # _SEP = '_' for t in [i[0].split(_SEP) for i in filter(lambda i: callable(i[1]), TestCase.__dict__.items())]: test = '' for f in t: test += f if globals().has_key(test): test += _SEP; continue def _closure(): name = test def _makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCase, name)) return suite return _makeTestSuite globals()[test] = _closure() test += _SEP makeTestSuite = check def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main() ZSI-2.1-a1/test/test_union.py0000644000175100017510000000505610541637256014255 0ustar zsizsi#!/usr/bin/env python import unittest, sys, sha, base64 import ZSI from ZSI import _get_element_nsuri_name from ZSI.schema import GED, TypeDefinition, ElementDeclaration from ZSI.parse import ParsedSoap from ZSI.wstools.c14n import Canonicalize from ZSI.wstools.Namespaces import WSA200403, SOAP from cStringIO import StringIO # # Generated code class ns3: class localPAssertionId_Dec(ElementDeclaration): literal = "localPAssertionId" schema = "http://www.pasoa.org/schemas/version024/PStruct.xsd" def __init__(self, **kw): kw["pname"] = ("http://www.pasoa.org/schemas/version024/PStruct.xsd","localPAssertionId") kw["aname"] = "_localPAssertionId" if ns3.LocalPAssertionId_Def not in ns3.localPAssertionId_Dec.__bases__: bases = list(ns3.localPAssertionId_Dec.__bases__) bases.insert(0, ns3.LocalPAssertionId_Def) ns3.localPAssertionId_Dec.__bases__ = tuple(bases) ns3.LocalPAssertionId_Def.__init__(self, **kw) if self.pyclass is not None: self.pyclass.__name__ = "localPAssertionId_Dec_Holder" class LocalPAssertionId_Def(ZSI.TC.Union, TypeDefinition): memberTypes = [(u'http://www.w3.org/2001/XMLSchema', u'long'), (u'http://www.w3.org/2001/XMLSchema', u'string'), (u'http://www.w3.org/2001/XMLSchema', u'anyURI')] schema = "http://www.pasoa.org/schemas/version024/PStruct.xsd" type = (schema, "LocalPAssertionId") def __init__(self, pname, **kw): ZSI.TC.Union.__init__(self, pname, **kw) class UnionTestCase(unittest.TestCase): "test Union TypeCode" def setUp(self): pass def tearDown(self): pass def check_union_long(self): import time typecode = GED("http://www.pasoa.org/schemas/version024/PStruct.xsd", "localPAssertionId") for value in (1234455, "whatever", "urn:whatever"): sw = ZSI.SoapWriter() sw.serialize(value, typecode) xml = str(sw) ps = ParsedSoap(xml) pyobj = ps.Parse(typecode) # Union Limitation: # currently it tries to parse it sequentially via memberTypes, # so string is going to parse the URI when we want anyURI self.failUnless(value == pyobj, 'Expected equivalent') def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(UnionTestCase, "check")) return suite def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == '__main__': main() ZSI-2.1-a1/test/test_zsi_net.py0000644000175100017510000000061210643543564014572 0ustar zsizsi#!/usr/bin/env python import test_t4 import test_callhome from test_zsi import * def makeTestSuite(): return unittest.TestSuite( map(lambda t: globals()[t].makeTestSuite(), filter(lambda g: g.startswith('test_') and True, globals())) ) def main(): unittest.main(defaultTest="makeTestSuite") suite = unittest.TestSuite() if __name__ == "__main__" : main() ZSI-2.1-a1/test/tests_bad.py0000644000175100017510000001023307707636072014034 0ustar zsizsitest01 = ''' DIS ''' test02 = ''' 5 ''' test03 = ''' SOAP-ENV:MustUnderstand SOAP Must Understand Error ''' test04 = ''' SOAP-ENV:Server Server Error My application didn't work 1001 ''' test05 = ''' ''' test06 = ''' ''' test07 = ''' ''' test08 = ''' ''' test09 = ''' ''' test10 = ''' ''' test11 = ''' DEF ''' test12 = ''' DEF ''' test13 = ''' DEF ''' ZSI-2.1-a1/test/test_t2.py0000644000175100017510000000604310356606232013441 0ustar zsizsi#!/usr/bin/env python import unittest, sys from ZSI import * class t2TestCase(unittest.TestCase): "Test case wrapper for old ZSI t2 test case" def checkt2(self): try: ps = ParsedSoap(IN) except ParseException, e: print >>OUT, FaultFromZSIException(e).AsSOAP() self.fail() except Exception, e: # Faulted while processing; assume it's in the # header. print >>OUT, FaultFromException(e, 1).AsSOAP() self.fail() # We are not prepared to handle any actors or mustUnderstand elements. # Arbitrary fault back with the first one found. a = ps.WhatActorsArePresent() if len(a): print >>OUT, FaultFromActor(a[0]).AsSOAP() self.fail() mu = ps.WhatMustIUnderstand() if len(mu): uri, localname = mu[0] print >>OUT, FaultFromNotUnderstood(uri, localname).AsSOAP() self.fail() try: player = ps.Parse(Player) except EvaluateException, e: print >>OUT, FaultFromZSIException(e).AsSOAP() self.fail() try: import operator total = reduce(operator.add, player.Scores, 0) result = Average(foo(total, len(player.Scores))) sw = SoapWriter().serialize(result) print >>OUT, str(sw) except Exception, e: print >>OUT, FaultFromException(e, 0, sys.exc_info()[2]).AsSOAP() self.fail() def makeTestSuite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(t2TestCase, "check")) return suite class Player: '''Input class.''' def __init__(self, name=None): pass Player.typecode = TC.Struct(Player, [ TC.String('Name', optional=1), TC.Array('xsd:integer', TC.Integer(), 'Scores'), ], 'GetAverage') class Average: '''Output class.''' def __init__(self, average): self.average = average Average.typecode = TC.Struct(Average, [ TC.Integer('average'), ], 'GetAverageResponse', inline=1) def bar(total, len): return total / len def foo(total, len): return bar(total, len) OUT = sys.stdout IN=''' 84 101 200 4 John Doe ''' def main(): unittest.main(defaultTest="makeTestSuite") if __name__ == "__main__" : main()

Contents