7baa1587c7e87f16a6a1d45272a41476cedc45e5
[smartapi.git] / Common / Python / SmartAPI / tests / TestSequences.py
1 #!/usr/bin/python
2
3 """ 
4 """
5
6 import sys
7
8 import datetime
9 import urllib2
10 import httplib
11 from urlparse import urlparse
12
13
14 from SmartAPI.model.Capacity import Capacity
15 from SmartAPI.model.Evaluation import Evaluation
16 from SmartAPI.model.SystemOfInterest import SystemOfInterest
17 from SmartAPI.model.TemporalContext import TemporalContext
18 from SmartAPI.model.Input import Input
19 from SmartAPI.model.Output import Output
20 from SmartAPI.model.Activity import Activity
21 from SmartAPI.model.Address import Address
22 from SmartAPI.model.AliveRequest import AliveRequest
23 from SmartAPI.model.Availability import Availability
24 from SmartAPI.model.Status import Status
25 from SmartAPI.model.Response import Response
26 from SmartAPI.model.InterfaceAddress import InterfaceAddress
27 from SmartAPI.model.TimeSeries import TimeSeries
28 from SmartAPI.model.ValueObject import ValueObject
29 from SmartAPI.rdf.Variant import Variant
30 from SmartAPI.model.Map import Map
31 from SmartAPI.model.Organization import Organization
32 from SmartAPI.model.PhysicalEntity import PhysicalEntity
33 from SmartAPI.model.Service import Service
34 from SmartAPI.model.Size import Size
35 from SmartAPI.model.Velocity import Velocity
36 from SmartAPI.model.Orientation import Orientation
37 from SmartAPI.model.Direction import Direction
38 from SmartAPI.model.Parameter import Parameter
39 from SmartAPI.model.Waypoints import Waypoints
40 from SmartAPI.model.Waypoint import Waypoint
41 from SmartAPI.model.Address import Address
42 from SmartAPI.model.Route import Route
43 from SmartAPI.model.Coordinates import Coordinates
44 from SmartAPI.model.Request import Request
45 from SmartAPI.model.UnitPriceSpecification import UnitPriceSpecification
46 from SmartAPI.model.PropertyDependentPriceSpecification import PropertyDependentPriceSpecification
47 from SmartAPI.model.SomeItems import SomeItems
48 from SmartAPI.model.Condition import Condition
49 from SmartAPI.model.Offering import Offering
50 from SmartAPI.model.Transaction import Transaction
51 from SmartAPI.model.Entity import Entity
52 from SmartAPI.model.Device import Device
53 from SmartAPI.model.Service import Service
54 from SmartAPI.model.Obj import Obj
55 from SmartAPI.factory.Factory import Factory
56 from SmartAPI.factory.RequestFactory import RequestFactory
57 from SmartAPI.factory.ResponseFactory import ResponseFactory
58 from SmartAPI.factory.CommandFactory import CommandFactory
59
60 from SmartAPI.common.Tools import Tools
61 from SmartAPI.common.SmartAPICrypto import SmartAPICrypto
62 from SmartAPI.common.SERIALIZATION import SERIALIZATION
63 from SmartAPI.common.RESOURCE import RESOURCE
64 from SmartAPI.common.PROPERTY import PROPERTY
65 from SmartAPI.common.DATATYPE import DATATYPE
66 from SmartAPI.common.NS import NS
67 from SmartAPI.common.CryptoKeyWallet import CryptoKeyWallet
68 from SmartAPI.agents.OntologyAgent import OntologyAgent
69
70 from SmartAPI.agents.RegistrationAgent import RegistrationAgent
71 from SmartAPI.agents.SearchAgent import SearchAgent
72 from SmartAPI.agents.TransactionAgent import TransactionAgent
73
74 from SmartAPI.rdf.LinkedList import LinkedList
75 from SmartAPI.rdf.OrderedList import OrderedList
76 from SmartAPI.rdf.ItemizedList import ItemizedList
77 from SmartAPI.rdf.NudeList import NudeList
78
79 from rdflib import URIRef
80 from Crypto.PublicKey import RSA
81 import os
82 import uuid
83 import base64
84 import isodate
85 import datetime
86 import random
87 import traceback
88 from datetime import timedelta
89 from SmartAPI.common.URLs import KEYSERVER_URI
90
91
92 def objectCopyTest():
93     fromObject = PhysicalEntity()
94     size = Size()
95     speed = Velocity()
96     alternativeSpeed = Velocity()
97     
98     size.setWidth(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(100)))
99     size.setHeight(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(301.9)))
100     size.setDepth(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(11.222)))
101     
102     speed.setLinearVelocityX(ValueObject(unit = URIRef(NS.UNIT + "MeterPerSecond"), value = Variant(3.4)))
103     speed.setLinearVelocityY(ValueObject(unit = NS.UNIT + "MeterPerSecond", value = Variant(30.1)))
104     speed.setAngularVelocityY(ValueObject(unit = NS.UNIT + "RadianPerSecond", value = Variant(54.3)))
105     
106     alternativeSpeed.setAngularVelocityY(ValueObject(unit = NS.UNIT + "RadianPerSecond", value = Variant(10.1)))
107     
108     fromObject.addType(RESOURCE.CAR)
109     fromObject.setName("This is the source");
110     fromObject.setVelocity(speed);
111     fromObject.setSize(size);
112     
113     fromObject.setWeight(ValueObject(unit = NS.UNIT + "Kilogram", value = Variant(222)))
114     fromObject.add(URIRef(PROPERTY.ADDITIONAL_NAME), "An additional name has been set")
115     fromObject.add(URIRef(PROPERTY.AVERAGEVELOCITY), alternativeSpeed)
116     
117     print "Serialized original:"
118     print Tools().toString(fromObject, SERIALIZATION.TURTLE)
119     
120     toObject = PhysicalEntity()
121     Tools.copy(fromObject, toObject)
122     
123     print "Serialized copy:"
124     print Tools().toString(toObject, SERIALIZATION.TURTLE)
125     
126     print "Changing the copy"
127     print "-----------------"
128     toObjectSize = Size()
129     size.setWidth(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(2000)))
130     toObject.setSize(toObjectSize);
131     
132     print "Serialized original:"
133     print Tools().toString(fromObject, SERIALIZATION.TURTLE)
134     print "Serialized copy:"
135     print Tools().toString(toObject, SERIALIZATION.TURTLE)
136     
137     
138 def serializeRequestTest():
139
140     sampleValue = 9
141
142     targetSystemUri = "http://localhost:8099/seas/v1.0/access/";
143     myId = "http://seasdemos.asema.com/csharp/controlcommandsender/Cabcd";
144     targetId = "http://seasdemos.asema.com/csharp/controlcommandreceiver/Cabcd";
145     sourceIdentity = "http://seasexamples.asema.com/dataservers/timeseries";
146     myIdentity = "http://seasexamples.asema.com/datafetchers/timeseries";
147
148     print "Test routine for request serialization";
149
150     seriesEnd = datetime.datetime.now()
151     seriesStart = seriesEnd - datetime.timedelta(days = 7)
152
153     request_vars = []
154     request_vars.append(("Temperature", "DegreeCelsius"))
155     request_vars.append(("Cloudiness", "Percent"))
156     request_vars.append(("Precipitation", "MilliMeter"))
157
158     tsRequest = RequestFactory().create(myIdentity);
159
160     system = SystemOfInterest()
161     system.setSameAs(sourceIdentity)
162     system.setSessionKey("Measurement")
163     tsRequest.setSystemOfInterest(system)
164
165     tc = TemporalContext()
166     tc.setStart(seriesStart)
167     tc.setEnd(seriesEnd)
168     tc.setDuration(2,2,2,2,2,2)
169    
170     a = Activity()
171     i = Input()
172     i.setTemporalContext(tc)
173     a.setInput(i)
174     tsRequest.setActivity(a)
175     
176     if len(request_vars) == 1:
177         tsRequest.setQuantity(NS.SMARTAPI + request_vars[0][0])
178         tsRequest.setUnit(NS.SMARTAPI + request_vars[0][1])
179     else:
180         for idx in range(len(request_vars)):
181             v = ValueObject()
182             sampleValue += 1
183             v.setQuantity(NS.SMARTAPI + request_vars[idx][0])
184             v.setUnit(NS.SMARTAPI + request_vars[idx][1])
185             v.setValue(Variant(sampleValue))
186             tsRequest.addValueObject(v)
187
188     payload = Tools().toString(tsRequest, SERIALIZATION.TURTLE)
189     print "Serialze to String ..."
190     print payload
191     print "parse back to request object..."
192     newPayload = Request.fromString(payload, SERIALIZATION.TURTLE)
193     print "and serialze back ...."
194     print "***End ", newPayload.firstActivity().firstInput().getTemporalContext().getEnd()
195     print Tools().toString(newPayload, SERIALIZATION.TURTLE)
196     
197     
198     return tsRequest
199
200
201 def requestResponseTest3():
202     '''
203     This test case is copied and modified from Java version
204     '''
205         
206     clientIdentity = "http://www.client.com/seas/Cclient"
207     serverIdentity = "http://www.server.com/seas/Cserver"
208    
209     #get sessionKey  
210     crypto = SmartAPICrypto() 
211     sessionKey = crypto.generateSymmetricKey()  
212     
213     print "\n\nREQUEST/RESPONSE, TEST 3"
214     print '\n------------REQUEST part test -----------------------\n'
215     # Send request
216     rc = RequestFactory().create(clientIdentity)
217     rc.setMethod(RESOURCE.READ);
218     a = Activity()
219     i = Input()
220     a.addInput(i)
221     i.setSystemOfInterestWithSameAs("http://a.com/b")
222     
223     i2 = Input()
224     a.addInput(i2)
225     i2.setSystemOfInterestWithSameAs("http://additional.com/b")
226     
227     rc.addActivity(a);
228     
229     serializedRequest, ct = Tools.serializeRequest(rc, SERIALIZATION.RDF_XML )#'text/turtle')
230     print "\n ****** REQUEST in RDF/XML:***** \n", serializedRequest
231     print "Request Content-Type:  ", ct
232         
233     # Receive request
234     rs = Tools.parseRequest(serializedRequest, None, SERIALIZATION.RDF_XML)
235     clientId = rs.getGeneratedBy()
236     aa = rs.getActivities()[0]
237     ii = aa.getInputs()[0]
238     print "Request, sys of interest ", ii.getSystemOfInterest().getSameAs().getIdentifierUri(), " from ", clientId
239     
240     
241     print '\n------------RESPONSE part test -----------------------\n'
242     # Send response
243     resp = ResponseFactory().create(serverIdentity)
244     resp.setMethod(RESOURCE.READ)
245     ars = Activity()
246     
247     ors = Output()
248     ars.addOutput(ors)
249     ors.setSystemOfInterestWithSameAs("http://a.com/b")
250     ors.encrypt(sessionKey)
251     
252     ors2 = Input()
253     ars.addInput(ors2)
254     ors2.setSystemOfInterestWithSameAs("http://additional.com/b")
255     ors2.encrypt(sessionKey)
256     
257     resp.addActivity(ars)
258         
259     serializedResponse, ct2 = Tools.serializeResponse(resp, SERIALIZATION.TURTLE) #'text/turtle')
260     print "\n **** RESPONSE in turtle (encrypting Input and Output with Session key):****\n", serializedResponse
261     print "Response Content-Type:  ", ct2
262         
263     # Receive response
264     respc = Tools.parseResponse(serializedResponse, ct2, SERIALIZATION.TURTLE)
265     print 'DEBUG: ', len(Tools.messagePartsForParse)
266     print '\n...reserialize whole Response to String using plain old toString().....'
267     print Tools().toString(respc, SERIALIZATION.TURTLE)
268     
269     serverId = respc.getGeneratedBy()
270     ac = respc.getActivities()[0]
271     oc = ac.getOutputs()[0]
272     ic = ac.getInputs()[0]
273    
274     oc_parsed = oc.decrypt(sessionKey);
275     ic_parsed = ic.decrypt(sessionKey);
276     print '\n...After decrypting, reserialize the recovered Output to String using plain old toString() .....'
277     print Tools().toString(oc_parsed, SERIALIZATION.TURTLE)
278     print "\nResponse, sys of interest ", oc_parsed.getSystemOfInterest().getSameAs().getIdentifierUri(), " from ", serverId
279     print '\n...After decrypting, reserialize the recovered Input to String using plain old toString() .....'
280     print Tools().toString(ic_parsed, SERIALIZATION.TURTLE)
281     
282     
283     print '\n ======= now encrypt REQUEST with public key ========'
284     privKey = SmartAPICrypto().loadPrivateKey('testkey_private.pem')
285     pubKey = SmartAPICrypto().downloadPublicKey(clientId, KEYSERVER_URI)
286     
287     rc.encrypt(pubKey)
288     serializedRequest2, ct2 = Tools.serializeRequest(rc)
289     print 'REQUEST in turtle (encrypt with public key).....'
290     print serializedRequest2
291     rc_recovered = Tools.parseRequest(serializedRequest2, ct2)
292     if rc_recovered.isEncrypted() and rc_recovered.getEncryptionKeyType() == RESOURCE.PUBLICKEY:
293         rc_recovered = rc_recovered.decrypt(privKey)
294         print ' after parsing and decrypting, we get: '
295         rc_recovered.turtlePrint()
296     
297     ac2 = rc_recovered.getActivities()[0]
298     ac2.encrypt(pubKey)
299     serializedRequest3, ct3 = Tools.serializeRequest(rc_recovered)
300     print '.....REQUEST in turtle with Activity being encrypted (encrypt with public key).....'
301     print serializedRequest3
302     
303     rc_recovered3 = Tools.parseRequest(serializedRequest3, ct3)
304     if rc_recovered3.getActivities()[0].isEncrypted():
305         rc_recovered4 = rc_recovered3.getActivities()[0].decrypt(privKey)
306         print ' after parsing and decrypting, we get: '
307         rc_recovered4.turtlePrint()
308     
309
310 def requestResponseTest4():
311     '''
312     it tests key handling, message serialization/parsing, and signature verification
313     '''
314         
315     clientIdentity = "http://www.client.com/seas/Cclient"
316     serverIdentity = "http://www.server.com/seas/Cserver"
317          
318     current_path = os.getcwd()
319 #     pubKey = getPemPublicKey(os.path.join(current_path, "testkey_public.pem"))
320 #     privKey = getPemPrivateKey(os.path.join(current_path,"testkey_private.pem"))
321     #privKey, pubKey = SmartAPICrypto().generateKeyPair() 
322     
323     privKey = SmartAPICrypto().loadPrivateKey('testkey_private.pem')
324     
325     print '\n\nREQUEST/RESPONSE, TEST 4 (request and response with signed data) '
326      # Send request
327     rc = RequestFactory().create(clientIdentity)
328     rc.setMethod(RESOURCE.READ);
329     a = Activity()
330     i = Input()
331     a.addInput(i)
332     i.setSystemOfInterestWithSameAs("http://a.com/b")
333     rc.addActivity(a);
334     
335     print 'run turtlePrint() function for request ....'
336     rc.turtlePrint()
337     
338     rc.sign(privKey)    
339     serializedRequest, ct = Tools.serializeRequest(rc, 'turtle')
340     print "REQUEST, after signing, no outer header :\n", serializedRequest
341     print "Request Content-Type:  ", ct    
342     print '--------  end of request ----------'
343     
344     serializedRequest = serializedRequest.replace('Read', 'Write')
345     # Receive request    
346     rs = Tools.parseRequest(serializedRequest, ct)
347     print ':::: here is rs ::::'
348     rs.turtlePrint()
349     clientId = rs.getGeneratedBy()
350     aa = rs.getActivities()[0]
351     ii = aa.getInputs()[0]
352     print "Request, sys of interest ", ii.getSystemOfInterest().getSameAs().getIdentifierUri(), " from ", clientId
353     
354     pubKey = SmartAPICrypto().downloadPublicKey(clientId, KEYSERVER_URI)
355     
356     print 'verifying signature succeed? ', rs.verifySignature(pubKey)
357     
358     print '\n------------RESPONSE part test -----------------------\n'
359     # Send response
360     resp = ResponseFactory().create(serverIdentity)
361     resp.setMethod(RESOURCE.READ)
362     ars = Activity()
363     
364     ors = Output()
365     ars.addOutput(ors)
366     ors.setSystemOfInterestWithSameAs("http://a.com/b")
367         
368     ors.sign(privKey)
369     resp.addActivity(ars)
370         
371     serializedResponse, ct2 = Tools.serializeResponse(resp, 'turtle', False)
372     print "RESPONSE with outer MIME header:\n", serializedResponse
373     print "Response Content-Type:  ", ct2
374         
375     # Receive response    
376     respc = Tools.parseResponse(serializedResponse)
377     print 'DEBUG: ', len(Tools.messagePartsForParse)
378     print '\n...reserialize whole Response to String using plain old toString().....'
379     print Tools().toString(respc, SERIALIZATION.TURTLE)
380     
381     serverId = respc.getGeneratedBy()
382     ac = respc.getActivities()[0]        
383     oc = ac.getOutputs()[0]
384     print '....... reserialize the recovered Output to String using plain old toString() .....'
385     print Tools().toString(oc, SERIALIZATION.TURTLE)  
386     if oc.isSigned():  
387         verified = oc.verifySignature(pubKey)
388         print "Signature verification successful?: ", verified 
389     print "Response, sys of interest ", oc.getSystemOfInterest().getSameAs().getIdentifierUri()
390
391
392 def notaryKeyStoreTest():
393     myId = "http://seas.test.asema.com/notarykeytest"
394     referenceId = "http://seas.test.asema.com/notarykeytest/ref1"+uuid.uuid4().get_hex()   
395     content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in lectus at sem commodo venenatis. Fusce in eros ex. In hac habitasse platea dictumst. Phasellus dignissim, augue vel aliquet pretium, nibh eros tristique est, dignissim aliquet elit justo vel mauris. Vestibulum a posuere nulla. Curabitur aliquam semper sagittis."
396     content = content + uuid.uuid4().get_hex()
397
398     pubKey = getPemPublicKey("testkey_public.pem")
399     privKey = getPemPrivateKey("testkey_private.pem")
400     # save these key pairs to keywallet Class, which will used later in TransactionAgent.sendKeyToNotary()
401     
402     CryptoKeyWallet.setPublicKey(pubKey)
403     CryptoKeyWallet.setPrivateKey(privKey)
404     
405     crypto = SmartAPICrypto()
406     
407     notary = TransactionAgent.getDefaultNotary()
408     sessionKey = crypto.generateSymmetricKey()
409     #  save the key to string
410     sessionKeySent = base64.b64encode(sessionKey)
411     contentHash = crypto.createEncodedMessageDigest(content)
412     signature = crypto.sign(privKey, contentHash)
413     sentOK = TransactionAgent.sendKeyToNotary(myId, referenceId, contentHash, sessionKeySent, signature, notary)
414     sessionKeyReceived = TransactionAgent.fetchKeyFromNotary(myId, referenceId, contentHash, signature, notary)
415     
416     print 'Sent OK?: ', sentOK
417     print 'Send key: ', sessionKeySent
418     print 'Receive key: ', sessionKeyReceived
419     print 'Keys match?: ', sessionKeySent==sessionKeyReceived 
420     
421     # test encryptAndNotarize() method
422     print '\n ---- Now test Obj.encryptAndNotarize()----'
423     resp = ResponseFactory().create('http://www.server.com/seas/Cserver')
424     resp.setMethod(RESOURCE.READ)
425     ars = Activity()
426     
427     ors = Output()
428     ars.addOutput(ors)
429     ors.setSystemOfInterestWithSameAs("http://a.com/b")
430     ors.encryptAndNotarize(notary, pubKey, myId)
431     resp.addActivity(ars)
432     
433     serializedResponse, ct2 = Tools.serializeResponse(resp, 'text/turtle')
434     print "RESPONSE:\n", serializedResponse
435     
436     keyReceived = TransactionAgent.fetchKeyFromNotary(myId, ors.getIdentifierUri(), 
437                                                       ors.getHashCode(), ors.getSignature(), notary)
438     print 'Receive key: ', keyReceived
439
440
441 def unitPriceSpecificationTest():
442     '''
443     Test UnitPriceSpecification class parse/serialize
444     '''
445     myIdentity = "http://seasexamples.asema.com/pricefetcher"
446     ps = UnitPriceSpecification(myIdentity)
447     ps.setGrDescription("A subclass of GrObj")
448     ps.setGeneratedAt(datetime.datetime.now())
449     ps.setGrName("Price Fetching service")
450     ps.setCurrency("EUR")
451     ps.setCurrencyValue(3.12)
452     ps.setSameAs("http://bogus.same.as")
453     ps.setValidFrom(datetime.datetime.now())
454     ps.setQuantity(RESOURCE.ENERGYANDWORK)
455     ps.setUnit(RESOURCE.KILOWATTHOUR)
456    
457     ps.addType(RESOURCE.PRICE)
458     ps.setValueAddedTaxIncluded(False)
459     ps.setVatPercentage(Variant(100.2))
460     
461     print "        ---------",ps.getGrDescription()
462     print "        .....serialize UnitPriceSpecification object to string... "
463     st = Tools().toString(ps, SERIALIZATION.TURTLE)
464     print "        ", st
465     print "        parse back to UNITPriceSpecification object..."
466     model = Tools().fromString(st, SERIALIZATION.TURTLE)    
467     res = Tools().getResourceByType(RESOURCE.UNITPRICESPECIFICATION, model)
468     ps_parsed = UnitPriceSpecification().parse(res) 
469     
470     print "        GrDescription: ", ps_parsed.getGrDescription()
471     print "        ValueAddedTaxIncluded: ", ps_parsed.getValueAddedTaxIncluded()
472     print "        Vat percentage: ", ps_parsed.getVatPercentage()
473     print '        unit: ', ps_parsed.getUnit()
474     print '        validFrom: ', ps_parsed.getValidFrom()
475     
476     print "        .....reserialize to string ...."
477     st2 = Tools().toString(ps_parsed, SERIALIZATION.TURTLE)
478     print "        ", st2
479     print "\n"
480     print "        --------------"
481     
482     print '\n----explain---\n'
483     ps.explain()
484     
485     print '\n-----print----\n'
486     ps.printOut()
487     
488     return ps
489
490
491 def offeringTest():
492     '''
493     Test Offering class parse/serialize
494    
495     '''
496     myIdentity = "http://seasexamples.asema.com/offering"
497     offer = Offering(myIdentity, "an Offer", "an offer for extra energy")
498     offer.setBusinessFunction("http://myonlineBusiness.com")
499     offer.setSameAs("http://bogus.same.as")
500     someitems1 = SomeItems(None, RESOURCE.PRICE, "solar energy", "solar energy is unstable and unpredicatable", "http://my.demo.com")    
501     someitems1.setDuration("P1Y2M3DT10H10M1S")
502     offer.addIncludes(someitems1)
503     someitems2 = SomeItems(None, RESOURCE.PRICE, "Northern Sea wind farm", "winder energy is unstable as well", "http://my.demo2.com")
504     someitems2.setDuration(5,5,1,1,10,10)
505     offer.addIncludes(someitems2)
506     
507     ps = UnitPriceSpecification("http://unit.pricespecification.com")
508     ps.setGrDescription("A subclass of GrObj")
509     ps.setGeneratedAt(datetime.datetime.now())
510     ps.setGrName("Price Fetching service")
511     ps.setCurrency("EUR")
512     ps.setCurrencyValue(3.12)
513     ps.setSameAs("http://bogus.same.as")
514     ps.setValidFrom(datetime.datetime.now())
515     ps.setQuantity(RESOURCE.ENERGYANDWORK)
516     ps.setUnit(RESOURCE.KILOWATTHOUR)
517    
518     ps.addType(RESOURCE.PRICE)
519     ps.setValueAddedTaxIncluded(False)
520     ps.setVatPercentage(Variant(100.2))
521     offer.addPriceSpecification(ps)
522     
523     print ".....serialize Offering object to string... "
524     st = Tools().toString(offer, SERIALIZATION.TURTLE)
525     print st
526     print "....parse back to Offering object..."
527     model = Tools().fromString(st, SERIALIZATION.TURTLE)
528     res = Tools().getResourceByType(RESOURCE.OFFERING, model)
529     ps_parsed = Offering.parse(res) 
530     
531     print "business function URI: ", ps_parsed.getBusinessFunction().getIdentifierUri()
532     print "include 1 Types: ", ps_parsed.getIncludes()[0].getTypes()
533     print "include 1 duration: ", ps_parsed.getIncludes()[0].getDuration()
534     print "price specification VatPercentage: ", ps_parsed.getPriceSpecification()[0].getVatPercentage()
535     
536     print ".....reserialize to string ...."
537     st2 = Tools().toString(ps_parsed, SERIALIZATION.TURTLE)
538     print st2
539     
540     print "\n---explain----\n"
541     offer.explain()
542     print "\n---print----\n"
543     offer.printOut()
544
545
546 def TransactionSerialzeTest():
547     '''
548     Test Transaction Class parse/serialized.     
549     '''
550     print '\n <Test Transaction Class parse/serialized> \n'
551     myIdentity = "http://seasexamples.asema.com/transaction"
552     trans = Transaction(myIdentity)
553     trans.setGeneratedBy("http://asema.com/activitySeas")
554     trans.setGeneratedAt(datetime.datetime.now())
555     trans.setSigner("http://myOnlineBusiness.com")
556     
557     tsRequest = RequestFactory().create("http://localhost:8099/seas/v1.0/access/");
558
559     system = SystemOfInterest()
560     system.setSameAs("http://bogus.same.as")
561     system.setSessionKey("Measurement")
562     tsRequest.setSystemOfInterest(system)
563     
564     trans.setMessage(tsRequest)
565     trans.setSignature("XXXQAZWSXEDC")
566     trans.setHashCode("1234567")
567     #refObj = trans.createReference()
568     
569     print ".....serialize Transaction object to string... "
570     st = Tools().toString(trans, SERIALIZATION.TURTLE)
571     print st
572     
573     print ".....parse back to Transaction object using Tools.toObj()..."
574     #model = Tools().fromString(st, SERIALIZATION.TURTLE)    
575     #res = Tools().getResourceByType(RESOURCE.TRANSACTION, model)        
576     #ps_parsed = Transaction.parse(res) 
577     ps_parsed = Tools().toObj(st)
578     
579     print "Signature: ", ps_parsed.getSignature()
580     print "Message Session key: ", ps_parsed.getMessage().getSystemOfInterest().getSessionKey()
581     print "Message Generated By: ", ps_parsed.getMessage().getGeneratedBy().getIdentifierUri()
582     print "Generated At: ", ps_parsed.getGeneratedAt()
583     print "Generated By Types: ", ps_parsed.getGeneratedBy().getTypes()
584     
585     print ".....reserialize to string ...."
586     st2 = Tools().toString(ps_parsed, SERIALIZATION.TURTLE)
587     print st2
588     
589     print '\n----explain---\n'
590     ps_parsed.explain()
591     
592     print '\n-----print----\n'
593     ps_parsed.printOut()
594     # Reference parse/serialize test
595     #print "++++++++++++++serialize Transaction's Reference object to String +++++++"
596     #stRef = Tools().toString(refObj, SERIALIZATION.TURTLE)
597     #print stRef
598     
599     #print "+++++ Parse back to Reference Object ++++++++"
600     #model = Tools().fromString(stRef, SERIALIZATION.TURTLE)    
601     #resRef = Tools().getResourceByType(RESOURCE.REFERENCE, model)        
602     #ref_parsed = Transaction.parse(resRef) 
603     #print "++ Reference Object hashcode: ", ref_parsed.getHashCode()
604     #print "++ Reference Object Notary: ", ref_parsed.getNotary()
605     #print "+++++++ reserialize to string +++++ "
606     #st2Ref = Tools().toString(ref_parsed, SERIALIZATION.TURTLE)
607     #print st2Ref
608     
609     print "\n"
610
611
612 def longSerializeParseTest():
613     from SmartAPI.model.Obj import Obj
614     '''
615     Duration related testings are added in this test case.
616     '''
617     myId = "http://seasdemos.asema.com/cpluplus/controlcommandsender/Cabcd"
618     
619     print "Test routine for serialization + parse of an activity"
620     
621     a = Activity("http://asema.com/activitySeasIdentifier")
622     i1 = Input("http://input.uri", Input.TYPE_DATA)
623     i1.setName("data input")
624     i2 = Input("http://input2.uri", Input.TYPE_REFERENCE)
625     i2.setName("reference input")
626     a.setInput(i1)
627     a.addInput(i2)
628     o1 = Output("http://output.uri")
629     o1.setName("output 1")
630     o2 = Output("http://output.uri")
631     o2.setName("output 2")
632     a.setOutput(o1)
633     a.addOutput(o2)
634     
635     ab = Availability()
636     ab.setIdentifierUri("http://availability.uri")
637     ab.setName("availability")
638     ab.setIsControlledBy("http://availability.controlled.by")
639     a.addAvailability(ab)
640     dab = Availability()
641     dab.setIdentifierUri("http://data.availability.uri")
642     dab.setName("data availability")
643     a.addDataAvailability(dab)
644     
645     iface1 = InterfaceAddress()
646     iface1.setIdentifierUri("http://iface1.uri")
647     iface1.setName("eth0")
648     iface2 = InterfaceAddress()
649     iface2.setIdentifierUri("http://iface2.uri")
650     iface2.setType(RESOURCE.INTERFACEADDRESS)
651     iface2.addType(RESOURCE.BATTERY)
652     iface2.setName("eth1")
653     a.setInterface(iface1)
654     a.addInterface(iface2)
655     
656     tc = TemporalContext()
657     tc.setStart(datetime.datetime.now())
658     tc.setEnd(datetime.datetime.now())
659     tc.setDuration("P8DT8H2M2S")
660
661     status = Status()
662     status.setPercentage(50)
663     status.setCompleted(20)
664
665     req = ResponseFactory().create(myId)
666     req.setSameAs("http://bogus.same.as")
667     req.setName("test request")
668     req.setActivity(a)
669     req.setTemporalContext(tc)
670     req.setMessageId(1)
671     req.setProcessId(2)
672     req.setStatus(status)
673     req.setIdentifierUri("http://bogus.seas.identifier.uri")
674     req.add(URIRef("http://booleanProperty"), True)
675     req.add(URIRef("http://objectProperty"), Obj("http://foo.bar"))
676     req.add(URIRef("http://stringProperty"), "string value")
677     req.add(URIRef("http://doubleProperty"), -12.34)
678     req.add(URIRef("http://integerProperty"), 40)
679     req.add(URIRef("http://datetimeProperty"), datetime.datetime.now())
680     duration = Factory.createDuration(1, 2, 3, 4, 5, 6)
681     req.add(URIRef(PROPERTY.FRESHNESS), duration)
682     req.add(URIRef(PROPERTY.ADDON), 1.234)
683
684     system = SystemOfInterest()
685     system.setSameAs("http://system.of/interest")
686     #system.setRegisterKey("Measurement")
687     req.setSystemOfInterest(system)
688
689     payload = Tools().toString(req, SERIALIZATION.TURTLE)
690     
691     print "Serialized payload:"
692     print payload
693
694     print "Parsing back the serialized payload..."
695
696     model = Tools().fromString(payload, SERIALIZATION.TURTLE)
697     res = Tools().getResourceByType(RESOURCE.RESPONSE, model)
698     tsResponse = Response().parse(res)
699     print "hasTemporalContext? ", tsResponse.hasTemporalContext()
700     print "hasSystemOfInterest? ", tsResponse.hasSystemOfInterest()
701     if tsResponse.getTemporalContext().getStart() is not None:
702         print "temporal context start", tsResponse.getTemporalContext().getStart().getValue()
703     if tsResponse.getGeneratedBy() is not None:
704         print "is generated by ", tsResponse.getGeneratedBy()
705     print "is generated at ", tsResponse.getGeneratedAt()
706     print "is same as", tsResponse.getSystemOfInterest().getSameAs().toString()
707     print "addon: ", tsResponse.getFirstValue(URIRef(PROPERTY.ADDON))
708     print "freshness: ", tsResponse.getFirstValue(URIRef(PROPERTY.FRESHNESS))
709     
710     print "\nRe-serializing into JSON-LD"
711     reserializedPayload = Tools().toString(tsResponse, SERIALIZATION.TURTLE)
712     print reserializedPayload
713     
714     tsResponse.printOut()
715     
716
717
718 def propertySerializeParseTest():
719     o = Evaluation()
720     s = SystemOfInterest()
721     s.setSameAs("my system")
722     
723     a = Activity()
724     i = Input()
725     i.add("abcd", "1234")
726     a.addInput(i)
727     #o.addActivity(a)
728     
729     route = Route()
730     route.addRoutePoint(Coordinates(latitude = 61.15, longitude = 25.89))
731     route.addRoutePoint(Coordinates(latitude = 61.14, longitude = 24.78))
732     route.addRoutePoint(Coordinates(latitude = 61.14, longitude = 24.61))
733     
734     waypoints = Waypoints()
735     wp1 = Waypoint()
736     wp2 = Waypoint()
737     addr1 = Address()
738     addr2 = Address()
739     
740     wp1.setLocation(Coordinates(latitude = 60.2, longitude = 24.1))
741     wp2.setLocation(Coordinates(latitude = 61.2, longitude = 25.1))
742     wp1.setInstant(datetime.datetime.now())
743     wp1.setAddress(addr1)
744     wp2.setAddress(addr2)
745     waypoints.addWaypoint(wp1)
746     waypoints.addWaypoint(wp2)
747     
748     route.addRoutePoint(Coordinates(latitude = 61.15, longitude = 25.89))
749     route.addRoutePoint(Coordinates(latitude = 61.14, longitude = 24.78))
750     route.addRoutePoint(Coordinates(latitude = 61.14, longitude = 24.61))
751
752     map = Map()
753     map.insert("key1", "Value1")
754     map.insert("key2", "Value2")
755     map.insert("key3", waypoints)
756     map.insert("key4", [Variant("Value3"), Variant("Value4"), Variant("Value5")])
757     map.insert("key5", ["Value6", "Value7", "Value8"])
758     
759     s.setSameAs("http://same.as")
760     o.add("my numeric para", 1234.5678)
761     o.add("my string para", "test string")
762     o.add("my variant para", Variant(1234))
763     o.add("my simple object para", s)
764     o.add("my complex object para", a)
765     o.add("list para", route)
766     o.add("somelist", ["ValueA", "ValueB", "ValueC"])
767     o.add("map", map)
768     o.add(URIRef("http://www.example.com/value"), "examplevalue")
769     o.add(URIRef(NS.SMARTAPI + "foo"), "bar")
770     
771     serialized = Tools().toString(o, SERIALIZATION.TURTLE)
772     print "Serialized", serialized
773     
774     #o_parsed = Obj.parse(Tools().getResourceByType(RESOURCE.EVALUATION, Tools().fromString(serialized, SERIALIZATION.TURTLE)))
775     # this works too.
776     #o_parsed = Evaluation.parse(Tools().getResourceByType(RESOURCE.EVALUATION, Tools().fromString(serialized, SERIALIZATION.TURTLE)))    
777     # this alternative also works
778     o_parsed = Evaluation.fromString(serialized, SERIALIZATION.TURTLE)
779     reserialized = Tools().toString(o_parsed, SERIALIZATION.TURTLE)
780         
781     print "-------------------------------------"
782     print reserialized
783     
784
785 def inputOutputTest():
786     r1 = Request("http://me.com")
787     
788     a1 = Activity("http://you.com/colorcalculator")
789     i = Input()
790     map = Map()
791     map.insert("dataitems", "color")
792     map.insert("rgb", ["red", "green", "blue"])
793     i.add("callId", "1234")
794     i.add("callParams", map)
795     a1.addInput(i)
796     r1.addActivity(a1)
797     
798     print "Request:\n", Tools().serializeRequest(r1, serialization = SERIALIZATION.getMimeType(SERIALIZATION.TURTLE))[0]
799     
800     r2 = Response("http://you.com")
801     a2 = Activity("http://you.com/colorcalculator")
802     o = Output()
803     o.add("callId", "1234")
804     o.add("result", "white")
805     a2.addOutput(o)
806     r2.addActivity(a2)
807     
808     print "Response:\n", Tools().serializeRequest(r2, serialization =SERIALIZATION.getMimeType( SERIALIZATION.TURTLE))[0]
809     
810     
811 def parameterSerializeParseTest():
812     pass
813     
814     
815 def physicalEntityTest():
816     entity = PhysicalEntity()
817     size = Size()
818     speed = Velocity()
819     orientation = Orientation()
820     direction = Direction()
821     
822     size.setWidth(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(100.2)))
823     size.setHeight(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(301.9)))
824     size.setDepth(ValueObject(unit = NS.UNIT + "Centimeter", value = Variant(11.222)))
825     
826     orientation.setYaw(ValueObject(unit = NS.UNIT + "DegreeAngle", value = Variant(270)))
827     orientation.setPitch(ValueObject(unit = NS.UNIT + "DegreeAngle", value = Variant(45)))
828     orientation.setRoll(ValueObject(unit = NS.UNIT + "DegreeAngle", value = Variant(301)))
829     
830     direction.setBearing(ValueObject(unit = NS.UNIT + "DegreeAngle", value = Variant(121)))
831     direction.setHeading(ValueObject(unit = NS.UNIT + "DegreeAngle", value = Variant(243)))
832
833     speed.setLinearVelocityX(ValueObject(unit = URIRef(NS.UNIT + "MeterPerSecond"), value = Variant(3.4)))
834     speed.setLinearVelocityY(ValueObject(unit = NS.UNIT + "MeterPerSecond", value = Variant(30.1)))
835     speed.setAngularVelocityY(ValueObject(unit = NS.UNIT + "RadianPerSecond", value = Variant(54.3)))
836     
837     entity.addType(RESOURCE.PHYSICALENTITY)
838     entity.addType(RESOURCE.CAR)
839     entity.setName("This is a test entity");
840     entity.setVelocity(speed);
841     entity.setOrientation(orientation);
842     entity.setDirection(direction);
843     entity.setSize(size);
844     
845     entity.setWeight(ValueObject(unit = NS.UNIT + "Kilogram", value = Variant(222)))
846     
847     serialized = Tools().toString(entity, SERIALIZATION.TURTLE)
848     print "Serialized:"
849     print serialized
850     
851     model = Tools().fromString(serialized, SERIALIZATION.TURTLE)
852     res = Tools().getResourceByType(RESOURCE.PHYSICALENTITY, model)
853     parsedEntity = PhysicalEntity().parse(res)
854     
855     print "Width: ", parsedEntity.getSize().getWidth().getValue()
856     print "Depth: ", parsedEntity.getSize().getDepth().getValue()
857     
858     print "\nRe-serializing...";
859     reserializedPayload = Tools().toString(parsedEntity, SERIALIZATION.TURTLE)
860     print reserializedPayload
861
862
863 def waypointsTest():
864     waypoints = Waypoints()
865     
866     wp1 = Waypoint()
867     wp2 = Waypoint()
868     wp3 = Waypoint()
869     
870     loc1 = Address()
871     loc2 = Address()
872     loc3 = Address()
873     coords1 = Coordinates(latitude = 60.2, longitude = 24.1)
874     
875     route = Route()
876     route.addRoutePoint(Coordinates(latitude = 61.15, longitude = 25.89))
877     route.addRoutePoint(Coordinates(latitude = 61.14, longitude = 24.78))
878     route.addRoutePoint(Coordinates(latitude = 61.14, longitude = 24.61))
879
880     #for i in range(100000):
881     for i in range(5):
882         route.addRoutePoint(Coordinates(latitude = 61.14+i/1000.0, longitude = 24.61-i/1000.0))
883         
884     loc1.setCity("Pori")
885     loc2.setCity("Espoo")
886     loc2.setCountry("Finland")
887     loc2.setStreetAddress("Otakaari 1")
888     loc2.setZipCode("02150")
889     loc3.setCity("Kuopio")
890     
891     wp1.setInstant(datetime.datetime.now())
892     wp1.setAddress(loc1)
893     wp1.setLocation(coords1)
894
895     wp2.setAddress(loc2)
896
897     wp3.setAddress(loc3)
898     wp3.setRoute(route)
899
900     waypoints.addWaypoint(wp1)
901     waypoints.addWaypoint(wp2)
902     waypoints.addWaypoint(wp3)
903     
904     oStart = datetime.datetime.now()
905     serialized = Tools().toString(waypoints, SERIALIZATION.TURTLE)
906     oEnd = datetime.datetime.now()
907     print "Serialized (elapsed %s:"%(oEnd - oStart)
908     print serialized
909
910     oStart = datetime.datetime.now()
911     model = Tools().fromString(serialized, SERIALIZATION.TURTLE)
912     res = Tools().getResourceByType(RESOURCE.WAYPOINTS, model)
913     parsedEntity = Waypoints().parse(res)
914     oEnd = datetime.datetime.now()
915     print "Parsed (elapsed %s:"%(oEnd - oStart)
916     
917     for wp in waypoints.getWaypoints():
918         print "WP:", wp.getInstant().getValue() if wp.getInstant() else "no instant"
919     
920     wpr = waypoints.getWaypoints()[2]
921     for rp in wpr.getRoute().getRoutePoints():
922         print "RP:", rp.getLatitude(), rp.getLongitude()
923     
924     print "\nRe-serializing...";
925     reserializedPayload = Tools().toString(parsedEntity, SERIALIZATION.TURTLE)
926     print reserializedPayload
927
928
929 def basicListSerializeParseTest():
930     now = datetime.datetime.now()
931     
932     # Raw lists
933     # This should by default create an ordered list widhout a base object
934     o = Input()
935     o.setName("Some input")
936     l = [1, 2, 3, "ab", o, 4]
937     
938     stringData = Tools().toString(l, SERIALIZATION.TURTLE)
939     print "Ordered list"
940     print stringData
941     o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
942     print Tools().toString(o, SERIALIZATION.TURTLE)
943     
944     # Explicitly create lists
945     ll = LinkedList()
946     il = ItemizedList()
947     
948     ll.add_items(l)
949     il.add_items(l)
950     
951     print "Linked list"
952     stringData = Tools().toString(ll, SERIALIZATION.TURTLE)
953     print stringData
954     o  = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
955     print Tools().toString(o, SERIALIZATION.TURTLE)
956     
957     print "Itemized list"
958     stringData = Tools().toString(il, SERIALIZATION.TURTLE)
959     print stringData
960     o  = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
961     print Tools().toString(o, SERIALIZATION.TURTLE)
962     
963     # Lists within a context (should use ordered list by default
964     ts = TimeSeries()
965     ts.setType(RESOURCE.TIMESERIES)
966     
967     testList = []
968     
969     for i in range(10):
970         e = Evaluation()
971         e.setValue(Variant(i));
972         e.setInstant(now + datetime.timedelta(days = i))
973         testList.append(e)
974     
975     ts.setList(testList)
976     
977     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
978     
979     print "Serialized timeseries:"
980     print stringData
981
982     print "Parsing back the serialized data..."
983     tsParsed = Tools().toObj(stringData, SERIALIZATION.TURTLE)
984     print Tools().toString(tsParsed, SERIALIZATION.TURTLE)
985     
986     if tsParsed.hasList():
987         tsl = tsParsed.getList()
988         for j in range(tsParsed.getListSize()):
989             e = tsl.get_item(j)
990             print "Value:", e.getInstant(), e.getValue().getValue()
991
992     print '\n---explain TimeSeries---\n'
993     #ts.explain()
994     print '\n---print TimeSeries---\n'
995     #ts.printOut()
996
997 def baseObjectListSerializeParseTest():
998     # Raw lists
999     # This should by default create an ordered list without a base object
1000     d = Device()
1001     d.add(PROPERTY.GROUNDSPEED, 5)
1002     d.add(PROPERTY.GROUNDSPEED, 10)
1003     d.add(PROPERTY.GROUNDSPEED, 20)
1004     print Tools().toString(d, SERIALIZATION.TURTLE)
1005     
1006     o = Input()
1007     o.setName("Some input")
1008     l = [1, 2, 3, "ab", o, 4]
1009     
1010     stringData = Tools().toString(l, SERIALIZATION.TURTLE)
1011     #print "Ordered list"
1012     #print stringData
1013     o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1014     print Tools().toString(o, SERIALIZATION.TURTLE)
1015     
1016     base = ValueObject(unit = NS.UNIT + "Centimeter")
1017     # Explicitly create lists
1018     ll = LinkedList()
1019     ol = OrderedList()
1020     il = ItemizedList()
1021     nl = NudeList()
1022     
1023     ll.setBaseObject(base)
1024     il.setBaseObject(base)
1025     ol.setBaseObject(base)
1026     nl.setBaseObject(base)
1027     
1028     ll.add_items(l)
1029     il.add_items(l)
1030     ol.add_items(l)
1031     nl.add_items(l)
1032     
1033     ll.setBaseObjectProperty(PROPERTY.FRESHNESS)
1034     il.setBaseObjectProperty(PROPERTY.FRESHNESS)
1035     ol.setBaseObjectProperty(PROPERTY.FRESHNESS)
1036     nl.setBaseObjectProperty(PROPERTY.FRESHNESS)
1037     
1038     print "Linked list"
1039     stringData = Tools().toString(ll, SERIALIZATION.TURTLE)
1040     print stringData
1041     o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1042     print o
1043     
1044     print "Itemized list"
1045     stringData = Tools().toString(il, SERIALIZATION.TURTLE)
1046     print stringData
1047     o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1048     print o
1049     
1050     print "Ordered list"
1051     stringData = Tools().toString(ol, SERIALIZATION.TURTLE)
1052     print stringData
1053     o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1054     print o
1055     
1056     print "Nude list"
1057     stringData = Tools().toString(nl, SERIALIZATION.TURTLE)
1058     print stringData
1059     o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1060     print o
1061     
1062     # Lists within a context (should use ordered list by default
1063     ts = TimeSeries()
1064     ts.setType(RESOURCE.TIMESERIES)
1065     
1066     testList = [i for i in range(10)]
1067     e = Evaluation()
1068     e.setInstant(datetime.datetime.now())
1069     
1070     ts.setList(testList, baseObject=e, baseObjectProperty=PROPERTY.FRESHNESS)
1071     
1072     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1073     
1074     print "Serialized data:"
1075     print stringData
1076
1077     print "Parsing back the serialized data..."
1078     tsParsed = Tools().toObj(stringData, SERIALIZATION.TURTLE)
1079     print Tools().toString(tsParsed, SERIALIZATION.TURTLE)
1080     
1081     if tsParsed.hasList():
1082         tsl = tsParsed.getList()
1083         for j in range(tsParsed.getListSize()):
1084             e = tsl.get_object(j)
1085             print "Value:", e.getInstant(), e.get(PROPERTY.FRESHNESS)
1086             
1087
1088 def timeseriesListSerializeParseTest():
1089     ts = TimeSeries()
1090     ts.setList(OrderedList())
1091     start = datetime.datetime.now()
1092     end = start + Factory.createDuration(0, 0, 0, 5, 0, 0)
1093     # 5 hours
1094     ts.setTemporalContext(TemporalContext(start=start, end=end))
1095     # create valueobject as a base object
1096     baseVo = ValueObject('http://test.vo')
1097     baseVo.setUnit(RESOURCE.DEGREECELSIUS)
1098     baseVo.setQuantity(RESOURCE.TEMPERATURE)
1099     ts.setBaseObject(baseVo)
1100     ts.setBaseObjectProperty(URIRef("http://base.object.com"))
1101     # 1 hour timestep between data values
1102     timeStep = Factory.createDuration(0, 0, 0, 1, 0, 0)
1103     ts.setTimeStep(Variant(timeStep))
1104     # add timeseries values
1105     current = start
1106     i = 0
1107     while current < end:
1108         ts.addListItem(i)
1109         i += 1
1110         current += timeStep
1111         
1112     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1113     
1114     print "Serialized data:"
1115     print stringData
1116
1117     print "Parsing back the serialized data..."
1118     tsParsed = Tools().toObj(stringData, SERIALIZATION.TURTLE)
1119     print Tools().toString(tsParsed, SERIALIZATION.TURTLE)
1120
1121     
1122 def listExplainTest():
1123     '''
1124     Test case for testing explain()/printOut() function, serialization/parse for all kinds of List. 
1125     
1126     '''
1127     print '\n listExplainTest()**********\n'
1128     now = datetime.datetime.now()
1129     
1130     ts = TimeSeries()
1131     ts.setType(RESOURCE.TIMESERIES)
1132     
1133     testList = []
1134     
1135     for i in range(3):
1136         e = Evaluation()
1137         e.setValue(Variant(i));
1138         e.setInstant(now + datetime.timedelta(days = i))
1139         testList.append(e)
1140     
1141     ll = LinkedList()
1142     ll.add_items(testList)
1143     ts.setList(ll)
1144     
1145     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1146     print "\n >>>>>>>>>>> linked list"
1147     print stringData
1148     o = Tools().toObj(stringData)
1149     print '\n    parse and then reserialize: \n'
1150     
1151     print Tools().toString(o, SERIALIZATION.TURTLE)
1152     
1153     print '\n---explain TimeSeries with linkedlist---\n'    
1154     ts.explain()
1155     print '\n---print TimeSeries with linkedlist---\n'    
1156     ts.printOut()
1157      
1158     
1159     il = ItemizedList()
1160     il.add_items(testList)    
1161     ts.setList(il)
1162     
1163     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1164     print "\n >>>>>>>>>itemized list"
1165     print stringData
1166     o = Tools().toObj(stringData)
1167     print '\n    parse and then reserialize: \n'
1168     
1169     print Tools().toString(o, SERIALIZATION.TURTLE)
1170     
1171     print '\n---explain TimeSeries with itemizedList---\n'    
1172     ts.explain()
1173     print '\n---print TimeSeries with itemizedList---\n'    
1174     ts.printOut()
1175     
1176     
1177     ol = OrderedList()
1178     ol.add_items(testList)
1179     ts.setList(ol)
1180     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1181     print "\n >>>>>>>>>ordered list"
1182     print stringData
1183     o = Tools().toObj(stringData, SERIALIZATION.TURTLE)
1184     print '\n    parse and then reserialize: \n'
1185     
1186     print Tools().toString(o, SERIALIZATION.TURTLE)
1187     
1188     print '\n---explain TimeSeries with orderedlist---\n'    
1189     ts.explain()
1190     print '\n---print TimeSeries with orderedlist---\n'    
1191     ts.printOut()
1192
1193     
1194     nl = NudeList()
1195     nl.add_items(testList)
1196     ts.setList(nl)
1197     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1198     print "\n >>>>>>>>>Nude list"
1199     print stringData
1200     o = Tools().toObj(stringData, SERIALIZATION.TURTLE)
1201     print '\n    parse and then reserialize: \n'
1202     
1203     print Tools().toString(o, SERIALIZATION.TURTLE)
1204     
1205
1206 def listSpeedTestSerialize():
1207     import simplejson
1208     l = [x for x in range(10)]
1209     
1210     a = { "array": l }
1211     print "JSON list"
1212     jStart = datetime.datetime.now()
1213     stringData = simplejson.dumps(a)
1214     jEnd = datetime.datetime.now()
1215     
1216     print "Ordered list"
1217     oStart = datetime.datetime.now()
1218     stringData = Tools().toString(l, SERIALIZATION.TURTLE)
1219     oEnd = datetime.datetime.now()
1220     
1221     # Explicitly create lists
1222     print "Itemized list"
1223     il = ItemizedList()
1224     il.add_items(l)
1225     iStart = datetime.datetime.now()
1226     stringData = Tools().toString(il, SERIALIZATION.TURTLE)
1227     iEnd = datetime.datetime.now()
1228     
1229     print "Linked list"
1230     ll = LinkedList()
1231     ll.add_items(l)
1232     lStart = datetime.datetime.now()
1233     stringData = Tools().toString(ll, SERIALIZATION.TURTLE)
1234     lEnd = datetime.datetime.now()
1235     
1236     print "Nude list"
1237     nl = NudeList()
1238     nl.add_items(l)
1239     nStart = datetime.datetime.now()
1240     stringData = Tools().toString(nl, SERIALIZATION.TURTLE)
1241     print stringData
1242     nEnd = datetime.datetime.now()
1243     
1244     print "RESULTS"
1245     print "Ordered list", (oEnd - oStart)
1246     print "Unordered list", (iEnd - iStart)
1247     print "Linked list", (lEnd - lStart)
1248     print "Nude list", (nEnd - nStart)
1249     print "JSON reference", (jEnd - jStart)
1250
1251
1252 def listSpeedTestSerializeAndParse():
1253     import simplejson
1254     l = [x for x in range(10)]
1255     
1256     print "\n\nOrdered list"
1257     oStart = datetime.datetime.now()
1258     stringData = Tools().toString(l, SERIALIZATION.TURTLE)
1259     oEnd = datetime.datetime.now()
1260     print stringData
1261     opStart = datetime.datetime.now()
1262     try:
1263         o = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
1264     except:
1265         o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1266     opEnd = datetime.datetime.now()
1267     #print Tools().toString(o, SERIALIZATION.TURTLE)
1268     print "-----------------"
1269     print "Serialize:", (oEnd - oStart)
1270     print "Parse:", (opEnd - opStart)
1271     
1272     
1273     # Explicitly create lists
1274     print "\n\nItemized list"
1275     il = ItemizedList()
1276     il.add_items(l)
1277     iStart = datetime.datetime.now()
1278     stringData = Tools().toString(il, SERIALIZATION.TURTLE)
1279     iEnd = datetime.datetime.now()
1280     print stringData
1281     ipStart = datetime.datetime.now()
1282     try:
1283         o = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
1284     except:
1285         o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1286     ipEnd = datetime.datetime.now()
1287     #print Tools().toString(o, SERIALIZATION.TURTLE)
1288     print "-----------------"
1289     print "Serialize:", (iEnd - iStart)
1290     print "Parse:", (ipEnd - ipStart)
1291     
1292     print "\n\nLinked list"
1293     ll = LinkedList()
1294     ll.add_items(l)
1295     lStart = datetime.datetime.now()
1296     stringData = Tools().toString(ll, SERIALIZATION.TURTLE)
1297     lEnd = datetime.datetime.now()
1298     print stringData
1299     lpStart = datetime.datetime.now()
1300     #try:
1301     #    o = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
1302     #except:
1303     #    o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1304     lpEnd = datetime.datetime.now()
1305     #print Tools().toString(o, SERIALIZATION.TURTLE)
1306     print "-----------------"
1307     print "Serialize:", (lEnd - lStart)
1308     print "Parse:", (lpEnd - lpStart)
1309     
1310     print "\n\nNude list"
1311     nl = NudeList()
1312     nl.add_items(l)
1313     nStart = datetime.datetime.now()
1314     stringData = Tools().toString(nl, SERIALIZATION.TURTLE)
1315     nEnd = datetime.datetime.now()
1316     print stringData
1317     npStart = datetime.datetime.now()
1318     try:
1319         o = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
1320     except:
1321         o = Tools().fromStringAsList(stringData, SERIALIZATION.TURTLE)
1322     npEnd = datetime.datetime.now()
1323     #print Tools().toString(o, SERIALIZATION.TURTLE)
1324     print "-----------------"
1325     print "Serialize:", (nEnd - nStart)
1326     print "Parse:", (npEnd - npStart)
1327
1328     
1329 def listOfMapsTest():
1330     print "List of maps test"
1331     
1332     a = Activity()
1333     i = Input()
1334     o = Output()
1335     
1336     a.addInput(i)
1337     a.addOutput(o)
1338     
1339     # Input
1340     controllable_appliances = []
1341     # Test adding something empty
1342     i.add("ControllableAppliances", controllable_appliances)
1343     
1344     appliance0 = Map()
1345     appliance0.insert("Active", True)
1346     i.add("FirstAppliance", appliance0)
1347     
1348     appliance1 = Map()
1349     appliance1.insert("Active", True)
1350     appliance1.insert("Whatever", 1)
1351     appliance1.insert("ConsumptionRate", 1.267)
1352     appliance1.insert("Name", "String content")
1353     
1354     controllable_works = []
1355     works1 = Map()
1356     works1.insert("EarlyStartPeriod", 2147483647)
1357     works1.insert("LateStopPeriod", 2147483647)
1358     works1.insert("WorkDuration", 2147483647)
1359     controllable_works.append(works1)
1360     appliance1.insert("ControllableWorks", works1)
1361     controllable_appliances.append(appliance1)
1362     
1363     # Output
1364     controllable_appliance_result = []
1365     appliance_result_1 = Map()
1366     appliance_result_1.insert("Name", "String content")
1367     controllable_appliance_work_result = []
1368     appliance_result_1.insert("ControllableWorkResult", controllable_appliance_work_result)
1369     work_result_1 = Map()
1370     controllable_appliance_work_result.append(work_result_1)
1371     usage_information = Map()
1372     usage_information.insert("StartPeriod", 2147483647)
1373     usage_information.insert("StopPeriod", 2147483647)
1374     usage_information.insert("WorkDuration", 2147483647)
1375     work_result_1.insert("UsageInformation", usage_information)
1376     
1377     period_consumptions = []
1378     period_1 = Map()
1379     period_1.insert("Period", 2147483647)
1380     period_1.insert("Value", 1.26743)
1381     period_consumptions.append(period_1)
1382     work_result_1.insert("PeriodConsumption", period_consumptions)
1383     controllable_appliance_result.append(appliance_result_1)
1384     o.add("ControllableApplianceResult", controllable_appliance_result)
1385     
1386     serialized = Tools().toString(a, SERIALIZATION.TURTLE)
1387     print "Serialized:\n", serialized
1388     a_parsed = Tools().fromStringAsObj(serialized, serialization = SERIALIZATION.TURTLE)
1389     reserialized = Tools().toString(a_parsed, SERIALIZATION.TURTLE)
1390     
1391     print "----"
1392     print "Re-serialized:\n", reserialized
1393     
1394 def hugeDataTest():
1395     print "HugeDataTest: Not implemented yet"
1396     myId = "http://seasdemos.asema.com/cplusplus/controlcommandsender/Cabcd"
1397
1398     now = datetime.datetime.now()
1399
1400     req = ResponseFactory().create(myId)
1401     req.setSameAs("http://hugedata.test")
1402     req.setName("Huge dataset test")
1403     req.setIdentifierUri("http://huge.data.uri")
1404         
1405     for i in range(4000):
1406         e = Evaluation()
1407         e.setValue(Variant(i));
1408         e.setInstant(now + datetime.timedelta(days = i))
1409         req.add("http://evaluation.com", e)
1410         
1411     stringData = Tools().toString(req, SERIALIZATION.TURTLE)
1412     
1413     print "Serialized data:"
1414     print stringData
1415
1416     print "Parsing back the serialized data..."
1417
1418     model = Tools().fromString(stringData, SERIALIZATION.TURTLE)
1419     res = Tools().getResourceByType(RESOURCE.RESPONSE, model)
1420     reqParsed = Response().parse(res)
1421     
1422     for p in reqParsed.listProperties()[0]:
1423         print "Value:", e.getValue().getValue()
1424     
1425 def registrationTest():
1426 #     pubKey = SmartAPICrypto().downloadPublicKey("http://www.client.com/seas/Cclient", KEYSERVER_URI)
1427 #     privKey = SmartAPICrypto().loadPrivateKey('testkey_private.pem')
1428     
1429     serverIdentity = "http://seasexamples.asema.com/api/Ctestserver"
1430     service = createSampleRegistrationEntity(serverIdentity)
1431     agent = RegistrationAgent(serverIdentity)
1432     agent.addEntity(service)
1433     
1434     agent.setDebugMode(True)
1435     #payload = agent.generateEncryptedRegistrationMessage(pubKey, service)
1436     
1437     """
1438     # Test sets for compatibility
1439     # C++
1440     payload = "PDvrIUEup/eiTAolieUHSFBgV+UI2h0vvuGhHQjnS5QXlBmPKgO4WrJTUyV60Yqx7/baPg28or6Zat4HokK0ZbXux6xUMvYUTkGpzSjrnaulrn7biv5g/p7dTKx89JkVuW0K3Oci2ICDdg4PcYC1EH/7EWVaLUoUcPb1qRn/qBpsDwieBvvHU4Solo59meo26Ch+CL4hLtsTtrdZmtCvUkn1lIFm9vc3WRo5jXZP9vpR5UMRVXDCu007fqeAD7ppgJHI6/U3kIiyc3n54yvgyzKShlAeORIaxNxMSY09QTEtoGr92M5iBoOZYsfdxndfHy0yPNuGvOhO9ab6nrXwlA==";
1441     payload += '\n';
1442     payload += "LCBcyYE+8ILCD43DOQGBsg==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";
1443     
1444     # Java
1445     payload = "Agj9Y55uNpgn4Y2Z6HqSOjtdTCBpQTW1JniLaqWe7UCZShuryBObDxdWYVSpVJgqKnrU/LmbHVaIGuuOWnhUP2G9oVCV3fYBvFQz9ZXXoz1PkzF0sIh7aBFFfFTA9dSMddZWxnILyL+qpR4dyOHlyHCQBEprmOgDSaJ3YWVj4cgQkfSLEFdYHHG1hqkwYwJ41Ni+RRRd7yT9E1oIuuYme5FRzFXmauX+ZkrXjJDbDrak15Xbng1m356+5wxOufcE4mnBQbYl60ujmXqZZh/wM+80xImC51o5RGjTXcrUDYA3aCvSDbG0qCzLlS8/NQfaa200hts5xTZ+8eqQVTHLWA=="
1446     payload += '\n';
1447     payload += "fibcjFUMHedV3Dxz889SLw==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"
1448     """ 
1449     response = agent.registrate()
1450     print '\n registration result:'
1451     if response.hasErrors():
1452         for err in response.getErrors():
1453             print 'Error message: ', err.getErrorMessage()
1454        
1455     if response.hasStatus():
1456         status = response.getStatus()
1457         print 'status: ' 
1458         status.turtlePrint()
1459         # check if the operation was successful
1460         if ( status.isOfType(RESOURCE.ERROR)):
1461             print "Registration failed."
1462         elif (status.isOfType(RESOURCE.READY)):
1463             print "Registration successful."
1464      
1465     print '\n now testing deregister'
1466     
1467 #     response2 = agent.deRegistrate()
1468 #     if response2.hasErrors():
1469 #         for err in response2.getErrors():
1470 #             print 'Error message: ', err.getErrorMessage()
1471                 
1472     
1473 def getPemPublicKey(fileName):
1474     f = open(fileName,'r')
1475     return RSA.importKey(f.read())
1476
1477 def getPemPrivateKey(fileName):
1478      f = open(fileName,'r')
1479      return RSA.importKey(f.read())
1480
1481 def  createSampleRegistrationEntity(serverIdentity):
1482     from SmartAPI.model.Obj import Obj
1483     serverName = "A Python sample route energy calculation service";
1484         
1485     service = Service(serverIdentity);
1486         
1487     # Service metadata
1488     owner = Organization();
1489     acmeAddress = Address();
1490     iface = InterfaceAddress();
1491         
1492     iface.setHost("www.acme.com");
1493     iface.setScheme("https");
1494     iface.setPath("/seas/v1.0e1.0/access");
1495     acmeAddress.setStreetAddress("Giant Rubber Band Street");
1496     acmeAddress.setZipCode("12345");
1497     acmeAddress.setCity("Fairfield, Python");
1498     owner.setName("Acme Industries");
1499     owner.setAddress(acmeAddress);
1500         
1501     service.addInterface(iface);
1502     service.addOwner(owner);
1503     service.setName(serverName);
1504     service.setDescription("A route calculation service that in addition to length and driving time calculates the amount of energy consumed in the battery. Takes as parameters various efficiency factors such as weight and drag.");
1505     service.addWebsite("http://www.acme.com/acmeoptimizers/roadrunner/beep/beep");
1506         
1507         
1508     # API payload data
1509     a = Activity();
1510     i = Input();
1511     o = Output();
1512     a.addOutput(o);
1513     a.addInput(i);
1514     service.addCapability(a);
1515         
1516     car = PhysicalEntity();
1517     car.setWeight(Factory().createValueObject(unit = NS.UNIT + "Kilogram", description = "Vehicle's weight without any consumables or passengers."));
1518     car.add("frontalAerodynamicCoefficient", Factory().createValueObject(unit = NS.UNIT + "SquareMeter", description = "Product of vehicle's frontal area and aerodynamic coefficient"));
1519     car.add("tireRollingResistanceCoefficient", Factory().createValueObject(datatype = Obj(DATATYPE.INTEGER), description = "Vehicle's tire rolling resistance coefficient, in interval ]0, 1["));
1520     car.add("gearEfficiencyCoefficient", Factory().createValueObject(description = "Vehicle's efficiency coefficient between engine and gear, in interval ]0, 1["));
1521     car.add("batteryCapacity", Factory().createValueObject(unit = NS.UNIT + "KilowattHour", description = "Vehicle's capacity of the battery (enter only if electric vehicle or hybrid rechargeable, 0 otherwise"));
1522     car.add("extraLoadWeight", Factory().createValueObject(unit = NS.UNIT + "Kilogram", description = "Vehicle's extra load (consumables and passengers weight)"));
1523     car.add("auxiliaryEquipmentConsumption", Factory().createValueObject(unit = NS.UNIT + "Watt", description = "Vehicle's instantaneous auxiliary equipments consumption"));
1524     car.add("maximumAcceleration", Factory().createValueObject(unit = NS.UNIT + "MeterPerSecondSquared", description = "Maximum acceleration (> 0.1), based on vehicle's acceleration capacity and expected driving behavior"));
1525     car.add("maximumDeceleration", Factory().createValueObject(unit = NS.UNIT + "MeterPerSecondSquared", description = "Maximum deceleration (< -0.1), based on vehicle's braking capacity and expected driving behavior"));
1526     i.add("vehicleData", car);
1527         
1528     tc = TemporalContext();
1529     averageVelocity = Velocity();
1530     route = Route();
1531         
1532     tc.setDescription("The timespan estimated for traveling the route.");
1533     averageVelocity.setDescription("Estimated average speed for the travel.");
1534         
1535     averageVelocity.setGroundSpeed(Factory().createValueObject(unit = NS.UNIT + "KilometerPerHour", description = "Velocity component in relation to road surface."));
1536     
1537     route.setLength(Factory().createValueObject(unit = NS.UNIT + "Kilometer", description = "Total length of the calculated route."));
1538     route.setEnergyConsumption(Factory().createValueObject(unit = NS.UNIT + "KilowattHour", description = "Total energy consumed in driving the route."));
1539     route.setAverageVelocity(averageVelocity);
1540     route.setDuration(tc);
1541         
1542     o.add("routeData", route);
1543     return service
1544
1545
1546 def registrySearchTest():
1547     serverIdentity = "http://seasexamples.asema.com/api/Ctestserver"
1548     agent = SearchAgent(serverIdentity)
1549     SearchAgent.setDebugMode(True)
1550     
1551     # all entities in Otaniemi, Espoo as defined by the given polygon
1552 #     polygon = []
1553 #     polygon.append(Coordinates(None, 60.178, 24.829))
1554 #     polygon.append(Coordinates(None, 60.183, 24.83))
1555 #     polygon.append(Coordinates(None, 60.1926, 24.842))
1556 #     polygon.append(Coordinates(None, 60.187, 24.809))
1557 #     polygon.append(Coordinates(None, 60.181, 24.818))
1558 #     agent.polygonSearchArea(polygon)
1559 #       
1560 #     entities = agent.search()
1561     # or
1562     #entities = SearchAgent.searchById(serverIdentity, 500, "http://127.0.0.1/smart/97f2468a47792c27eec4f82fa4795cf35e94ef3b")
1563     entities =  SearchAgent.fetchBySmartAPIId(serverIdentity, "http://acme.com/services/Cweather")
1564     
1565     print entities
1566 #     for e in entities:
1567 #         print e.getName(), "-", e.getId() 
1568 #         for ty in e.getTypes():
1569 #             print '------', ty   
1570         #e.turtlePrint()
1571     
1572 def capacityTest():
1573     now = datetime.datetime.now()
1574     
1575     c = Capacity(value = Variant(3), maximum = Variant(4))
1576     stringData = Tools().toString(c, SERIALIZATION.TURTLE)
1577     
1578     print "Serialized data:"
1579     print stringData
1580
1581     print "Parsing back the serialized data..."
1582
1583     c_parsed = Tools().fromStringAsObj(stringData, serialization = SERIALIZATION.TURTLE)
1584     reserialized = Tools().toString(c_parsed, SERIALIZATION.TURTLE)
1585     
1586     print "----"
1587     print "Re-serialized:\n", reserialized
1588     
1589     
1590 def cryptoTests():
1591     crypto = SmartAPICrypto()
1592     clientKeyId = "http://www.acme.com/services/abcd/"
1593     publicKeyServer = "http://127.0.0.1:11371"
1594     
1595     # Test the generation of keypairs
1596     priv, pub = crypto.generateKeyPair()
1597 #     print "Got private and public keys"
1598 #     print "Public is:\n", crypto.convertPublicKeyToPemFormat(pub)
1599 #     
1600 #     # Test fetching a public key for clientIdUri
1601 #     clientPubKey = crypto.downloadPublicKey(clientKeyId, publicKeyServer)
1602 #     print "Got a public key\n", clientPubKey
1603 #     
1604 #     # Test loading keys    
1605 #     current_path = os.getcwd()
1606     pubKey = pub #getPemPublicKey(os.path.join(current_path, "testkey_public.pem"))
1607     privKey = priv # getPemPrivateKey(os.path.join(current_path,"testkey_private.pem"))
1608     
1609     # Test signing and hashes
1610     testData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras dapibus, sapien eu consequat faucibus, ligula purus tincidunt orci, tincidunt mattis orci dolor in eros. Praesent eget enim ante. Curabitur eleifend ipsum orci, quis vehicula lectus auctor vitae. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean congue nisl lectus. Fusce varius aliquam velit at varius. Integer eu bibendum mi, eget rhoncus metus. Morbi efficitur massa et leo viverra hendrerit. Integer fermentum, dui sed gravida interdum, orci nibh posuere elit, a tincidunt tortor urna a eros. Proin ornare ornare massa quis dignissim. Sed sit amet sapien turpis. Fusce tempus turpis vitae nunc tincidunt ornare. Nulla sit amet scelerisque lectus. Nulla facilisis ipsum ac elit fermentum pharetra. ";
1611     signature = crypto.sign(privKey, testData)
1612     print "Created signature: ", signature
1613     signedProperly = crypto.verifySignature(signature, pubKey, testData)
1614     print "Signature test result: ", signedProperly
1615         
1616     # Generate a session key
1617     sessionKey = crypto.generateSymmetricKey()
1618     # Encrypt data with sessionKey
1619     encryptedResponse = crypto.symmetricEncrypt(sessionKey, testData)
1620     print "\nEncrypted response:\n", encryptedResponse
1621         
1622     # Encrypt sessionKey with client's public key
1623     encryptedSessionKey = crypto.encryptAndEncodeKey(pubKey, sessionKey)
1624     print "\nEncrypted key:\n", encryptedSessionKey
1625
1626     # Calculate a hash for the encryptedResponse
1627     responseHash = crypto.createEncodedMessageDigest(encryptedResponse)
1628     print "\nHash for the response: ", responseHash
1629     
1630     # Verify hash
1631     hashmatches = crypto.verifyEncodedMessageDigest(responseHash, encryptedResponse)
1632     print "Hash verification: ", hashmatches
1633         
1634     # Open the session key
1635     decryptedSessionKey = crypto.decryptAndDecodeKey(privKey, encryptedSessionKey)
1636     decryptedData = crypto.symmetricDecrypt(sessionKey, encryptedResponse)
1637     print "Decrypted data: \n", decryptedData
1638
1639 def keyServerTest():
1640     crypto = SmartAPICrypto()
1641     current_path = os.getcwd()
1642     
1643     content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in lectus at sem commodo venenatis. Fusce in eros ex. In hac habitasse platea dictumst. Phasellus dignissim, augue vel aliquet pretium, nibh eros tristique est, dignissim aliquet elit justo vel mauris. Vestibulum a posuere nulla. Curabitur aliquam semper sagittis.";
1644     keyId = "http://demo.smart-api.io/testkey"
1645     publicKeyServer = KEYSERVER_URI
1646     downloadedKey = crypto.downloadPublicKey(keyId, publicKeyServer)
1647     
1648     if downloadedKey is None:
1649         print "No key found in downloads"
1650     else:
1651         print 'download key successfully!'
1652         print downloadedKey
1653         
1654     pubKey = getPemPublicKey(os.path.join(current_path, "testkey_public.pem"))
1655     privKey = getPemPrivateKey(os.path.join(current_path,"testkey_private.pem"))
1656
1657     signature = crypto.sign(privKey, content)
1658     verified = False
1659     try:
1660         verified = crypto.verifySignature(signature, pubKey, content)
1661     except:
1662         pass
1663     print "Signature verification, key on disk ", verified
1664         
1665     try:
1666         verified = crypto.verifySignature(signature, downloadedKey, content)
1667     except:
1668         print "Exception in verifying with downloaded key"
1669         verified = False
1670     
1671     print "Signature verification, downloaded key ", verified
1672     
1673 def keyHandlingTest():
1674     privPem, pubPem = Tools.createCryptoKeys()
1675     print privPem
1676     print pubPem
1677     Tools.uploadPublicKey(pubPem, "http://demo.smart-api.io/testkey", "senni", "12345")
1678     Tools.revokePublicKey("http://demo.smart-api.io/testkey", "senni", "12345")
1679     
1680     #SmartAPICrypto().createAndSaveKeyPair("http://demo.smart-api.io/testkey", 'localpath.pem', KEYSERVER_URI, "senni", "12345")
1681     
1682 def simpleHashTest():
1683     current_path = os.getcwd()
1684     pubKey = getPemPublicKey(os.path.join(current_path, "testkey_public.pem"))
1685     privKey = getPemPrivateKey(os.path.join(current_path,"testkey_private.pem"))
1686     
1687     r = "Simple hash input"
1688     responseHash = SmartAPICrypto().createEncodedMessageDigest(r)
1689     print "\nHash for the text: ", responseHash
1690     
1691     signature = "ciTATVtKvAZxwYOBKNcbupgLCfwpuJ+SDjC1JXZYNBXyjSxYxalbmsDhI52nyse32SbbJp6TCj276nkX9wcM3gr7jnDovO4mPtucHHC8L38EHN9/vs8zWl4mh8VQ2Q+kbIl14K+cpacPKVo3KCRKaixnTktFBMbiEHh7S0VWuGICrY3cMS1j3mGrZ3J4lYmhGYTNdFiWGw/8N/DabduBX0RKNcTPa8OCGS9mYMOujEK49932KJ5jAXO3dXZkzXM/3VXbwZIwz36pQVEjiE9YusVWjO55il6mwdKiLIsgA2L2LMjhlWgXsKPwZj3F9fgAxQlfppRrVbeD62150e5i7A=="
1692     data = "Some simple data";
1693         
1694     verify = SmartAPICrypto().verifySignature(signature, pubKey, data);
1695     print "Verify result: " , verify
1696
1697     sig2 = SmartAPICrypto().sign(privKey, data);
1698     print "New sig: ", sig2
1699     print "Old sig: ", signature
1700     
1701     hexbytes = "40707265666978206e73313a203c687474703a2f2f7075726c2e6f72672f676f6f6472656c6174696f6e732f7631233e202e0d0a40707265666978206e73323a203c687474703a2f2f736d61727465672e6f72672f6f6e746f6c6f67792f312e302f73656173233e202e0d0a40707265666978206e73333a203c687474703a2f2f7777772e77332e6f72672f323030322f30372f6f776c233e202e0d0a40707265666978207264663a203c687474703a2f2f7777772e77332e6f72672f313939392f30322f32322d7264662d73796e7461782d6e73233e202e0d0a4070726566697820726466733a203c687474703a2f2f7777772e77332e6f72672f323030302f30312f7264662d736368656d61233e202e0d0a4070726566697820786d6c3a203c687474703a2f2f7777772e77332e6f72672f584d4c2f313939382f6e616d6573706163653e202e0d0a40707265666978207873643a203c687474703a2f2f7777772e77332e6f72672f323030312f584d4c536368656d61233e202e0d0a3c687474703a2f2f736561732e6173656d612e636f6d2f64617461736572766963652f736f6c61722f50617269732f6f666665722f436f4339555a6d787a733147624e396a6c4a4b445163513d3d3e2061206e73313a4f66666572696e672c0d0a20202020202020206e73323a5265666572656e6365203b0d0a20202020726466733a6c6162656c20225072696365206f6666657220666f7220736f6c61722070616e656c2067617465776179207365727669636522203b0d0a202020206e73313a686173427573696e65737346756e6374696f6e206e73313a53656c6c203b0d0a202020206e73313a686173507269636553706563696669636174696f6e205b2061206e73313a556e6974507269636553706563696669636174696f6e203b0d0a2020202020202020202020206e73313a68617343757272656e6379202245555222203b0d0a2020202020202020202020206e73313a68617343757272656e637956616c75652022302e31225e5e7873643a666c6f6174203b0d0a2020202020202020202020206e73313a76616c69645468726f7567682022323031372d31312d33305432333a35393a3539225e5e7873643a6461746554696d65205d203b0d0a202020206e73313a696e636c75646573205b2061206e73313a536f6d654974656d732c0d0a202020202020202020202020202020206e73323a52657175657374203b0d0a2020202020202020202020206e73313a6465736372697074696f6e2022416e79206b696e64206f66207365727669636520726571756573742e22203b0d0a2020202020202020202020206e73313a6e616d65202253657276696365207265717565737422203b0d0a2020202020202020202020206e73323a73797374656d4f66496e746572657374205b2061206e73323a53797374656d4f66496e746572657374203b0d0a20202020202020202020202020202020202020206e73333a73616d654173203c687474703a2f2f736561732e6173656d612e636f6d2f64617461736572766963652f736f6c61722f50617269732f4370616e656c67773e205d205d203b0d0a20202020726466733a636f6d6d656e7420225072696365206f6666657220666f72207573696e672074686520736f6c61722070616e656c2067617465776179207365727669636520666f72203130206575726f2063656e742070657220726571756573742e22202e0d0a"
1702     bytes = bytearray.fromhex(hexbytes)
1703     sig2 = SmartAPICrypto().sign(privKey, bytes);
1704     print "Proper sig: ", sig2
1705
1706 def crossSystemDecryptionTest():
1707     encrypted = "GUsjdd81ugIzil2isjteOQ==tPkIcebSOYdsS+o6fecuk4MSsA6P++HBv9/7MDuruGvCQvBAAAuMZb5mqyqg/oIjGwAavhi7RHFMG8OtDabbRywW8cWEmt6KKj96fAnozvzuvSbduguOtIiuzgwPVmxURPzHhoKM08bvoQDzhXsfA5YY5eBNDq3SdUHSQIl7rWeyKATjUXOZhlWNwjwkcztF4UCj+g2YcoFRtlaxKFxON2LsGNcNrQght/SBWfX00qys9uXuii9GgMnXjMuP/BlRMC3AZms3BBVAgJD9MvdkBAdU9jN6hpdC0WkXc1IPIumdk5W8jg7mIg9HCzs/g4phGQG5CbHDuSLcns95O5emrNls9K9n0olI7SWfeFwNRimuOUqOk5fO26I7/ELu1jnvVppFzt4MBr13E67CR7PvnQ==";
1708     key = "adUiExOZ/L05Hds1r4W2vg==";
1709     crypto = SmartAPICrypto()
1710     
1711     decodedKey = base64.b64decode(key)
1712
1713     decrypted = crypto.symmetricDecrypt(decodedKey, encrypted);
1714     print decrypted
1715     return decrypted[0:3] == "The" and decrypted[-2:-1] == ". "
1716
1717 def simpleListTest():
1718     print "simpleListTest"
1719     # create timeseries with Evaluations as list items
1720     now = datetime.datetime.now()
1721
1722     # Lists within a context (should use ordered list by default
1723     ts = TimeSeries()
1724     
1725     testList = []
1726     for i in range(10):
1727         e = Evaluation()
1728         e.setValue(Variant(i))
1729         e.setInstant(now + datetime.timedelta(days = i))
1730         testList.append(e)
1731
1732     ts.setList(testList)
1733
1734     # print list items 
1735     print "Printing list before test:"
1736     if ts.hasList():
1737         list = ts.getList().get_items()
1738         for item in list:
1739             print "Value:", item.getInstant().asDate(), item.getInstant().asTime(), item.getValue().getValue()
1740
1741     stringData = Tools().toString(ts, SERIALIZATION.TURTLE)
1742     
1743     # print serialized data
1744     print "Serialized data:"
1745     print stringData
1746
1747     print "Parsing back the serialized data..."
1748     tsParsed = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
1749     # print parsed-serialized data
1750     print "Parsed-Serialized data:"
1751     print Tools().toString(tsParsed, SERIALIZATION.TURTLE)
1752     
1753     # print list items after serialize-parse 
1754     print "Printing list after serialize-parse:"
1755     if tsParsed.hasList():
1756         list = tsParsed.getList().get_items()
1757         for item in list:
1758             print "Value:", item.getInstant().asDate(), item.getInstant().asTime(), item.getValue().getValue()
1759     
1760     print '\n---explain TimeSeries---\n'
1761     ts.explain()
1762     print '\n---print TimeSeries---\n'
1763     ts.printOut()
1764
1765 def identifierManagementTest():
1766     print "Running identifierManagementTest.."
1767     domain = "asema.com"
1768     systemId = "iotc/123"
1769     objId = "/obj%567&/>qwerty/"
1770     
1771     e = Entity(Tools.createIdentifierUri(domain, systemId, objId))
1772     print "identifier creation successful"
1773     e.turtlePrint()
1774     
1775     domain2 = e.getDomain()
1776     systemId2 = e.getSystemIdentifier()
1777     objId2 = e.getObjectIdentifier()
1778     secondObjetcId = e.getObjectIdentifier(2)
1779     print "domain: ",  domain2
1780     print "systemId: ",  systemId2
1781     print "objectId: ", objId2
1782     print "secondObjetcId: ", secondObjetcId
1783     print "identifier partition successful"
1784     
1785     if domain == domain2:
1786         print "domain correct"
1787     else:
1788         print "domain MISMATCH"
1789     if systemId == systemId2:
1790         print "systemId correct"
1791     else:
1792         print "systemId MISMATCH"
1793     if objId == objId2:
1794         print "objId correct"
1795     else:
1796         print "objId MISMATCH!"
1797     if secondObjetcId is None:
1798         print "secondObjetcId correct"
1799     else:
1800         print "secondObjetcId MISMATCH"
1801
1802 def readAndWriteObjectTest():
1803     from SmartAPI.common.HttpClient import HttpClient
1804     from SmartAPI.model.TemporalContext import TemporalContext
1805     
1806     print "Running readAndWriteObjectTest.."
1807     domain = "asema.com"
1808     systemId = "iotc123"
1809     objId = "lamp"
1810     
1811     d = Device(Tools.createIdentifierUri(domain, systemId, objId))
1812     itf = Factory.createInterface("http://asema.com:8082/smartapi/v1.0e1.0/access/nonstandard")
1813     
1814     vo = ValueObject(quantity=NS.SMARTAPI + "Brightness", unit=RESOURCE.PERCENT, 
1815                      types=[NS.SMARTAPI + "Actuator", NS.SMARTAPI + "Dimmer"])
1816     d.addValueObject(vo);
1817
1818     vo2 = ValueObject(quantity=NS.SMARTAPI + "PowerOnState", unit=RESOURCE.BOOLEANUNIT, 
1819                       types=[NS.SMARTAPI + "Actuator", NS.SMARTAPI + "PowerSwitch"])    
1820     d.addValueObject(vo2)
1821
1822     vo3 = ValueObject(dataType=DATATYPE.STRING, description="String message shown on lamp screen, use the lamp keyboard to change the message", 
1823                       types=NS.SMARTAPI + "Sensor")    
1824     d.addValueObject(vo3)
1825     
1826     aRead = Factory.createStandardReadActivity(interfaceAddress=itf, valueObjects=[vo, vo2, vo3])
1827     d.addCapability(aRead)
1828     aReadts = Factory.createStandardReadTimeSeriesActivity(interfaceAddress=itf, valueObjects=[vo, vo2])
1829     d.addCapability(aReadts)
1830     aWrite = Factory.createStandardWriteActivity(interfaceAddress=itf, valueObjects=[vo, vo2])
1831     d.addCapability(aWrite)
1832     aWritets = Factory.createStandardWriteTimeSeriesActivity(interfaceAddress=itf, valueObjects=[vo])
1833     d.addCapability(aWritets)
1834    
1835     # debug print device description
1836     d.turtlePrint()
1837     
1838     client = HttpClient()
1839     #enable debug mode to see printout of uri and request body
1840     client.debugMode(True)
1841     # just some random temporal context
1842     tcx = TemporalContext(None, "2017-08-22T15:18:54.842", "2017-08-23T15:18:54.842")
1843     
1844     #test call to read whole lamp device object
1845     client.getObject(d)
1846     #test call to read brightness value object time series data
1847     client.getValueObject(d, None, tcx, None, d.getValueObjectByQuantity(NS.SMARTAPI + "Brightness"), d.getValueObjectByQuantity((NS.SMARTAPI + "PowerOnState")))
1848     print '------------'
1849     #test call to write time series data to lamp
1850     client.setObject(d, None, TimeSeries(), None)
1851     #test call to write brightness value
1852     d.getValueObjectByQuantity(NS.SMARTAPI + "Brightness").setValue(80)
1853     client.setValueObject(d, None, None, None, d.getValueObjectByQuantity(NS.SMARTAPI + "Brightness"))
1854     
1855 def standardRWtest():
1856     from SmartAPI.agents.SearchAgent import SearchAgent
1857     from SmartAPI.common.HttpClient import HttpClient
1858     from SmartAPI.common.ValidationMode import ValidationMode
1859     
1860     finalResult = True
1861     
1862     print 'Running standard RW test against SimpleRW servlet...'
1863     
1864     now = datetime.datetime.now()
1865     #search for SimpleRW device, should find one
1866     entities = SearchAgent.searchByNameAndType(Factory.defaultIdentity, 500, ["SimpleRW"], [RESOURCE.DEVICE])
1867     for e in entities:
1868         e.turtlePrint()    
1869         brightness = e.getValueObjectByQuantity(NS.SMARTAPI + "Brightness")
1870         powerOnState = e.getValueObjectByQuantity(NS.SMARTAPI + "PowerOnState")
1871         
1872         client = HttpClient()
1873         # enable debug mode to see printout of uri and request body
1874         #client.debugMode(True)
1875         brightnessValue = 0
1876         powerValue = True
1877         
1878         # fetch brightness value
1879         updated = client.getValueObject(e, None, None, None, brightness).getEntities()[0]
1880         brightnessValue = updated.getValueObjectByQuantity(NS.SMARTAPI + "Brightness").getValue().asInt()
1881         #print "Read: ", brightnessValue
1882         
1883         # set new brightness value
1884         if brightnessValue > 50:
1885             brightnessValue = 30
1886         else:
1887             brightnessValue = 80
1888         
1889         # send new brightness value
1890         updated.getValueObjectByQuantity(NS.SMARTAPI + "Brightness").setValue(brightnessValue)
1891         updated = client.setValueObject(e, None, None, None, updated.getValueObjectByQuantity(NS.SMARTAPI + "Brightness")).getEntities()[0]
1892         
1893         # fetch brightness value again to see if it changed correctly
1894         updated = client.getValueObject(e, None, None, None, brightness).getEntities()[0]
1895         newValue = updated.getValueObjectByQuantity(NS.SMARTAPI + "Brightness").getValue().asInt()
1896         
1897         if brightnessValue != newValue:
1898             print "Standard RW test failed. Value (brightness) was not set correctly!"
1899             finalResult = False
1900         
1901         # fetch power on state value
1902         updated = client.getValueObject(e, None, None, None, powerOnState).getEntities()[0]
1903         powerValue = updated.getValueObjectByQuantity(RESOURCE.POWERONSTATE).getValue().asBoolean()
1904         
1905         # set new power on value
1906         powerValue = not powerValue
1907         
1908         # send new power on state value
1909         e.getValueObjectByQuantity(RESOURCE.POWERONSTATE).setValue(powerValue)
1910         updated = client.setValueObject(e, None, None, None, e.getValueObjectByQuantity(RESOURCE.POWERONSTATE)).getEntities()[0]
1911         
1912         # fetch power on state value
1913         updated = client.getValueObject(e, None, None, None, powerOnState).getEntities()[0]
1914         newPowerValue = updated.getValueObjectByQuantity(RESOURCE.POWERONSTATE).getValue().asBoolean()
1915            
1916         if powerValue != newPowerValue:
1917             print "Standard RW test failed. Value (power on state) was not set correctly!"
1918             finalResult = False
1919         
1920         # note that all read timeseries are just generated, not real values and wrote timeseries values 
1921         # are not followed by any actions on the server side
1922         
1923         # fetch brightness timeseries for the last 5 hours          
1924         tcx = TemporalContext()
1925         tcx.setEnd(now)
1926         tcx.setStart(now - datetime.timedelta(hours=5))
1927         readBrightnessTS = None
1928         try:
1929             readBrightnessTS = client.getValueObject(e, None, tcx, None, brightness).getTimeSeries()[0]
1930         except: 
1931             print 'Standard RW test failed. Error while fetching brightness timeseries!'
1932             finalResult = False
1933             traceback.print_exc()
1934         if readBrightnessTS is None or not readBrightnessTS.hasList():
1935             print "Standard RW test failed. Error while fetching brightness timeseries! Zero items in returned list."
1936             finalResult = False
1937         else:
1938             # debug printing for comparing with the ts seen on browser ui
1939             print "Read brightness timeseries:"
1940             for index in range(readBrightnessTS.getListSize()):
1941                 print readBrightnessTS.getListItem(index).asInt()
1942             print "\n"
1943
1944         # fetch poweronstate timeseries for the last 5 hours
1945         readPowerOnStateTS = None
1946         try:
1947             readPowerOnStateTS = client.getValueObject(e, None, tcx, None, powerOnState).getTimeSeries()[0]
1948         except:
1949             print "Standard RW test failed. Error while fetching brightness timeseries!"
1950             finalResult = False
1951             traceback.print_exc()
1952         
1953         if readPowerOnStateTS is None or not readPowerOnStateTS.hasList():
1954             finalResult = False
1955             print "Standard RW test failed. Error while fetching power on state timeseries! Zero items in returned list."
1956         else:
1957             # debug printing for comparing with the ts seen on browser ui
1958             print "Read PowerOnState timeseries:"
1959             for index in range(readPowerOnStateTS.getListSize()):
1960                 print readPowerOnStateTS.getListItem(index).asBoolean()
1961             print "\n"
1962         
1963         # send timeseries command (next 5 hours)
1964         tcx = TemporalContext()
1965         tcx.setStart(now)
1966         end = now + datetime.timedelta(hours=5)
1967         tcx.setEnd(end) 
1968         ts = TimeSeries()
1969         ts.setTemporalContext(tcx)
1970         # set list type
1971         ts.setList(OrderedList())
1972         # 1 hour timestep between data values
1973         timeStep = Factory.createDuration(0, 0, 0, 1, 0, 0)
1974         ts.setTimeStep(timeStep)
1975         currentDate = now
1976         baseObject = brightness # a ValueObject                 
1977         ts.setBaseObject(baseObject)
1978         while (currentDate < end):
1979             ts.addListItem(random.randint(1, 101))
1980             currentDate = currentDate + timedelta(hours=1)
1981         
1982         # debug printing for comparing with the ts seen on browser ui
1983         print "Wrote brightness timeseries:"
1984         for index in range(ts.getListSize()):
1985             print ts.getListItem(index).asInt()
1986         print "\n"
1987         
1988         ts.turtlePrint()
1989         
1990         
1991     if finalResult:   
1992         print "Standard RW test passed."
1993     
1994     test1 = NS.toAbsoluteUri('asema:monkey')
1995     print  test1
1996     test2 = NS.toAbsoluteUri('owl:Class')
1997     print  test2
1998     test3 = NS.toAbsoluteUri('quantity:Power')
1999     test4 = NS.toAbsoluteUri('unit:watt')
2000
2001 def smallTests():
2002     '''
2003     a series small tests used for writing manual
2004     '''
2005     device = Device()
2006     device.add(URIRef(NS.VCARD + "nickname"), "Sheep")
2007     device.add(URIRef(NS.VCARD + "nickname"), "Nily")
2008     device.add(URIRef("http://someProperty"), Evaluation('http://foo'))
2009     device.add(URIRef("http://otherProperty"), -12.34)
2010     device.setCoordinates(Coordinates(None, 12.3, 34.5))
2011     
2012     rets = device.get(URIRef(NS.VCARD + "nickname"))
2013     
2014     for ret in rets:
2015         r = ret.getValue()
2016         print 'result: ', r
2017     
2018 #     props = device.getProperties()
2019 #     for prop, value in props.iteritems():
2020 #         print 'property: ', prop        
2021 #         for v in value:
2022 #             print '    value: ', v
2023     
2024     print 'first value: ', device.getFirstValue(URIRef(NS.VCARD + "nickname"))
2025     nicknameUri = NS.toAbsoluteUri('vcard:nickname')
2026     nickname_var =  device.getFirst(URIRef(nicknameUri))
2027     if nickname_var.isString():
2028         print 'string value: ', nickname_var.getValue()
2029     
2030     object_result = device.getFirstValue(URIRef("http://someProperty"))
2031     print type(object_result)
2032     
2033     otherDevice = Device()
2034
2035 #   device.add(URIRef(PROPERTY.ISCONTROLLEDBY), otherDevice)
2036     # or
2037     isControlledBy_uri = NS.toAbsoluteUri("smartapi:isControlledBy")
2038     
2039     device.add(URIRef(isControlledBy_uri), otherDevice)
2040     device.turtlePrint()
2041     print '-----------------'
2042     myMap = Map()
2043     myMap.insert("myIntegerValue", 27)
2044     myMap.insert("myDoubleValue", 1.267)
2045     myMap.insert("myStringValue", "The slick fox")
2046
2047     myDouble = myMap.value("myDoubleValue")
2048     print myDouble
2049
2050
2051 def conceptValidationTest():
2052     
2053     print "Running concept validation test..."
2054     try:
2055         s = Service("http://concept.validation.test/")
2056         # add undefined concept
2057         s.addType(NS.SMARTAPI + "MyType")
2058         s.add(URIRef(PROPERTY.METHOD), Obj(RESOURCE.READ))
2059         # add illegal value type (string instead of resource)
2060         s.add(URIRef(PROPERTY.METHOD), RESOURCE.READ)
2061         # add undefined concept
2062         s.add(URIRef(PROPERTY.METHOD), Obj(NS.SMARTAPI + "MyMethod"))
2063         # add undefined property
2064         s.add(URIRef(NS.SMARTAPI + "myProp"), "helloy")
2065         s.setName("Concept validation test Service ")
2066         s.setDescription("Sample service description for concept validation test.")
2067         s.setInterface(Factory.createStandardInterface("acme.com"))
2068         s.addCapability(Factory.createStandardReadActivity("http://acme.com/service/Cread"))
2069         
2070         s.turtlePrint()
2071         
2072         # validate
2073         g = OntologyAgent.quickValidate(s)
2074         g.turtlePrint()
2075         
2076         # check that there were errors
2077         if ( g.getValueGrade() < 10 and g.getValueGrade() > 0 and
2078                 g.getConceptGrade() < 10 and g.getConceptGrade() > 0 and
2079                 g.getGrade() < 10 and g.getGrade() > 0 ):
2080             print "Concept validation test passed."
2081         else:
2082             print "Concept validation test failed."
2083     except:
2084         traceback.print_exc()
2085
2086
2087 def velocityTest():
2088     velocity = Velocity();
2089     velocity.setDescription("Estimated average speed for the travel.");
2090         
2091     velocity.setGroundSpeed(ValueObject(value = 10.0, unit = NS.UNIT + "KilometerPerHour", description = "Velocity component in relation to road surface."));
2092     stringData = Tools().toString(velocity, SERIALIZATION.TURTLE)
2093     
2094     # print serialized data
2095     print "Serialized data:"
2096     print stringData
2097
2098     print "Parsing back the serialized data..."
2099     velParsed = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
2100     print velParsed.getGroundSpeed().getValue(), velParsed.getGroundSpeed().getUnit()
2101     
2102     """
2103     start = datetime.datetime.now()
2104     for a in range(1000000):
2105         b = Velocity()
2106     end = datetime.datetime.now()
2107     print end - start
2108     """
2109     
2110     
2111 def conditionalPriceSpecificationTest():
2112     offering = Offering()
2113     priceSpec = PropertyDependentPriceSpecification()
2114     
2115     c1 = Condition()
2116     c1.addGreater(0)
2117     c1.addAction(10)
2118     priceSpec.addCondition(c1)
2119     
2120     c2 = Condition()
2121     c2.addGreater(10)
2122     c2.addAction(20)
2123     priceSpec.addCondition(c2)
2124     
2125     c3 = Condition()
2126     c3.addGreater(30)
2127     c3.addAction(40)
2128     priceSpec.addCondition(c3)
2129     
2130     c4 = Condition()
2131     c4.addGreater(40)
2132     c4.addAction(55)
2133     priceSpec.addCondition(c4)
2134     
2135     offering.addPriceSpecification(priceSpec)
2136     
2137     stringData = Tools().toString(offering, SERIALIZATION.TURTLE)
2138     
2139     # print serialized data
2140     print "Serialized data:"
2141     print stringData
2142
2143     print "Parsing back the serialized data..."
2144     parsed = Tools().fromStringAsObj(stringData, SERIALIZATION.TURTLE)
2145     print Tools().toString(offering, SERIALIZATION.TURTLE)
2146     
2147     
2148 def main():
2149     #objectCopyTest()
2150     #serializeRequestTest()
2151     #longSerializeParseTest()
2152     #propertySerializeParseTest()
2153     #inputOutputTest()
2154     #parameterSerializeParseTest()
2155     #physicalEntityTest()
2156     #waypointsTest()
2157     basicListSerializeParseTest()
2158     baseObjectListSerializeParseTest()
2159     #timeseriesListSerializeParseTest()
2160     #listSpeedTestSerialize()
2161     #listSpeedTestSerializeAndParse()
2162     #listOfMapsTest()
2163     #hugeDataTest()
2164     #registrationTest()
2165     #registrySearchTest()
2166     #capacityTest()
2167     #offeringTest()
2168     #TransactionSerialzeTest()
2169     #requestResponseTest3()
2170     #cryptoTests()
2171     #crossSystemDecryptionTest()
2172     #requestResponseTest4()
2173     #notaryKeyStoreTest()
2174     #simpleListTest()
2175     #simpleHashTest()
2176     #keyServerTest()
2177     #keyHandlingTest()
2178     #listExplainTest()
2179     #serializeParseLoopTest()
2180     #identifierManagementTest()
2181     #readAndWriteObjectTest()
2182     #standardRWtest()
2183     #smallTests()
2184     #conceptValidationTest()
2185     #velocityTest()
2186     #unitPriceSpecificationTest()
2187     conditionalPriceSpecificationTest()
2188     
2189 if __name__=='__main__':
2190     main()