Changeset 1110
- Timestamp:
- 12/04/07 17:08:44 (7 months ago)
- Files:
-
- trunk/src/main/php/net/stubbles/examples/pageelements/CurrentTimeXMLPageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/examples/pageelements/TestElementWithInjectedResource.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/examples/pageelements/TestShopPageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/examples/pageelements/TestXMLPageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisIncludeFilePageElement.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisIncludeTemplatePageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisLoadExtensionPageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisPageElement.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisProcessor.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/websites/stubAbstractPageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/websites/stubPageElement.php (modified) (3 diffs)
- trunk/src/main/php/net/stubbles/websites/xml/stubXMLPageElement.php (modified) (1 diff)
- trunk/src/main/php/net/stubbles/websites/xml/stubXMLPageElementCachingDecorator.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/websites/xml/stubXMLPageElementDecorator.php (modified) (8 diffs)
- trunk/src/main/php/net/stubbles/websites/xml/stubXMLPassThruPageElement.php (modified) (2 diffs)
- trunk/src/main/php/net/stubbles/websites/xml/stubXMLProcessor.php (modified) (2 diffs)
- trunk/src/test/php/net/stubbles/websites/memphis/stubMemphisIncludeFilePageElementTestCase.php (modified) (5 diffs)
- trunk/src/test/php/net/stubbles/websites/memphis/stubMemphisPageElementTestCase.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/main/php/net/stubbles/examples/pageelements/CurrentTimeXMLPageElement.php
r798 r1110 21 21 * processes the page element 22 22 * 23 * @param stubRequest $request the request data 24 * @param stubSession $session current session 25 * @param stubResponse $response contains response data 26 * @param array $context optional additional context data 23 * @return mixed 27 24 */ 28 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())25 public function process() 29 26 { 30 27 return array('currentTime' => date('Y-m-d H:i:s', time())); … … 34 31 * returns a list of form values 35 32 * 36 * @param stubRequest $request current request37 * @param stubSession $session current session38 33 * @return array<string,string> 39 34 */ 40 public function getFormValues( stubRequest $request, stubSession $session)35 public function getFormValues() 41 36 { 42 37 return array(); trunk/src/main/php/net/stubbles/examples/pageelements/TestElementWithInjectedResource.php
r908 r1110 41 41 * processes the page element 42 42 * 43 * @param stubRequest $request the request data 44 * @param stubSession $session current session 45 * @param stubResponse $response contains response data 46 * @param array $context optional additional context data 43 * @return mixed 47 44 */ 48 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())45 public function process() 49 46 { 50 47 $this->resource->incrementCount(); … … 55 52 * returns a list of form values 56 53 * 57 * @param stubRequest $request current request58 * @param stubSession $session current session59 54 * @return array<string,string> 60 55 */ 61 public function getFormValues( stubRequest $request, stubSession $session)56 public function getFormValues() 62 57 { 63 58 return array(); trunk/src/main/php/net/stubbles/examples/pageelements/TestShopPageElement.php
r1075 r1110 25 25 * processes the page element 26 26 * 27 * @param stubRequest $request the request data 28 * @param stubSession $session current session 29 * @param stubResponse $response contains response data 30 * @param array $context optional additional context data 31 * @retrun array<shop> 27 * @return mixed 32 28 */ 33 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())29 public function process() 34 30 { 35 31 $shop = new Shop(); … … 44 40 * returns a list of form values 45 41 * 46 * @param stubRequest $request current request47 * @param stubSession $session current session48 42 * @return array<string,string> 49 43 */ 50 public function getFormValues( stubRequest $request, stubSession $session)44 public function getFormValues() 51 45 { 52 46 $data = array(); 53 47 $validator = new stubPassThruValidator(); 54 if ($ request->hasValue('id') === true) {55 $data['id'] = $ request->getValidatedValue($validator, 'id');48 if ($this->request->hasValue('id') === true) { 49 $data['id'] = $this->request->getValidatedValue($validator, 'id'); 56 50 } 57 51 58 if ($ request->hasValue('title') === true) {59 $data['title'] = $ request->getValidatedValue($validator, 'title');52 if ($this->request->hasValue('title') === true) { 53 $data['title'] = $this->request->getValidatedValue($validator, 'title'); 60 54 } 61 55 62 if ($ request->hasValue('url') === true) {63 $data['url'] = $ request->getValidatedValue($validator, 'url');56 if ($this->request->hasValue('url') === true) { 57 $data['url'] = $this->request->getValidatedValue($validator, 'url'); 64 58 } 65 59 trunk/src/main/php/net/stubbles/examples/pageelements/TestXMLPageElement.php
r798 r1110 21 21 * processes the page element 22 22 * 23 * @param stubRequest $request the request data 24 * @param stubSession $session current session 25 * @param stubResponse $response contains response data 26 * @param array $context optional additional context data 23 * @return mixed 27 24 */ 28 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())25 public function process() 29 26 { 30 27 return array('foo' => 'Hello World!'); … … 34 31 * returns a list of form values 35 32 * 36 * @param stubRequest $request current request37 * @param stubSession $session current session38 33 * @return array<string,string> 39 34 */ 40 public function getFormValues( stubRequest $request, stubSession $session)35 public function getFormValues() 41 36 { 42 37 return array(); trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisIncludeFilePageElement.php
r930 r1110 63 63 * processes the page element 64 64 * 65 * @param stubRequest $request the request data 66 * @param stubSession $session current session 67 * @param stubResponse $response contains response data 68 * @param array $context optional additional context data 65 * @return string 69 66 * @throws stubIOException 70 67 */ 71 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())68 public function process() 72 69 { 73 70 $existsInBasePath = file_exists(self::$baseDir . DIRECTORY_SEPARATOR . $this->source); trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisIncludeTemplatePageElement.php
r936 r1110 49 49 * processes the page element 50 50 * 51 * @param stubRequest $request the request data 52 * @param stubSession $session current session 53 * @param stubResponse $response contains response data 54 * @param array $context optional additional context data 51 * @return string 55 52 * @throws stubIOException 56 53 */ 57 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())54 public function process() 58 55 { 59 if (isset($ context['template']) === false || ($context['template'] instanceof stubMemphisTemplate) === false) {56 if (isset($this->context['template']) === false || ($this->context['template'] instanceof stubMemphisTemplate) === false) { 60 57 throw new stubRuntimeException('Context contains no template of instance net.stubbles.websites.memphis.stubMemphisTemplate'); 61 58 } … … 66 63 } 67 64 68 $ context['template']->readTemplatesFromFile($this->source);69 return $ context['template']->getParsedTemplate($this->name);65 $this->context['template']->readTemplatesFromFile($this->source); 66 return $this->context['template']->getParsedTemplate($this->name); 70 67 } 71 68 } trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisLoadExtensionPageElement.php
r1039 r1110 52 52 * processes the page element 53 53 * 54 * @param stubRequest $request the request data 55 * @param stubSession $session current session 56 * @param stubResponse $response contains response data 57 * @param array $context optional additional context data 54 * @return string 58 55 * @throws stubIOException 59 56 */ 60 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())57 public function process() 61 58 { 62 if (isset($ context['template']) === false || ($context['template'] instanceof stubMemphisTemplate) === false) {59 if (isset($this->context['template']) === false || ($this->context['template'] instanceof stubMemphisTemplate) === false) { 63 60 throw new stubRuntimeException('Context contains no template of instance net.stubbles.websites.memphis.stubMemphisTemplate'); 64 61 } … … 74 71 } 75 72 76 $binder->bindConstant()->named('context')->to($ context);77 $binder->bind('stubRequest')->named('prefixed')->toInstance($ request);73 $binder->bindConstant()->named('context')->to($this->context); 74 $binder->bind('stubRequest')->named('prefixed')->toInstance($this->request); 78 75 $extension = $binder->getInjector()->getInstance($class->getName()); 79 76 return $extension->process(); trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisPageElement.php
r923 r1110 29 29 * key part and if the value of this member is inside of the configured parts. 30 30 * 31 * @param stubRequest $request the request data32 * @param stubSession $session current session33 * @param stubResponse $response contains response data34 * @param array $context optional additional context data35 31 * @return bool 36 32 */ 37 public function isAvailable( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())33 public function isAvailable() 38 34 { 39 if (isset($ context['part'])== false) {35 if (isset($this->context['part']) === false) { 40 36 return false; 41 37 } 42 38 43 if (count($this->parts) == 0) {39 if (count($this->parts) === 0) { 44 40 return true; 45 41 } 46 42 47 return in_array($ context['part'], $this->parts);43 return in_array($this->context['part'], $this->parts); 48 44 } 49 45 trunk/src/main/php/net/stubbles/websites/memphis/stubMemphisProcessor.php
r1098 r1110 137 137 protected function processElement(stubPageElement $element, stubRequest $request, array $context) 138 138 { 139 if ($element->isAvailable($request, $this->session, $this->response, $context) === false) { 139 $element->init($request, $this->session, $this->response, $context); 140 if ($element->isAvailable() === false) { 140 141 return ''; 141 142 } 142 143 143 144 try { 144 $content = $element->process( $request, $this->session, $this->response, $context);145 $content = $element->process(); 145 146 } catch (Exception $e) { 146 147 $content = 'An error occurred: ' . $e->getMessage(); trunk/src/main/php/net/stubbles/websites/stubAbstractPageElement.php
r797 r1110 22 22 */ 23 23 protected $name = ''; 24 /** 25 * the request 26 * 27 * @var stubRequest 28 */ 29 protected $request; 30 /** 31 * current session 32 * 33 * @var stubSession 34 */ 35 protected $session; 36 /** 37 * the created response 38 * 39 * @var stubResponse 40 */ 41 protected $response; 42 /** 43 * additional context data 44 * 45 * @var array<string,mixed> 46 */ 47 protected $context; 24 48 25 49 /** … … 54 78 55 79 /** 80 * initializes the page element 81 * 82 * @param stubRequest $request the request data 83 * @param stubSession $session current session 84 * @param stubResponse $response contains response data 85 * @param array<string,mixed> $context optional additional context data 86 */ 87 public function init(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()) 88 { 89 $this->request = $request; 90 $this->session = $session; 91 $this->response = $response; 92 $this->context = $context; 93 } 94 95 /** 56 96 * checks whether the page element is available or not 57 97 * 58 * @param stubRequest $request the request data59 * @param stubSession $session current session60 * @param stubResponse $response contains response data61 * @param array $context optional additional context data62 98 * @return bool 63 99 */ 64 public function isAvailable( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())100 public function isAvailable() 65 101 { 66 102 return true; trunk/src/main/php/net/stubbles/websites/stubPageElement.php
r798 r1110 41 41 42 42 /** 43 * checks whether the page element is available or not43 * initializes the page element 44 44 * 45 45 * @param stubRequest $request the request data … … 49 49 * @return bool 50 50 */ 51 public function isAvailable(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()); 51 public function init(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()); 52 53 /** 54 * checks whether the page element is available or not 55 * 56 * @return bool 57 */ 58 public function isAvailable(); 52 59 53 60 /** … … 57 64 * into the response! 58 65 * 59 * @param stubRequest $request the request data 60 * @param stubSession $session current session 61 * @param stubResponse $response contains response data 62 * @param array $context optional additional context data 66 * @return mixed content for page element 63 67 */ 64 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array());68 public function process(); 65 69 } 66 70 ?> trunk/src/main/php/net/stubbles/websites/xml/stubXMLPageElement.php
r596 r1110 19 19 * returns a list of form values 20 20 * 21 * @param stubRequest $request current request22 * @param stubSession $session current session23 21 * @return array<string,string> 24 22 */ 25 public function getFormValues( stubRequest $request, stubSession $session);23 public function getFormValues(); 26 24 } 27 25 ?> trunk/src/main/php/net/stubbles/websites/xml/stubXMLPageElementCachingDecorator.php
r798 r1110 29 29 * @param int 30 30 */ 31 public function setLifetime($lifetime) { 31 public function setLifetime($lifetime) 32 { 32 33 $this->lifetime = $lifetime; 33 34 } … … 36 37 * Tries to load the result from the cache or processes the page element. 37 38 * 38 * @param stubRequest $request the request data 39 * @param stubSession $session current session 40 * @param stubResponse $response contains response data 41 * @param array $context optional additional context data 39 * @return mixed 42 40 */ 43 public function process(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()) { 41 public function process() 42 { 44 43 $cacheFile = sprintf('%s/xml/elements/%s.cache', stubConfig::getCachePath(), $this->element->getName()); 45 if (file_exists($cacheFile) && (filemtime($cacheFile) + $this->lifetime) >= time()) {44 if (file_exists($cacheFile) === true && (filemtime($cacheFile) + $this->lifetime) >= time()) { 46 45 $data = unserialize(file_get_contents($cacheFile)); 47 46 if ($data instanceof stubSerializedObject) { 48 47 $data = $data->getUnserialized(); 49 48 } 49 50 50 return $data; 51 51 } 52 $data = $this->element->process($request, $session, $response); 52 53 $data = $this->element->process($this->request, $this->session, $this->response); 53 54 file_put_contents($cacheFile, serialize($data)); 54 55 return $data; trunk/src/main/php/net/stubbles/websites/xml/stubXMLPageElementDecorator.php
r798 r1110 7 7 * @subpackage websites 8 8 */ 9 stubClassLoader::load('net.stubbles.websites.xml.stubXMLPageElement' 10 ); 9 stubClassLoader::load('net.stubbles.websites.xml.stubXMLPageElement'); 11 10 /** 12 11 * Abstract base class for page element decorators … … 23 22 */ 24 23 protected $element; 24 /** 25 * the request 26 * 27 * @var stubRequest 28 */ 29 protected $request; 30 /** 31 * current session 32 * 33 * @var stubSession 34 */ 35 protected $session; 36 /** 37 * the created response 38 * 39 * @var stubResponse 40 */ 41 protected $response; 42 /** 43 * additional context data 44 * 45 * @var array<string,mixed> 46 */ 47 protected $context; 25 48 26 49 /** … … 29 52 * @param stubPageElement $element 30 53 */ 31 public function __construct(stubXMLPageElement $element) { 54 public function __construct(stubXMLPageElement $element) 55 { 32 56 $this->element = $element; 33 57 } … … 38 62 * @param string $name 39 63 */ 40 public function setName($name) { 64 public function setName($name) 65 { 41 66 $this->element->setName($name); 42 67 } … … 47 72 * @return string 48 73 */ 49 public function getName() { 74 public function getName() 75 { 50 76 return $this->element->getName(); 51 77 } … … 62 88 63 89 /** 90 * initializes the page element 91 * 92 * @param stubRequest $request the request data 93 * @param stubSession $session current session 94 * @param stubResponse $response contains response data 95 * @param array<string,mixed> $context optional additional context data 96 */ 97 public function init(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()) 98 { 99 $this->element->init($request, $session, $response, $context); 100 $this->request = $request; 101 $this->session = $session; 102 $this->response = $response; 103 $this->context = $context; 104 } 105 106 /** 64 107 * checks whether the page element is available or not 65 108 * 66 * @param stubRequest $request the request data67 * @param stubSession $session current session68 * @param stubResponse $response contains response data69 * @param array $context optional additional context data70 109 * @return bool 71 110 */ 72 public function isAvailable(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()) { 73 return $this->element->isAvailable($request, $session, $response, $context); 111 public function isAvailable() 112 { 113 return $this->element->isAvailable(); 74 114 } 75 115 … … 80 120 * into the response! 81 121 * 82 * @param stubRequest $request the request data 83 * @param stubSession $session current session 84 * @param stubResponse $response contains response data 85 * @param array $context optional additional context data 122 * @return mixed 86 123 */ 87 public function process(stubRequest $request, stubSession $session, stubResponse $response, array $context = array()) { 88 return $this->element->process($request, $session, $response); 124 public function process() 125 { 126 return $this->element->process(); 89 127 } 90 128 … … 92 130 * returns a list of form values 93 131 * 94 * @param stubRequest $request current request95 * @param stubSession $session current session96 132 * @return array<string,string> 97 133 */ 98 public function getFormValues( stubRequest $request, stubSession $session)134 public function getFormValues() 99 135 { 100 return $this->element->getFormValues( $request, $session);136 return $this->element->getFormValues(); 101 137 } 102 138 trunk/src/main/php/net/stubbles/websites/xml/stubXMLPassThruPageElement.php
r831 r1110 72 72 * returns a list of form values 73 73 * 74 * @param stubRequest $request current request75 * @param stubSession $session current session76 74 * @return array<string,string> 75 * @XMLIgnore() 77 76 */ 78 public function getFormValues( stubRequest $request, stubSession $session)77 public function getFormValues() 79 78 { 80 79 return array(); … … 84 83 * processes the page element 85 84 * 86 * @param stubRequest $request the request data 87 * @param stubSession $session current session 88 * @param stubResponse $response contains response data 89 * @param array $context optional additional context data 85 * @return mixed 86 * @XMLIgnore() 90 87 */ 91 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())88 public function process() 92 89 { 93 90 return $this; trunk/src/main/php/net/stubbles/websites/xml/stubXMLProcessor.php
r1057 r1110 68 68 } 69 69 70 if ($element->isAvailable($prefixRequest, $this->session, $this->response) == false) { 70 $element->init($prefixRequest, $this->session, $this->response); 71 if ($element->isAvailable() == false) { 71 72 continue; 72 73 } 73 74 74 $data = $element->process( $prefixRequest, $this->session, $this->response);75 $data = $element->process(); 75 76 if ($prefixRequest->isCancelled() === true) { 76 77 return; … … 79 80 $xmlSerializer->serialize($data, $xmlStreamWriter, array(stubXMLSerializer::OPT_ROOT_TAG => $name)); 80 81 if ($element instanceof stubXMLPageElement) { 81 $formValues[$name] = $element->getFormValues( $prefixRequest, $this->session);82 $formValues[$name] = $element->getFormValues(); 82 83 } 83 84 } trunk/src/test/php/net/stubbles/websites/memphis/stubMemphisIncludeFilePageElementTestCase.php
r812 r1110 8 8 */ 9 9 stubClassLoader::load('net.stubbles.websites.memphis.stubMemphisIncludeFilePageElement'); 10 Mock::generate('stubRequest');11 Mock::generate('stubSession');12 Mock::generate('stubResponse');13 10 /** 14 11 * Tests for net.stubbles.websites.memphis.stubMemphisIncludeFilePageElement. … … 25 22 */ 26 23 protected $includeFilePageElement; 27 /**28 * mocked request instance29 *30 * @var SimpleMock31 */32 protected $mockRequest;33 /**34 * mocked session instance35 *36 * @var SimpleMock37 */38 protected $mockSession;39 /**40 * mocked response instance41 *42 * @var SimpleMock43 */44 protected $mockResponse;45 24 46 25 /** … … 49 28 public function setUp() 50 29 { 51 $this->mockRequest = new MockstubRequest();52 $this->mockSession = new MockstubSession();53 $this->mockResponse = new MockstubResponse();54 30 $this->includeFilePageElement = new stubMemphisIncludeFilePageElement(); 55 31 } … … 81 57 { 82 58 $this->includeFilePageElement->setSource(TEST_SRC_PATH . '/resources/contentFile.txt'); 83 $this->assertEqual($this->includeFilePageElement->process( $this->mockRequest, $this->mockSession, $this->mockResponse), 'This is the content.');59 $this->assertEqual($this->includeFilePageElement->process(), 'This is the content.'); 84 60 } 85 61 … … 91 67 $this->includeFilePageElement->setSource(TEST_SRC_PATH . '/resources/doesNotExist'); 92 68 $this->expectException('stubException'); 93 $this->includeFilePageElement->process( $this->mockRequest, $this->mockSession, $this->mockResponse);69 $this->includeFilePageElement->process(); 94 70 } 95 71 } trunk/src/test/php/net/stubbles/websites/memphis/stubMemphisPageElementTestCase.php
r923 r1110 22 22 * processes the page element 23 23 * 24 * @param stubRequest $request the request data 25 * @param stubSession $session current session 26 * @param stubResponse $response contains response data 27 * @param array $context optional additional context data 24 * @return mixed 28 25 */ 29 public function process( stubRequest $request, stubSession $session, stubResponse $response, array $context = array())26 public function process() 30 27 { 31 28 // intentionally empty … … 82 79 { 83 80 $context = array('part' => 'dummy'); 84 $this->assertFalse($this->memphisPageElement->isAvailable($this->mockRequest, $this->mockSession, $this->mockResponse)); 85 $this->assertTrue($this->memphisPageElement->isAvailable($this->mockRequest, $this->mockSession, $this->mockResponse, $context)); 81 $this->memphisPageElement->init($this->mockRequest, $this->mockSession, $this->mockResponse); 82 $this->assertFalse($this->memphisPageElement->isAvailable()); 83 $this->memphisPageElement->init($this->mockRequest, $this->mockSession, $this->mockResponse, $context); 84 $this->assertTrue($this->memphisPageElement->isAvailable()); 86 85 $this->memphisPageElement->setParts('foo,bar, baz'); 87 $this->assertFalse($this->memphisPageElement->isAvailable($this->mockRequest, $this->mockSession, $this->mockResponse, $context)); 86 $this->memphisPageElement->init($this->mockRequest, $this->mockSession, $this->mockResponse, $context); 87 $this->assertFalse($this->memphisPageElement->isAvailable()); 88 88 $context = array('part' => 'foo'); 89 $this->assertTrue($this->memphisPageElement->isAvailable($this->mockRequest, $this->mockSession, $this->mockResponse, $context)); 89 $this->memphisPageElement->init($this->mockRequest, $this->mockSession, $this->mockResponse, $context); 90 $this->assertTrue($this->memphisPageElement->isAvailable()); 90 91 $context = array('part' => 'bar'); 91 $this->assertTrue($this->memphisPageElement->isAvailable($this->mockRequest, $this->mockSession, $this->mockResponse, $context)); 92 $this->memphisPageElement->init($this->mockRequest, $this->mockSession, $this->mockResponse, $context); 93 $this->assertTrue($this->memphisPageElement->isAvailable()); 92 94 $context = array('part' => 'baz'); 93 $this->assertTrue($this->memphisPageElement->isAvailable($this->mockRequest, $this->mockSession, $this->mockResponse, $context)); 95 $this->memphisPageElement->init($this->mockRequest, $this->mockSession, $this->mockResponse, $context); 96 $this->assertTrue($this->memphisPageElement->isAvailable()); 94 97 } 95 98 }
