Fixed issues with DependentPriceSpecification
[smartapi.git] / Common / Java / SmartAPI / src / smartapi / tests / TestSequence.java
1 package smartapi.tests;
2
3 import java.util.ArrayList;
4 import java.util.Calendar;
5 import java.util.Date;
6 import java.util.HashMap;
7 import java.util.Random;
8 import java.util.concurrent.TimeUnit;
9 import java.util.Base64;
10
11 import java.io.DataInputStream;
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.nio.charset.StandardCharsets;
15 import java.lang.reflect.InvocationTargetException;
16
17 import java.security.PrivateKey;
18 import java.security.PublicKey;
19 import javax.crypto.SecretKey;
20 import javax.xml.datatype.Duration;
21
22 import org.apache.jena.rdf.model.Model;
23 import org.apache.jena.rdf.model.Resource;
24 import org.apache.commons.lang3.time.DateUtils;
25 import org.apache.commons.lang3.tuple.ImmutablePair;
26
27 import smartapi.agents.OntologyAgent;
28 import smartapi.agents.RegistrationAgent;
29 import smartapi.agents.SearchAgent;
30 import smartapi.agents.SharingAgent;
31 import smartapi.agents.TradingAgent;
32 import smartapi.agents.TransactionAgent;
33 import smartapi.common.ConceptValidator;
34 import smartapi.common.Crypto;
35 import smartapi.common.CryptoKeyWallet;
36 import smartapi.common.DATATYPE;
37 import smartapi.common.HttpClient;
38 import smartapi.common.HttpMessage;
39 import smartapi.common.MessagePart;
40 import smartapi.common.NS;
41 import smartapi.common.PROPERTY;
42 import smartapi.common.RESOURCE;
43 import smartapi.common.SERIALIZATION;
44 import smartapi.common.SmartAPI;
45 import smartapi.common.Tools;
46 import smartapi.factory.Factory;
47 import smartapi.model.Account;
48 import smartapi.model.Activity;
49 import smartapi.model.Address;
50 import smartapi.model.Availability;
51 import smartapi.model.Capacity;
52 import smartapi.model.Condition;
53 import smartapi.model.Coordinates;
54 import smartapi.model.Device;
55 import smartapi.model.Entity;
56 import smartapi.model.Enumeration;
57 import smartapi.model.Evaluation;
58 import smartapi.model.Grading;
59 import smartapi.model.Input;
60 import smartapi.model.InterfaceAddress;
61 import smartapi.model.Map;
62 import smartapi.model.Message;
63 import smartapi.model.Obj;
64 import smartapi.model.Offering;
65 import smartapi.model.Organization;
66 import smartapi.model.Output;
67 import smartapi.model.Parameter;
68 import smartapi.model.PhysicalEntity;
69 import smartapi.model.PriceSpecification;
70 import smartapi.model.PropertyDependentPriceSpecification;
71 import smartapi.model.Request;
72 import smartapi.model.Response;
73 import smartapi.model.Route;
74 import smartapi.model.Service;
75 import smartapi.model.SomeItems;
76 import smartapi.model.Status;
77 import smartapi.model.SystemOfInterest;
78 import smartapi.model.TemporalContext;
79 import smartapi.model.TimeSeries;
80 import smartapi.model.Transaction;
81 import smartapi.model.UnitPriceSpecification;
82 import smartapi.model.ValueObject;
83 import smartapi.model.Velocity;
84 import smartapi.rdf.*;
85 import smartapi.reasoner.UnitConverter;
86
87
88 public class TestSequence {
89
90         public TestSequence()
91         {
92         }
93
94         public static void main(String[] args)
95         {
96                 
97                 TestSequence testSequence = new TestSequence();
98                 testSequence.runSequence();
99         }
100         
101         public void simpleSerializeParseTest()
102         {
103                 Activity a = new Activity();
104                 Input i = new Input();
105                 Output o = new Output();
106                 a.addInput(i);
107                 a.addOutput(o);
108                 
109                 Route route = new Route();
110                 Velocity averageSpeed = new Velocity();
111                 averageSpeed.setGroundSpeed(new ValueObject(NS.UNIT + "KilometerPerHour", 10));
112                 route.setAverageVelocity(averageSpeed);
113                 
114                 o.add("routeData", route);
115                 
116                 serializeReserialize(a);
117         }
118         
119         public void classSerializeParseTest()
120         {
121                 System.out.println("class Serialize Parse Test...");
122                 
123                 try {
124                 String serialization = SERIALIZATION.TURTLE;
125                 
126 //              // ALIVEREQUEST TEST
127 //              
128 //              // run TestAliveRequest and get the reference object string
129 //              String javaAliveRequestString = TestAliveRequest.test(serialization);
130 //              
131 //              // parse to Java object
132 //                      
133 //              AliveRequest javaAliveRequest = (AliveRequest)Tools.toObj(javaAliveRequestString, serialization);
134 //              
135 //              // test print, to be removed
136 //              System.out.println("\nSecond serialization: \n\n" + Tools.toString(javaAliveRequest, serialization) + "\n\n");
137                 
138                 // run C++ TestAliveRequest and get aliveRequest string from there
139                 //TODO
140                 //String cppAliveRequestString = HttpClient.sendPost("http://seas.asema.com/webapps/tests/seasobjects/cpp", "TestAliveRequest");
141                 // parse to Java object
142                 //AliveRequest cppAliveRequest = AliveRequest.fromString(cppAliveRequestString, serialization);
143                 
144                 // run C# TestAliveRequest and get aliveRequest string from there
145                 //TODO
146                 //String csAliveRequestString = HttpClient.sendPost("http://seas.asema.com/webapps/tests/seasobjects/cs", "TestAliveRequest");
147                 // parse to Java object
148                 //AliveRequest csAliveRequest = AliveRequest.fromString(csAliveRequestString, serialization);
149                 
150                 // compare Java object with c++
151                 //javaAliveRequest.equals(cppAliveRequest);
152                 // report here if cross-platform test failed
153
154                 // compare Java object with c#
155                 //javaAliveRequest.equals(csAliveRequest);
156                 // report here if cross-platform test failed
157                 } catch ( Exception e ) {
158                         e.printStackTrace();
159                 }
160
161         }
162                 
163         public void listSerializeParseTest(int listSize)
164         {
165                 System.out.println("Running listSerializeParseTest (list size: " + listSize + ")");
166                 Date testStartTime = new Date();
167                 
168                 // create data
169                 Date now = new Date();
170                 Calendar calendar = Calendar.getInstance();
171                 calendar.setTime(now);
172
173                 TimeSeries ts = new TimeSeries();
174
175                 //ArrayList<Evaluation> testList = new ArrayList<Evaluation>();
176                 smartapi.rdf.List testList = new LinkedList();
177                 
178                 for ( int i = 0; i < listSize; i++ ) {
179                         Evaluation e = new Evaluation();
180                         e.setValue(new Variant(i));
181                         e.setInstant(calendar.getTime());
182                         calendar.add(Calendar.DATE, 1);
183                         testList.addItem(e);
184                 }
185                 
186                 
187                 ts.setList(testList);
188                 printTestTime(testStartTime, "Time");
189                 
190                 // serialize
191                 System.out.println("Serializing data...\n");
192                 String stringData = Tools.toString(ts, SERIALIZATION.TURTLE);
193                 System.out.println(stringData+"\n");
194                 System.out.println("---test print() function \n");
195                 ts.printOut();
196                 printTestTime(testStartTime, "Time");
197                 
198                 // parse back
199                 System.out.println("Parsing back the serialized data...");
200                 Model model = Tools.fromString(stringData, SERIALIZATION.TURTLE);
201                 Resource res = null;
202                 try {
203                         res = Tools.getResourceByType(RESOURCE.TIMESERIES, model);
204                 } catch (Exception e) {
205                         System.err.println("Exception while trying to get smartapi:TimeSeries resource from the model.");
206                         printTestTime(testStartTime, "Test interrupted in");
207                         e.printStackTrace();
208                 }
209                 
210                 try {
211                         TimeSeries tsParsed = Obj.parse(TimeSeries.class, res);
212                         // test if list items are still there
213                         if ( tsParsed.hasList() ) {
214                                 ArrayList<Evaluation> tsl = (ArrayList<Evaluation>)(ArrayList<?>)tsParsed.getList().getItems();
215                                 if ( tsl.size() == listSize ) {
216                                         System.out.println("ListSerializeParseTest (list size: " + listSize + ") passed.");
217                                         printTestTime(testStartTime, "Test executed in");
218                                 } else {
219                                         System.err.println("ListSerializeParseTest (list size: " + listSize + ") failed!");
220                                         System.err.println("Size of serialized and parsed list is " + tsl.size() + ".");
221                                         printTestTime(testStartTime, "Test executed in");
222                                 }
223                         } else {
224                                 System.err.println("ListSerializeParseTest (list size: " + listSize + ") failed!");
225                                 System.err.println("Size of serialized and parsed list is 0.");
226                                 printTestTime(testStartTime, "Test executed in");
227                         }
228                 }
229                 catch (NoSuchMethodException e) {}
230                 catch (InvocationTargetException e) {}
231         }
232         
233         public void arraySerializeParseTest(int listSize)
234         {
235                 System.out.println("Running arraySerializeParseTest (array size: " + listSize + ")");
236                 Date testStartTime = new Date();
237                 
238                 // create data
239                 Date now = new Date();
240                 Calendar calendar = Calendar.getInstance();
241                 calendar.setTime(now);
242
243                 TimeSeries ts = new TimeSeries();
244                 OrderedList testList = new OrderedList();
245                 
246                 for ( int i = 0; i < listSize; i++ ) {
247                         Evaluation e = new Evaluation();
248                         e.setValue(new Variant(i));
249                         e.setInstant(calendar.getTime());
250                         calendar.add(Calendar.DATE, 1);
251                         testList.addItems(e);
252                 }
253                 
254                 ts.setList(testList);
255                 printTestTime(testStartTime, "Time");
256                 
257                 // serialize
258                 System.out.println("Serializing data...");
259                 String stringData = Tools.toString(ts, SERIALIZATION.TURTLE);
260                 printTestTime(testStartTime, "Time");
261                 
262                 // parse back
263                 System.out.println("Parsing back the serialized data...");
264                 Model model = Tools.fromString(stringData, SERIALIZATION.TURTLE);
265                 Resource res = null;
266                 try {
267                         res = Tools.getResourceByType(RESOURCE.TIMESERIES, model);
268                 } catch (Exception e) {
269                         System.err.println("Exception while trying to get smartapi:TimeSeries resource from the model.");
270                         printTestTime(testStartTime, "Test interrupted in");
271                         e.printStackTrace();
272                 }
273                 
274                 try {
275                         TimeSeries tsParsed = Obj.parse(TimeSeries.class, res);
276                                                 
277                         // test if list items are still there
278                         if ( tsParsed.hasList() ) {
279                                 ArrayList<Evaluation> tsl = (ArrayList<Evaluation>)(ArrayList<?>)tsParsed.getList().getItems();
280                                 if ( tsl.size() == listSize ) {
281                                         System.out.println("ArraySerializeParseTest (array size: " + listSize + ") passed.");
282                                         printTestTime(testStartTime, "Test executed in");
283                                 } else {
284                                         System.err.println("ArraySerializeParseTest (array size: " + listSize + ") failed!");
285                                         System.err.println("Size of serialized and parsed array is " + tsl.size() + ".");
286                                         printTestTime(testStartTime, "Test executed in");
287                                 }
288                         } else {
289                                 System.err.println("ArraySerializeParseTest (array size: " + listSize + ") failed!");
290                                 System.err.println("Size of serialized and parsed array is 0.");
291                                 printTestTime(testStartTime, "Test executed in");
292                         }
293                 }
294                 catch (NoSuchMethodException e) {}
295                 catch (InvocationTargetException e) {}
296         }
297         public void listOfMapsTest()
298         {
299                 System.out.println("List of maps test");
300         
301                 Activity a = new Activity();
302                 Input i = new Input();
303                 Output o = new Output();
304                 
305                 a.addInput(i);
306                 a.addOutput(o);
307                 
308                 // Input
309                 ArrayList<Map> controllable_appliances = new ArrayList<Map>();
310                 i.add("ControllableAppliances", controllable_appliances);
311                 
312                 Map appliance1 = new Map();
313                 appliance1.insert("Active", true);
314                 appliance1.insert("ConsumptionRate", 1.267);
315                 appliance1.insert("Name", "String content");
316                 
317                 ArrayList<Map> controllable_works = new ArrayList<Map>();
318                 Map works1 = new Map();
319                 works1.insert("EarlyStartPeriod", 2147483647);
320                 works1.insert("LateStopPeriod", 2147483647);
321                 works1.insert("WorkDuration", 2147483647);
322                 controllable_works.add(works1);
323                 appliance1.insert("ControllableWorks", works1);
324                 controllable_appliances.add(appliance1);
325                 
326                 // Output
327                 ArrayList<Map> controllable_appliance_result = new ArrayList<Map>();
328                 ArrayList<Map> controllable_appliance_work_result = new ArrayList<Map>();
329                 
330                 Map appliance_result_1 = new Map();
331                 Map work_result_1 = new Map();
332                 Map usage_information = new Map();
333                 
334                 appliance_result_1.insert("Name", "String content");
335                 appliance_result_1.insert("ControllableWorkResult", controllable_appliance_work_result);
336                 controllable_appliance_work_result.add(work_result_1);
337                 usage_information.insert("StartPeriod", 2147483647);
338                 usage_information.insert("StopPeriod", 2147483647);
339                 usage_information.insert("WorkDuration", 2147483647);
340                 work_result_1.insert("UsageInformation", usage_information);
341                 
342                 ArrayList<Map> period_consumptions = new ArrayList<Map>();
343                 Map period_1 = new Map();
344                 period_1.insert("Period", 2147483647);
345                 period_1.insert("Value", 1.26743);
346                 period_consumptions.add(period_1);
347                 work_result_1.insert("PeriodConsumption", period_consumptions);
348                 controllable_appliance_result.add(appliance_result_1);
349                 o.add("ControllableApplianceResult", controllable_appliance_result);
350                 
351                 serializeReserialize(a);
352         }
353         
354         public void listOfMapsWithValueObjectsTest()
355         {
356                 System.out.println("List of maps test");
357         
358                 Activity a = new Activity();
359                 Input i = new Input();
360                 Output o = new Output();
361                 
362                 a.addInput(i);
363                 a.addOutput(o);
364                 
365                 // Input
366                 ArrayList<Map> controllable_appliances = new ArrayList<Map>();
367                 i.add("ControllableAppliances", controllable_appliances);
368                 
369                 Map appliance1 = new Map();
370                 appliance1.insert("Active", true);
371                 appliance1.insert("ConsumptionRate", 1.267);
372                 appliance1.insert("Name", "String content");
373                 
374                 ArrayList<Map> controllable_works = new ArrayList<Map>();
375                 Map works1 = new Map();
376                 works1.insert("EarlyStartPeriod", 2147483647);
377                 works1.insert("LateStopPeriod", 2147483647);
378                 works1.insert("WorkDuration", 2147483647);
379                 controllable_works.add(works1);
380                 appliance1.insert("ControllableWorks", works1);
381                 controllable_appliances.add(appliance1);
382                 
383                 // Output
384                 ArrayList<Map> controllable_appliance_result = new ArrayList<Map>();
385                 ArrayList<Map> controllable_appliance_work_result = new ArrayList<Map>();
386                 
387                 Map appliance_result_1 = new Map();
388                 Map work_result_1 = new Map();
389                 Map usage_information = new Map();
390                 
391                 appliance_result_1.insert("Name", "String content");
392                 appliance_result_1.insert("ControllableWorkResult", controllable_appliance_work_result);
393                 controllable_appliance_work_result.add(work_result_1);
394                 usage_information.insert("StartPeriod", 2147483647);
395                 usage_information.insert("StopPeriod", 2147483647);
396                 usage_information.insert("WorkDuration", 2147483647);
397                 work_result_1.insert("UsageInformation", usage_information);
398                 
399                 ArrayList<Map> period_consumptions = new ArrayList<Map>();
400                 Map period_1 = new Map();
401                 period_1.insert("Period", 2147483647);
402                 period_1.insert("Value", 1.26743);
403                 period_consumptions.add(period_1);
404                 work_result_1.insert("PeriodConsumption", period_consumptions);
405                 controllable_appliance_result.add(appliance_result_1);
406                 o.add("ControllableApplianceResult", controllable_appliance_result);
407                 
408                 serializeReserialize(a);
409         }
410         
411         public void routingAndEnergyTest()
412         {
413                 String requesterIdentity = "http://seasexamples.asema.com/api/Crequest";
414                 
415                 // Create a request
416                 Request r = null;
417                 try {
418                         r = Factory.createRequest(requesterIdentity);
419                 } catch (Exception ex) {}
420                 
421                 Input i = new Input();
422                 Activity ar = new Activity();
423                 ar.addInput(i);
424                 r.addActivity(ar);
425                 
426                 PhysicalEntity car = new PhysicalEntity();
427                 car.setWeight( new ValueObject(NS.UNIT + "Kilogram", 1500));
428                 car.add("frontalAerodynamicCoefficient", new ValueObject(NS.UNIT + "SquareMeter", 0.73));
429                 car.add("tireRollingResistanceCoefficient", new ValueObject(0.2));
430                 car.add("gearEfficiencyCoefficient", new ValueObject(0.3));
431                 car.add("batteryCapacity", new ValueObject(NS.UNIT + "KilowattHour", 115000));
432                 car.add("extraLoadWeight", new ValueObject(NS.UNIT + "Kilogram", 510));
433                 car.add("auxiliaryEquipmentConsumption", new ValueObject(NS.UNIT + "Watt", 365));
434                 car.add("maximumAcceleration", new ValueObject(NS.UNIT + "MeterPerSecondSquared", 3.4));
435                 car.add("maximumDeceleration", new ValueObject(NS.UNIT + "MeterPerSecondSquared", 4.2));
436                 i.add("vehicleData", car);
437                 
438                 Request r_received = (Request)serializeParse(r, false);
439                 
440                 // Read some value from the response
441                 PhysicalEntity inputtedCar = r_received.getFirstActivity().getFirstInput().getFirstAs(PhysicalEntity.class, "vehicleData");
442                 ValueObject frontalAerodynamicCoefficient = inputtedCar.getFirstAs(ValueObject.class, "frontalAerodynamicCoefficient");
443                 System.out.println("Got input value for frontalAerodynamicCoefficient: " + frontalAerodynamicCoefficient.getValue().asDouble() + " which is in " + frontalAerodynamicCoefficient.getUnit());
444                 
445                 
446                 // Create a response
447                 String responderIdentity = "http://seasexamples.asema.com/api/Cresponse";
448                 Response r_s = null;
449                 try {
450                         r_s = Factory.createResponse(responderIdentity);
451                 } catch (Exception ex) {}
452                 
453                 Activity ar_s = new Activity();
454                 Output o_s = new Output();
455                 ar_s.addOutput(o_s);
456                 r_s.addActivity(ar_s);
457                 
458                 TemporalContext tc = new TemporalContext();
459                 Velocity averageSpeed = new Velocity();
460                 Route route = new Route();
461                 
462                 averageSpeed.setGroundSpeed(new ValueObject(NS.UNIT + "KilometerPerHour", 34.1));
463                 tc.setDuration("PT1H");
464                 
465                 route.setLength(new ValueObject(NS.UNIT + "Kilometer", 42.3));
466                 route.setEnergyConsumption(new ValueObject(NS.UNIT + "KilowattHour", 12000));
467                 route.setAverageVelocity(averageSpeed);
468                 route.setDuration(tc);
469                 
470                 route.add(PROPERTY.ADDON, 1.22);
471                 route.add(PROPERTY.FRESHNESS, Factory.createDuration(1, 2,3,4,5,6));
472                 
473                 System.out.println("DEBUG: "+route.get(PROPERTY.FRESHNESS));
474                 
475                 o_s.add("routeData", route);
476                 
477                 //serializeReserialize(r);
478                 serializeReserialize(r_s);
479         }
480         
481         public void registrationTest()
482         {
483                 String serverIdentity = "http://seasexamples.asema.com/api/Ctestserver";
484                 Service service = createSampleRegistrationEntity(serverIdentity);
485                                 
486                 RegistrationAgent agent = new RegistrationAgent(serverIdentity);
487                 agent.addEntity(service);
488                 
489                 Response response = agent.registrate();
490                 // print out possible errors on the response
491                 Tools.printErrors(response);
492                 // get response status
493                 if ( response.hasStatus() ) {
494                         Status status = response.getStatus();
495                         // check if the operation was successful
496                         if ( status.hasType(RESOURCE.ERROR) ) {
497                                 System.out.println("Registration failed.");
498                         } else {
499                                 System.out.println("Registration successful.");
500                         }
501                 }
502                 
503                 System.out.println("                    Now try deregister:");
504                 Response response2 = agent.deRegistrate();
505                 Tools.printErrors(response2);
506                 
507                 System.out.println("            now try search:");
508                 SearchAgent agent2 = new SearchAgent(serverIdentity);
509                 agent2.debugMode(true);
510                 // all entities in Otaniemi, Espoo as defined by the given polygon
511                 ArrayList<Coordinates> polygon = new ArrayList<Coordinates>();
512                 polygon.add(new Coordinates(60.178, 24.829));
513                 polygon.add(new Coordinates(60.183, 24.83));
514                 polygon.add(new Coordinates(60.1926, 24.842));
515                 polygon.add(new Coordinates(60.187, 24.809));
516                 polygon.add(new Coordinates(60.181, 24.818));
517                 agent2.polygonSearchArea(polygon);
518                 
519                 java.util.List<Entity> entities = agent2.search();
520                 System.out.println(entities.size());
521                 for (Entity e: entities){
522                         System.out.println(e.getName()+ "-"+ e.getIdentifierUri()); 
523                         System.out.println(e.getTypes());
524                 }
525         }
526         
527         public void symmetricCryptoTest()
528         {
529                 SecretKey key = Crypto.generateSymmetricKey();
530                 String content = "The two men entered the Starbucks on Thursday and asked to use to the bathroom. An employee told them it was only for paying customers. When they then sat in the store without ordering anything, the manager called police, and the men were arrested for trespassing. No charges were filed. ";
531                 
532                 String encrypted = Crypto.symmetricEncrypt(key, content);
533                 String decrypted = Crypto.symmetricDecrypt(key, encrypted);
534                 
535                 System.out.println("Crypto test.");
536                 System.out.println("Original:\n" + content);
537                 System.out.println("Encrypted:\n" + encrypted);
538                 System.out.println("Decrypted:\n" + decrypted);
539                 System.out.println("Key:\n" + Crypto.encodeKeyToBase64(key));
540         }
541         
542         public void cryptoRegistrationTest()
543         {
544                 PublicKey pubKey = null;
545                 PrivateKey privKey = null;
546                 
547                 try {
548                         pubKey = getPemPublicKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_public.pem", "RSA");
549                         privKey = getPemPrivateKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_private.pem", "RSA");
550                 } catch (Exception ex) {
551                         System.out.println("Could not find keys.");
552                         System.out.println(ex);
553                 }
554                 String serverIdentity = "http://seasexamples.asema.com/api/Ctestserver";
555                 Service service = createSampleRegistrationEntity(serverIdentity);
556                 
557                 RegistrationAgent agent = new RegistrationAgent(serverIdentity);
558                 String payload = agent.generateEncryptedRegistrationMessage(pubKey, service).getLeft();
559                 System.out.println("------");
560                 System.out.println(payload);
561                 System.out.println("------");
562                 
563                 // C++
564                 //payload = "PDvrIUEup/eiTAolieUHSFBgV+UI2h0vvuGhHQjnS5QXlBmPKgO4WrJTUyV60Yqx7/baPg28or6Zat4HokK0ZbXux6xUMvYUTkGpzSjrnaulrn7biv5g/p7dTKx89JkVuW0K3Oci2ICDdg4PcYC1EH/7EWVaLUoUcPb1qRn/qBpsDwieBvvHU4Solo59meo26Ch+CL4hLtsTtrdZmtCvUkn1lIFm9vc3WRo5jXZP9vpR5UMRVXDCu007fqeAD7ppgJHI6/U3kIiyc3n54yvgyzKShlAeORIaxNxMSY09QTEtoGr92M5iBoOZYsfdxndfHy0yPNuGvOhO9ab6nrXwlA==";
565                 //payload += '\n';
566                 //payload += "LCBcyYE+8ILCD43DOQGBsg==3poPZG6rbXOdruch0Wo9rtUaeFEOz4qGH3A+WvnH4LEo59Wo46EpGYvQ7mvwqxa8+lifjXR4ewHbrBTz7zHY36NAggvS325cvSuggH3NdUjNQ1t0QXDDC1aVQcc4OnW4TeFdXy5Wga+Kjz6M7m6gx1wAAs73yTFyGtE0ch3YreHq6cwQmxXt5U0m5qu8d15Iy4JVY73Gqw6m9KN0qz+vew+jJRkvXXmcXmNd+WRSyiL+Uq+huSOTHOr2DncDlCkSzC1ApbDKWisghV8W3V33Mg3iVIqQGFxJ102zHS3r/53lkApFR8iXY0aqBliCOsb2+lN2AtN8tf8Au01iGufx6KXnAzEeGFTWX+04Xo3wJCoJiHFKbIFelUFvP5I1VA7Diobq3AiKTJgxOLmI3nPNhYaDv07Whp4fxP1+VQrlKH20EyJdnb3hTUtWVjHMto0oNKujHHmFAXgKGwSIZ+30HdQA1qw3YUvq4+/t4grfKu+doHMKmjp2/mFIRGIhpKXeWS+QggvVVR1sMAng0VaSzlcF/V9Ppq+JXitHi2piH5Ek1BXO2JzaiuTQKYop20VQzTVP8ReHrz1YWYoePCM0yXH4H9r4h8HZy4+Q2fMUtaEoN+o9dmo57J0i2BRRXVjh/h1zO/583uV2rt/hchMDV8tUt4eKwcIqK51UYJuoY7JaOEWJDvqkSlvmtKmHl4JoaFuYgaFXTsamCo+7ABXyuyLVt0IO7pvAKajW1bCvOjcrqK1g7xJf/eFf4wobA5TjJAFCrcwPG8FdCIC6pRRnJqvKxuarJI6ztuZnEezQkGynyT7c/l4ubPXbEUdZTU7cL2dpz4llAlTl4LbRMtFBfEErsmGDIyuXXTO4YTMrAsddrx5ykmQ9yCKCfhigdb7O0yxgsPcHNzr8sa1QEtUJm/Px18P5lsqfk6g4j4VxtsG2i5w7A44fyXWcCgqv9+dhVAy2CGqeHZh384aplkstENVfW5jSDH6kIIxk217MuqSMNUAPVrR4M3RE9iORE5sQ85tiyXdFqsFJtepYsWroPgsbDJWZexasCvvze661fIzQHk71ylSzXSCzI2lZzhBoT+2OfzTUygx17kSHzHxMwyR9LXUouOBuqtugucy9hd2edrCI5+HxbWmTqTvBVKMgZUD+K2SPSkCeUu6mTGyNwcxwGExkMPyyuaBSJEj15aVs8qx/3H0j6gnAlaQCctOhHUuSWUvYudqQ7Ck8vRT+Xl+Iv7Y8MLm4PW4Bgv5M5dqkPujZ5RFU6dAAM40Ea8HfFfgCs1mRGWXk7ERWFam1F5FdmduN15iPgVQQl/WZqwsnzbxtiORzSHFyQHj6grmU7+TXrPvXkggWFkJl+wg5riGPKahZQ92EMibNpim7eiU4BLfxmFnzM5OFLMD44tzotUxZ9AUiw+x23iwm3P/EZ07v5Rsb6B41AAXxW1KtnVDOK/T9a5bAcJuRI2BcrLEZ2XbjdDxCU9+r3P2sKftiFvcDo5n87lv46iUQRAWz86L+XZeeIDkRDgVZvmLcGZPFdwBQjhwa4/ZjrbYa3VZH+26H4M+G0wHzIPcMYu6RVLRpHFhdAiIo7Gp2YhLzCKGVPWSdD36EsuxIS1oc5zGk67bJtYhoxTMTWHHGo8fBJOjXUaeFCLlGHQSgu1dz4d88X1WgCHcWQMbXXPL6zC5dNZN/iHdmqcoBR6kAZQ9vOL2LaltC9yXqTqmvk2vNPq2gs3uFe7pBBMwunWHThLLphy2YlBcNeTdCGAmnPSJfuh6s6apFeS3iqu68Poh5SAw6TQmNz4jEPBRkZW92S3USnP632di/Z5hcMyw5HYaEpD4xCWXyICc38yteQiXGUHoyZkUBDR0wcx3gQF+lhfSmnk3tBOmwrdpPAUeQOiXCDIJxsE5moCxw6xttW1hJGhn8c7nQF2Nl/Gc9oJJSakE9cx7w+g5p38PJY9ABF2ersWBifAotnVDsV2iHtgaD7x1viSQeo1ZKzUV9ZSnUJNPq8TQuecjKil3zGtGzDs1gpYhxtQx23WTttPHa07kr1+cyJF+fBdHYwKPVOJMe4ANToe/MVsFXQ7x8PvjNEVVRNTMe9AFt9TvhytnR01VX637l1pX7QiJxrJkzPYanYFc6jhHIJ14UcEjvUbqwGEcluQiU8Sk+p9b5QTMecF+yhNvoSTYPD/LNrwznY2qdzXHYfUUWizEo9tCyyeiLsfnDhICQatC5PDPh543c2XEonDZ6PyhNmKWAc2u9NvBPr6gWP+hSm2y4TfmZJ9Nw7wYkzWoaV2qlL6keg6Pxo3vCie3clK8C8QpC4lpkhh8SrU4bLMqBLAagjJylehRDnex3nETTaJkO296FaEAYqBIZ+ZeW2+QC9GyODcN831FysBdB3CafzlyI0TFohvkU8sGSVrORQnSF0Qyq2wGZYz4+xtJwxpIdvuL9Ro0fLHq1LcFuF6FKT7USdHxOJo6M/CqheN76GM1UT9Jvnw8O6AfE8i2PSdcmIctEmOnIgFY5OijexqukUWkwhLkwyrOObo4yl7vOhbwJyO0gD3NNVv9J2nDfa1f6e9RrDf3yeib9YROfO57VZazKKLBPFA59iM/yL/FaOXa+aLhT8sF2S6lxMOxiwjZhwK2xDmJlXxaJA63mslrSLhLexbHDrFGi9643JCb4BVSk/qxnWZqO0/xaqqatR0+4fPV9V0sKVOi89poRqMUI4Bu1c/pMC9RbG/HhJTTM6ihKi8wZHK3NJPPgJ3y99OFuosOPcqF527y+PgKtwWBwggShHKNvuMOf3xiQ+DvOuSjOLFWGzmVawdSi3XVNiOsQ10fpSMq+k1ESFx1Is4OvD2kNA+tjZ5bIsDdHDtpFl4cvq3NnfEs1hN8+SwZ6jE9A/LoFSCjOmx83LGmIHiE+w/23Znf0th4NCwMzaP0PjxhzlnOkUwpyr7QnkAw8O6N0g+a9oQ1oLAaM1ZzDUSGEMSRELE3JE+LA4c7/YHzdnZwcD2cTzWYMywijdSLlCfLw+fT7nqrGUzvVpS/bLWtZwR0u3OtsMRtBUvwqi5VSeXa2m5gq7v+uG0udyfHPfdCHr3pJNc0lsbAYEjbrYtRM5v3ygTjCRnljx4+tvgt86oVbgXPCvZODrHbL3fpsz+AO9OmX/aLEv342BquMOG1J6fTnOcoXv+WfjYedIXirSPAKgUe92n9VmLSQKMZMKLFoPTlRAaxWwbI8Q7cxpfPHhfRtklcHxXG0Mg4ulbUf0k3G+KegiP0LNUTctZCtqTFW1sFgwr8fJJBsSGUJg2H64u7ub8/qhUcNMiKWsNaYrNbFmzd2HKVEiqvXCr/cXSHXFMc4RAEFe7IkKRc642KySW4jC+1ZQ2VXvjH4DmhhDYicgSkz2Z10GFiXL+S5n+RKDpyD9/oNWf1Gy5eQuuaHOmS2Z89CZrHr53cAz2biIK1vB4TEh3YLcZD1SuBLdg+MGdEYM16svb8pO7tIGUzeqX+GXYB1D2fWLNVk8zFtwTVH8vOZybibdYZYPhjteLuk5yiAxLIBshPVtH/IV9PY57Rp0GRHgtvLZXRyKn8hg8631NuwdVV1hIPWHs/VLB0wPFFySgpIbdZuqnCdGTFMS0KDT2hTquRE2pZ3XR6leTMBTjFaAj1oDB5PYntgy1NFEdAaGUZPIxlnfnyoKkqUoaSou2aWo+AyIdb+169VHaSDZMPiQRlf6iQdrTSY7A86xlqO9t6F5sWepLYVJTAbi5+MHxEXJRnFOE3+bu8cH4JYnBMzVw2TlTW4prs9w6o8qNofYiQIxHOMdprjBgQONBGy8QOoQCiWKVG+zOs3mkT6VhJYnWGZRzuy/MD1MvUZo8CDT3F1bpvSwVqBIDQd5aAXqVycvvVjER+PnLrBl0K3UCFHKr1nB9xH1ilDR3pLUXRiCsxlEtIalrn6A3G8JvPw0l2oENVyrAVCpiaAQhP5ELwiq6uhXPvUvfODsJTD3WJGIfjMDYkgujaNVKCKh1KIasRMx/+vdCFSPXp/bGzsQTyuLPu3sODdzFaMMMPgrrA0N4uvlotqHkQ5sQ2ZICZr0Ek7lxRLn6+7r3t3XJwh8qF4P6MMXgmA5peZ2jrcauM0sLZKqCsslFj+YIA8xlFVcs3CjomIrpqr82FkrqtAV6xPAIjYq/w7YkQ5W6K6vEjeQCpbmjSx7h3B0919rymkNtASbGccDWu70UWIPKVfqtUEahlOLcsOIpH5D6r1SddGHhurFc8vzY3qmgC7c1jxTGE0MkekEF78QZwrmBh/lBjSREbMKVmAdl5SJ1zQRwVI/Pxmk091eWsesoCgdZ+wE9gK7xf4eLRgrab5OrTGD+4D9DgJymMhv2vB9OWwkQ0YePe56EReA4y7yfgupF+9dj7w76dGidhXFjLdW83Nuc8C2PZL82R3erViacXjstAfEQPhTielWYXnc6bEWHLhM9iui3KErxinAGUa0rDfAQ4sjyU9wIfEcaGgx0pqMWnn94p0Fnngzh5MqWdQfKzslYZoCDkgdzMIUP1ylWrHje18SLYRSPX0tnBXZ0oyAz0Rg/RYiHFcVXq/1AIHXgs0SjOnjxsigYfWTFbR1rOus94R7OXx1+gxnYBAjnbpyEgWfRvUdHRce+DEKxG7jwWtRrkasGic0lnPAqBGVfzUF2wfMc+wF/IR0/eqWSrxuaY22EB2ZAI1WP1i7zanVEKrRa+r//11Nb8ihsqb83Re+TQeYZhHf/PEBrNI4nqiPGZ9nvJ+iRtK8Q9cmKwnRgV4bt1MrhfbuhluV145C3w0Pc6zWSCTdLe1/0O9utdVoZbP6d1buDkFTy1xW80HqhsvDj6rtb1yrpwPmmw3EaIbfli2QAqbjcPgOv5kVtdPdYPR28753Kf6gaug0C/1+s7jQarAaR00HQaAPGuDBvaX5hxI3rk/X1jTKZ1DI5yfG33vwx03XhGZ/7GuZrfIlJaqinMDQkF6tLo8KFl0XV5yPcsHolOKKi5zcNSGP0OpPqxIS4dqmgbF7tK6s3/Mc3xEH9JXgNnLNM9Wy3919RF2CZ1gyunXDTXASJ2gkcuVlpQgnR0MjhyoYs1W+TUuEOPQRd/on4ztaXqiVISdfcL4Hp8NM0U/kN3NOWsZ3OmPptiBWX0M4usKIdU0iIJu9O8/e3vHlK/3g9Ln8vKXheraPqJWw43XX+V/9QoYnkqz5Uwfl/lYPmfcTOhpI/DKK2xWFLyOWPECU/BgDMfDZvKzmnBQb2tH/1MV6Kc+G50MbCp7LpzrQF6+4cXYq9gQNwTpjyBJN4g6QSiQK9r2uWv4IyPYnJYWcv4bkeipt8ELoycZ5Qxf1cw081678I5QwiWGwceaNrGXurGIaFjm0kGYKOS1SSce7shnhVnwAys5g95Mx1q2peJfuumUe+a4H6wGT0febyaFqpDYMRcqdEsDVwTwZj0E3mrX58gA6J62DKNXg3CykmqlbsSI7aPsCYJKY3U50AyBxyzjK0c5LtsMGm7GFoCzFd2PunjP2NvspcJzzu38W7knqMaWe1MQ9nrCE291coELZUWzQSVj1DkCuejT+ZCk/4i6yXFuNbByAu1o2nsTEsgXuY51MD11c63aFz9mxfMMJsCeAQwppqG6RS/5Af6LYMTdASrMtw47IQdfA1gyKWS0l4GrPsPYH3CPL6SMMbyEidtUI69MK0d/G415Z+E/Bgh4EfAXk9rkxP/iocb3k/x+qtTtWJNpxlkFPClGhc+whPYV1ozwiSpjGfgFoNS9wQNYj+ofdYTSwa7Oh9vytNVnJNdWoDqGXzkf8rx+K/CB+DJJAfbjzKKYBaBHv8T9Fl6Mhi6+tGUgThGodVzVrgiayLys1EV7sbXJmfQ9+dRpNt14yXUyOfCWR7CUnQUGORQ77XSjuBRw2YyZdEg8P122F/2dozbfUlTKyFh4s2NgDN3Ymc584VnZs29xfowDlFIjKdWu1eFWeqm7+vNqD2Ymr5kXgw+Eqz7KrhHrVqlIVE4+fWCu49Bc8GubGK/Ud6sfknfDY583Rb7bizpVBgO/oNW5BRgpD4oBSkZ3WkVYnZ/QH+8POf6aPIbO2/RTmnCLeKUEKmWfyOooRJq2H2nVdMx/HraOHhaSqGrSRHAi4wnyu/yqrdpT+BxKeUXUyRY2QitD5NYQn9fIuzkwrdeu8jFFw2Dw2gZWR6sWHn37som+0eqvCJ3W4Yri19t/mvjBd4BUdHORyfP5gtmtdsEyJgYhMpLLiQFmOqM+7RcaRZakNWL4Pnm3ftzMY1U6LdX98y7Ma8fDEUXb6flkNtMuNKNs4TNxqJ2xac0oq/JuBAie0VyV6HSeQiGfKoPYXL/CH8raOPVXSpdvnrH6VqhAsnznTh/6q/szvPbeXRGraa1XtrQVzjvrB7fIQ+iiMSmVXIceRoB0tyeSIkxjH56Ds8JmOCL9I5bjiYa+mMIRH5AUhSozKvq6ZN7DcKptCSedKPkpWBOrwQhFIl3LxvoC5gwp5WLXph04VJnC9E+A4LD8mKbns041bb69pGhbUYD2s8BUogC4SG6UwdOd+pNtShIHjw2Zs+f/S5OHwF3ebFdIiQ/eEzJ/aJ8e3Yd/VebJYMp6jCkWkZtGjJzJq1BCgNzwAabH5AWmGe1g/55FeLcKSHLF5MHyw1HWEr5Tgnlfu3eBW///l8gcVEfSHD5kA13GDOKt4OeN2Mg2KAPMKAQVIS2jSgk31jZt89XOpInJnJm5ul6S+ltHhHfAYHFsG4qt2H9QP7KF2/PIJVZRCo6D72vLaD6cpQm7+KShy9GRBQlN2Gl7qEZIpg5VX4dALNC0Ggi9tRaGXxyEXURtIEe/Rk52mN/ty8+WlV5/KSlIcDe5j5MNxLMIuIRayHLUE1DGVflwFYA+hdg8eaRk1uAGLoHGicwbB4e7YVVd4xDrSFh+8euMl1AHAf3Q8M5ZR4eH2UoVIMP7rylUeU3jkL6yqvZaoLWp5htH5azNsdPT7vihip3wcec/kB5WW42NjbeKUTT6wHbltxK7vKKo7OOt48+jVLh5AAZjE7eqFseeCqAM+k3dXNFTiu6nvbjUSV7UybXd7dUL73p8VvHxNFfdJJcP1iFMbVkbxduWApdoHPk36afWr7jodEiocITOwQauQOlI27U7oD8bQdYmX+b8GMJUhrjUG5WRW6feOMKUWKikbePS7WGyqpnVOEYmQOhwk7+ZAMXErwZoijv1qgIfmzjVcFpAuV+KHqFF3pL8E3BeQjQTVytnq5n56H4wptLJGFp7kP2wCrNoglpE7qlEoskmcj7KjiPXXj1RPQDD3FXVj9cTKTQlz+XfyH2TV2aGQlpfTrbjVRs6Ump3kMOkpFMglNatILEOJs6jbZaCYx8coCDNw3r4QcSDL0lTZNAT50zcmJvDSSSNXerdAS3rAWgg6reQr1JyuTnVYIGj03KSr3/3pSwZl45Fj0tMPOc8zp6vZh8gt0in1siqfeiG1I6kdjcfyBezJAN4Q8dwbBcv+iP4nhxuuAchfD4CHHhMhIAz2Td7p/AeWxRrkcMx3OdBdGyadsW3durEXTcX4zflpSNAMTT5I7vuHlKtpk6TgEPIDmW3pCKtKVQBJ9XeNwQ5FkMQ0RFGXbXVZZIFieZJMpEc9NSao23NSpfvqjzGl47fO1GnJFOxt8Lcv/v4Xes7EP8fzfDzkCq2vt9EOjYGcvTe8rcAWTSr/2nkz5iNp/YkYw4bjEqgs3y+0s7hsULoKA32YPDo0oikdxQ96vdc8jVZBWQx3xUbVzLg00K60uSgti3+Vt0uMGx/OO/teuod6pgMTnSJWKcjgB5bKUgs9vhpXuqck1he6i3DlCn0na4EwSbCe3thZz6H6OCo5Ei10LvgDE5Dzq0GFTL+fbnqC+VUZw3BtB0fgkpaBmFGeE0xD3RbEoPVD2FKqO1/H2b1LhckiXRE+dMrWncHEHEjauZoktmrhIjwMpo6+nC08rCbrAdQcmhJKXNRQEoAb8O1cFI0iXFLynH7Jk4nA7vx42qVxSIPx4Wv5UL3keOXY+6/DP5wxLHjCTeGD9eYkhiZXnCJLwk7qXQu68DSvSyFaRyA5weWcs5bQGyuIf5iX7df7UeR1vDHreLYP1zafQOsBe8g7k3HOstUDp+LeAZkuzWKumk77xsDYjl6QVtf1/1IPcAauwzeNIu9dbxO/wAVSOxw59OedHkijkbxI7z8o5BgMVUMfFmGiocXkq0NbLzFmFkJuXKhW6FU4ITLkRPqoXzWhT6NGQ/MBlkxskSPzFdcot3ZOK1YsClups6GTM613kGXHDoPfP+oFB0NGwIwf3QA5YHvs5T1nhnf6jbJLiHx43Wwg2E9hPvim7nmKKxFUNTBT2MdL9Pq4hh+yvKzxGZ///3NLJ45rkzfB0ImP2lyF3NFCEEb2r3wrU9vqDywTJmAH5mK8p8M0T2bfX7BJbtAFHVMxfz4pQ6tyLQfgLOVY9WJqbrPPXhaxFs6b2Q/QlSL/6Zpj2tHBwep78LpyGZWNkzu0KSnsJ0QJJQDOIjZXqOAwicCAnAM1xe9XNKkBZnsVvCRUvyQ0lV3W2l5RSqdQtwdb2OzdUes9QKttQ4ydXL1JwphSuYxxNOTuI9WDcXAD63aGHNzX37tKRuBsVKGFVs38fMKjcrKAXRtP0zV1Z2RNtX13nL3Q/k7pEhOwonM3cOc/EVgP8eYGyIUjTPzfEjo39JN5M90m3Kybq9PX0pBDui0IuI9hPHHP7CZmu1NlU9I68Zbk+oslaQFdoEtt0bbLA+8eaLj//3o";
567                 
568                 // Python
569                 //payload = "fYM/MR0yq2nDAvDM8xEg6VvEyvz9eWZefFylY6vaQr3syQw2vATDpv7DZIUdb3fsGbX9kboJNSSQTOTEG/VDhjnPz9DWLJXygRE3868ywyhzn5ojKrBMwf+ehvYfMnJI5gco+EzbO8zFuCC2yukJV/FA72y3OV3r/BGRSsJ+r+vZrwzF92m0rAJD0qrZ/ENfxEOgtXYUAs/glcxSi0fKUtrXledAnblusSXbg6iIdPBb7+5A+OadBg8oPZqIkZT2RwscsshEUDWlXYmZhmWjAkcNhiJiU1SJU9bt0oXBTVprmMBdzxlmU00xBnBj9qsu44e73I3YDIz04jnrcS8PzQ==";
570                 //payload += '\n';
571                 //payload += "Zh8VwrOxzMgke5nGy2WVaQ==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";
572
573                 ImmutablePair<String, SecretKey> decrypted = Crypto.asymmetricDecrypt(privKey, payload);
574                 System.out.println(decrypted.getLeft());
575                 System.out.println("------");
576                 String ct = Crypto.symmetricEncrypt(decrypted.getRight(), decrypted.getLeft());
577                 //System.out.println(ct);
578                 String pt = Crypto.symmetricDecrypt(decrypted.getRight(), ct);
579                 //System.out.println(pt);
580         }
581         
582         private String loadKeyFile(String filename) throws Exception {
583                 System.out.println("Loading key: " + filename);
584                 
585                 File f = new File("src/smartapi/tests/"+filename);
586                 System.out.println(f.getAbsolutePath());
587                                 
588                 
589                 //File f = new File(filename);
590                 FileInputStream fis = new FileInputStream(f);
591                 DataInputStream dis = new DataInputStream(fis);
592                 byte[] keyBytes = new byte[(int) f.length()];
593                 dis.readFully(keyBytes);
594                 dis.close();
595
596                 return new String(keyBytes);
597         }
598
599         private PrivateKey getPemPrivateKey(String fileName, String algorithm) throws Exception {
600                 String keyData = loadKeyFile(fileName);
601                 return Crypto.extractPemFormatPrivateKey(keyData, algorithm);
602         }
603
604         private PublicKey getPemPublicKey(String fileName, String algorithm) throws Exception {
605                 String keyData = loadKeyFile(fileName);
606                 return Crypto.extractPemFormatPublicKey(keyData, algorithm);
607         }
608         
609         public static Service createSampleRegistrationEntity(String serverIdentity)
610         {
611                 String serverName = "A fantastic Java route energy calculation service";
612                 
613                 Service service = new Service(serverIdentity);
614                 
615                 // Service metadata
616                 Organization owner = new Organization();
617                 Address acmeAddress = new Address();
618                 InterfaceAddress iface = new InterfaceAddress();
619                 
620                 iface.setHost("www.acme.com");
621                 iface.setScheme("https");
622                 iface.setPath("/seas/v1.0e1.0/access");
623                 acmeAddress.setStreetAddress("Giant Rubber Band Street");
624                 acmeAddress.setZipCode("12345");
625                 acmeAddress.setCity("Fairfield, New Java");
626                 owner.setName("Acme Industries");
627                 owner.setAddress(acmeAddress);
628                 
629                 service.addInterface(iface);
630                 service.addOwner(owner);
631                 service.setName(serverName);
632                 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.");
633                 service.addWebsite("http://www.acme.com/acmeoptimizers/roadrunner/beep/beep");
634                 
635                 
636                 // API payload data
637                 Activity a = new Activity();
638                 Input i = new Input();
639                 Output o = new Output();
640                 a.addOutput(o);
641                 a.addInput(i);
642                 service.addCapability(a);
643                 
644                 PhysicalEntity car = new PhysicalEntity();
645                 car.setWeight(Factory.createValueObject(NS.UNIT + "Kilogram", "Vehicle's weight without any consumables or passengers."));
646                 car.add("frontalAerodynamicCoefficient", Factory.createValueObject(NS.UNIT + "SquareMeter", "Product of vehicle's frontal area and aerodynamic coefficient"));
647                 car.add("tireRollingResistanceCoefficient", Factory.createValueObject(new Obj(DATATYPE.INTEGER), "Vehicle's tire rolling resistance coefficient, in interval ]0, 1["));
648                 car.add("gearEfficiencyCoefficient", Factory.createValueObject("Vehicle's efficiency coefficient between engine and gear, in interval ]0, 1["));
649                 car.add("batteryCapacity", Factory.createValueObject(NS.UNIT + "KilowattHour", "Vehicle's capacity of the battery (enter only if electric vehicle or hybrid rechargeable, 0 otherwise"));
650                 car.add("extraLoadWeight", Factory.createValueObject(NS.UNIT + "Kilogram", "Vehicle's extra load (consumables and passengers weight)"));
651                 car.add("auxiliaryEquipmentConsumption", Factory.createValueObject(NS.UNIT + "Watt", "Vehicle's instantaneous auxiliary equipments consumption"));
652                 car.add("maximumAcceleration", Factory.createValueObject(NS.UNIT + "MeterPerSecondSquared", "Maximum acceleration (> 0.1), based on vehicle's acceleration capacity and expected driving behavior"));
653                 car.add("maximumDeceleration", Factory.createValueObject(NS.UNIT + "MeterPerSecondSquared", "Maximum deceleration (< -0.1), based on vehicle's braking capacity and expected driving behavior"));
654                 i.add("vehicleData", car);
655                 
656                 TemporalContext tc = new TemporalContext();
657                 Velocity averageSpeed = new Velocity();
658                 Route route = new Route();
659                 
660                 tc.setDescription("The timespan estimated for traveling the route.");
661                 averageSpeed.setDescription("Estimated average speed for the travel.");
662                 
663                 averageSpeed.setGroundSpeed(Factory.createValueObject(NS.UNIT + "KilometerPerHour", "Speed component in relation to road surface."));
664                 
665                 route.setLength(Factory.createValueObject(NS.UNIT + "Kilometer", "Total length of the calculated route."));
666                 route.setEnergyConsumption(Factory.createValueObject(NS.UNIT + "KilowattHour", "Total energy consumed in driving the route."));
667                 route.setAverageVelocity(averageSpeed);
668                 route.setDuration(tc);
669                 
670                 o.add("routeData", route);
671                 
672                 return service;
673         }
674         
675         public void transactionProcessingTest()
676         {
677                 String clientKeyId = "http://www.acme.com/services/abcd/";
678                 String publicKeyServer = "http://127.0.0.1:11371";
679                 
680                 // Fetch public key for clientIdUri
681                 PublicKey clientPubKey = Crypto.downloadPublicKey(clientKeyId, publicKeyServer);
682                 System.out.println("Got a public key");
683                 System.out.println(clientPubKey);
684                 
685                 PublicKey pubKey = null;
686                 PrivateKey privKey = null;
687                 
688                 try {
689                         pubKey = getPemPublicKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_public.pem", "RSA");
690                         privKey = getPemPrivateKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_private.pem", "RSA");
691                 } catch (Exception ex) {
692                         System.out.println("Could not find keys for the test.");
693                         System.out.println(ex);
694                 }
695                 
696                 String 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. ";
697                 String signature = Crypto.sign(privKey, testData);
698                 System.out.println("Created signature: " + signature);
699                 boolean signedProperly = false;
700                 try {
701                         signedProperly = Crypto.verifySignature(signature, pubKey, testData);
702                 } catch (Exception e) {}
703                 System.out.println("Signature test result: " + signedProperly);
704                 
705                 // Generate a session key
706                 SecretKey sessionKey = Crypto.generateSymmetricKey();
707                 
708                 // Encrypt data with sessionKey
709                 String encryptedResponse = Crypto.symmetricEncrypt(sessionKey, testData.getBytes(StandardCharsets.UTF_8));
710                 System.out.println("\nEncrypted response:\n" + encryptedResponse);
711                 
712                 // Encrypt sessionKey with client's public key
713                 String encryptedSessionKey = Crypto.encryptAndEncodeKey(pubKey, sessionKey);
714                 System.out.println("\nEncrypted key:\n" + encryptedSessionKey);
715
716                 // Calculate a hash for the encryptedResponse
717                 String responseHash = Crypto.createEncodedMessageDigest(encryptedResponse);
718                 
719                 System.out.println("\nHash for the response: " + responseHash);
720         
721                 // Verify hash
722                 boolean hashmatches = Crypto.verifyEncodedMessageDigest(responseHash, encryptedResponse);
723                 System.out.println("Hash verification: " + hashmatches);
724                 
725                 // Open the session key
726                 SecretKey decryptedSessionKey = Crypto.decryptAndDecodeKey(privKey, encryptedSessionKey);
727                 String descryptedData = Crypto.symmetricDecrypt(sessionKey, encryptedResponse);
728                 System.out.println("Decrypted data: \n" + descryptedData);
729         }
730         
731         public void transactionVerificationTestWrite()
732         {
733                 String referenceId = "http://tests.b.c/ref";
734                 String senderId = "http://tests.b.c/sender";
735                 String myIdentity = senderId;
736                 PublicKey pubKey = null;
737                 PrivateKey privKey = null;
738                 String 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. ";
739                 
740                 try {
741                         pubKey = getPemPublicKey("testkey_public.pem", "RSA");
742                         privKey = getPemPrivateKey("testkey_private.pem", "RSA");
743                 } catch (Exception ex) {
744                         System.out.println("Could not find keys for the test.");
745                         System.out.println(ex);
746                 }
747                 
748                 Base64.Encoder b64e = Base64.getEncoder();
749                 String notary = TransactionAgent.getDefaultNotary();
750                 SecretKey key = Crypto.generateSymmetricKey();
751                 String sessionKeySent = Crypto.encryptAndEncodeKey(pubKey, key);
752                 String contentHash = Crypto.createEncodedMessageDigest(testData);
753                 String signature = Crypto.sign(privKey, contentHash);
754                 
755                 System.out.println("Encrypted content key is: " + sessionKeySent);
756                 System.out.println("Content signature is: " + signature);
757                 System.out.println("Content hash is: " + contentHash);
758                 
759                 /* ---- SEND ---- */
760                 // Emulate send operation
761                 Transaction transaction = null;
762                 try {
763                         transaction = Factory.createTransaction(referenceId, senderId);
764                 } catch ( Exception e ) {
765                         return;
766                 }
767                 transaction.setSigner(senderId);
768                 Message message = new Message();
769                 message.setHashCode(contentHash);
770                 message.setSignature(signature);
771                 message.setSessionKey(sessionKeySent);
772                 transaction.setNotarizedObject(message);
773                 
774                 HttpMessage sentMessage = new HttpMessage();
775                 
776                 //main request
777                 Request r = null;
778                 try {
779                         r = Factory.createRequest(myIdentity);
780                 } catch (Exception ex) {}
781                 r.setMethod(RESOURCE.WRITE);
782                 r.setId(1);
783                 Activity a = new Activity();
784                 r.addActivity(a);
785
786                 Input i = new Input();
787                 a.addInput(i);
788
789                 SystemOfInterest system = new SystemOfInterest();
790                 system.setSameAs(TransactionAgent.getDefaultNotary());
791                 i.setSystemOfInterest(system);
792
793                 Parameter param = new Parameter();
794                 param.setKey("transactions");
795                 param.setName("Transaction id list");
796                 param.setDescription("List of ids of transactions that are sent for storing into the database.");
797                 param.addValue(new Variant(transaction.getIdentifierUri()));
798                 i.addParameter(param);
799                 
800                 String mainRequestString = Tools.toString(r);
801                 sentMessage.add("Main", mainRequestString);
802
803                 String mainRequestHash = Crypto.createEncodedMessageDigest(mainRequestString);
804                 String requestSignature = Crypto.sign(privKey, mainRequestHash);
805                 
806                 // create transaction for the main request
807                 String transactionIdentifierUri = myIdentity + Crypto.generate16ByteCryptoRandomString();
808                 Transaction requestTransaction = null;
809                 try {
810                         requestTransaction = Factory.createTransaction(transactionIdentifierUri, myIdentity);
811                 } catch ( Exception e ) {
812                         return;
813                 }
814                 requestTransaction.setSigner(myIdentity);
815                 Message requestTransactionMessage = new Message();
816                 requestTransactionMessage.setId(r.getId());
817                 requestTransactionMessage.setHashCode(mainRequestHash);
818                 requestTransactionMessage.setSignature(requestSignature);
819                 requestTransaction.setNotarizedObject(requestTransactionMessage);
820                 
821                 // Add the message signature
822                 String requestTransactionString = Tools.toString(requestTransaction);
823                 sentMessage.add(transactionIdentifierUri, requestTransactionString);
824
825                 // Add transactions that are sent for storing
826                 sentMessage.add(transaction.getIdentifierUri(), Tools.toString(transaction));
827                 // with their respective signatures
828                 sentMessage.add(transaction.getIdentifierUri(), Tools.toString(transaction));
829                 
830                 String msg = sentMessage.asString();
831                 System.out.println("Sending: \n" + msg + "\n------------------------ < message end > --------------");
832                 
833                 
834                 /* ---- RECEIVE ---- */
835                 
836                 // Emulate reception
837                 HttpMessage receivedMessage;
838                 try {
839                         receivedMessage = HttpMessage.parse(msg, sentMessage.getContentType());
840                 } catch (Exception e) {
841                         System.out.println("Failed to parse incoming message body");
842                         return;
843                 }
844         
845                 if (receivedMessage.size() < 2) {
846                         System.out.println("Request should have at least two parts");
847                         return;
848                 }
849
850                 // parse all request parts
851                 java.util.Map<String,MessagePart> partsMap = receivedMessage.getParts();
852                 Obj[] objects = new Obj[partsMap.size()];
853                 String[] parts = new String[partsMap.size()];
854                 int mainRequestIndex = -1;
855                 Request mainRequest = null;
856                 try {
857                         int mi = 0;
858                         for (String partId : partsMap.keySet()) {
859                                 MessagePart part = partsMap.get(partId);
860                                 objects[mi] = Tools.toObj(part.getBody());
861                                 parts[mi] = part.getBody();
862                                 if (objects[mi] == null) {
863                                         System.out.println("No object returned when parsing the following part: " + parts[mi]);
864                                         return;
865                                 }
866                 
867                                 if (partId.equals("Main")) {
868                                         // main Request found
869                                         if (objects[mi] instanceof Request) {
870                                                 mainRequest = (Request)objects[mi];
871                                                 mainRequestIndex = mi;
872                                         } else {
873                                                 System.out.println("Main part should contain a Request object");
874                                                 return;
875                                         }
876                                 }
877                 
878                                 mi++;
879                         }
880                 } catch (Exception e) {
881                         System.out.println("Exception caught when parsing objects: " + e.getMessage());
882                         return;
883                 }
884                 if (mainRequest == null) {
885                         System.out.println("No main Request found");
886                         return;
887                 }
888
889                 // now find the main transaction, which satisfies the following:
890                 // (a) its id is not listed in main request as a sub-transaction
891                 // (b) its seas id matches the main request seas id
892                 Transaction mainTransaction = null;
893                 
894                 // get contained transaction ids
895                 Activity transactionIdActivity = mainRequest.getFirstActivity();
896                 java.util.List<Variant> transactionIds = new ArrayList<Variant>();
897                 ArrayList<String> transactionIdStrings = new ArrayList<String>(); // used for checking that transactions match
898                 Parameter transactionIdParameter = new Parameter(); // needed for constructing the response
899                 if (transactionIdActivity != null) {
900                          java.util.List<Input> inputs = transactionIdActivity.getInputs();
901                         for (Input ii : inputs) {
902                                 transactionIds = ii.get("transactions");
903                                 for (Variant v : transactionIds) {
904                                         transactionIdParameter.addValue(v);
905                                         transactionIdStrings.add(v.toString());
906                                 }
907                         }
908                 }
909                 // verify that transaction ids match the contained transactions
910                 // by going through all transactions and removing their ids from
911                 // transactionIdStrings; they should all be there and list should
912                 // be empty in the end
913                 for (Obj o : objects) {
914                         if (o instanceof Transaction) {
915                                 String transactionId = o.getIdentifierUri();
916                                 if (!transactionIdStrings.remove(transactionId)) {
917                                         // this transaction id was not in the request,
918                                         // so it could be the main transaction
919                                         Transaction t = (Transaction)o;
920                                         if (mainTransaction == null &&
921                                                         t.hasNotarizedObject() &&
922                                                         t.getNotarizedObject().hasIdentifierUri()) {
923                                         // transaction message id matches main request id, so this is indeed the main transaction
924                                         mainTransaction = (Transaction)o;
925                                         } else {
926                                                 // this isn't the main transaction but its id
927                                                 // cannot be found in the main request either
928                                                 System.out.println("Transaction id " + transactionId + " is missing from the main request");
929                                                 return;
930                                         }
931                                 }
932                         }
933                 }
934
935                 if (mainTransaction == null) {
936                         System.out.println("Main transaction not found in the request");
937                         return;
938                 }
939         
940                 // now all elements should have been removed from transactionIdStrings
941                 if (transactionIdStrings.size() > 0) {
942                         System.out.println("Main request contains " + transactionIds.size() + " unknown transaction ids");
943                         return;
944                 }
945
946 //              // verify signatures in the two main parts
947 //              try {
948 //                      // request (message) signature
949 //                      if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
950 //                              String messageSignature = mainTransaction.getNotarizedObject().getSignature();
951 //                              String messageHash = mainTransaction.getNotarizedObject().getHashCode();
952 //                              
953 //                              if (!TransactionAgent.verifyTransactionHash(messageHash, parts[mainRequestIndex])) {
954 //                                      // invalid request signature!
955 //                                      System.out.println("Main request hash verification failed!");
956 //                                      return;
957 //                              }
958 //                              if (!TransactionAgent.verifyTransactionSignature(messageSignature, pubKey, messageHash)) {
959 //                                      // invalid request signature!
960 //                                      System.out.println("Main request signature verification failed!");
961 //                                      return;
962 //                              } else {
963 //                                      System.out.println("Request signature verified");
964 //                              }
965 //                      } else {
966 //                              System.out.println("Message signature not found");
967 //                              return;
968 //                      }
969 //      
970 //                      // transaction signature
971 //                      if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
972 //                              String transactionSignature = mainTransaction.getNotarizedObject().getSignature();
973 //                              String transactionHash = mainTransaction.getNotarizedObject().getHashCode();
974 //                              
975 //                              if (!TransactionAgent.verifyTransactionSignature(transactionSignature, pubKey, transactionHash)) {
976 //                                      // invalid transaction signature!
977 //                                      System.out.println("Transaction signature verification failed!");
978 //                                      return;
979 //                              } else {
980 //                                      System.out.println("Transaction signature verified");
981 //                              }
982 //                      } else {
983 //                              System.out.println("Transaction signature not found");
984 //                              return;
985 //                      }
986 //              } catch (Exception e) {
987 //                      System.out.println("Exception caught when verifying signatures: " + e.getMessage());
988 //                      return;
989 //              }
990         }
991 //      
992 //      public void transactionVerificationTestRead()
993 //      {
994 //              String referenceId = "http://tests.b.c/ref";
995 //              String senderId = "http://tests.b.c/sender";
996 //              String myIdentity = senderId;
997 //              String contentHash = "ABCDHashEFGH";
998 //              PublicKey pubKey = null;
999 //              PrivateKey privKey = null;
1000 //              
1001 //              try {
1002 //                      pubKey = getPemPublicKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_public.pem", "RSA");
1003 //                      privKey = getPemPrivateKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_private.pem", "RSA");
1004 //              } catch (Exception ex) {
1005 //                      System.out.println("Could not find keys for the test.");
1006 //                      System.out.println(ex);
1007 //              }
1008 //              
1009 //              Base64.Encoder b64e = Base64.getEncoder();
1010 //              String notaryAddress = TransactionAgent.getDefaultNotary();
1011 //              String signature = Crypto.sign(privKey, contentHash);
1012 //              
1013 //              System.out.println("Content signature is: " + signature);
1014 //              System.out.println("Content hash is: " + contentHash);
1015 //              
1016 //              /* ---- SEND ---- */
1017 //              // Emulate send operation
1018 //              Transaction transaction = null;
1019 //              try {
1020 //                      transaction = Factory.createTransaction(referenceId, senderId);
1021 //              } catch ( Exception e ) {
1022 //                      e.printStackTrace();
1023 //                      return;
1024 //              }
1025 //              transaction.setSigner(senderId);
1026 //              Message message = new Message();
1027 //              message.setHashCode(contentHash);
1028 //              message.setSignature(signature);
1029 //              transaction.setNotarizedObject(message);
1030 //              
1031 //              HttpMessage sentHttpMessage = new HttpMessage();
1032 //              
1033 //              //main request
1034 //              Request r = null;
1035 //              try {
1036 //                      r = Factory.createRequest(myIdentity);
1037 //              } catch (Exception ex) {}
1038 //              r.setMethod(RESOURCE.READ);
1039 //              r.setId(1);
1040 //              Activity a = new Activity();
1041 //              r.addActivity(a);
1042 //
1043 //              Input i = new Input();
1044 //              a.addInput(i);
1045 //
1046 //              SystemOfInterest system = new SystemOfInterest();
1047 //              system.setSameAs(notaryAddress);
1048 //              i.setSystemOfInterest(system);
1049 //
1050 //              Parameter param = new Parameter();
1051 //              param.setKey("transactions");
1052 //              param.setName("Transaction id list");
1053 //              param.setDescription("List of ids of transactions that are sent to be fetched from the database.");
1054 //              param.addValue(new Variant(transaction.getIdentifierUri()));
1055 //              i.addParameter(param);
1056 //              
1057 //              String mainRequestString = Tools.toString(r);
1058 //              sentHttpMessage.add("Main", mainRequestString);
1059 //
1060 //              String mainRequestHash = Crypto.createEncodedMessageDigest(mainRequestString);
1061 //              String requestSignature = Crypto.sign(privKey, mainRequestHash);
1062 //              
1063 //              // create transaction for the main request
1064 //              String transactionIdentifierUri =  myIdentity + Crypto.generate16ByteCryptoRandomString();
1065 //              Transaction requestTransaction = null;
1066 //              try {
1067 //                      requestTransaction = Factory.createTransaction(transactionIdentifierUri, myIdentity);
1068 //              } catch ( Exception e ) {
1069 //                      e.printStackTrace();
1070 //                      return;
1071 //              }
1072 //              requestTransaction.setSigner(myIdentity);
1073 //              Message requestTransactionMessage = new Message();
1074 //              requestTransactionMessage.setId(r.getId());
1075 //              requestTransactionMessage.setHashCode(mainRequestHash);
1076 //              requestTransactionMessage.setSignature(requestSignature);
1077 //              requestTransaction.setNotarizedObject(requestTransactionMessage);
1078 //              
1079 //              String requestTransactionString = Tools.toString(requestTransaction);
1080 //              sentHttpMessage.add(transactionIdentifierUri, requestTransactionString);
1081 //
1082 //              // add transactions that are sent for reading
1083 //              sentHttpMessage.add(transaction.getIdentifierUri(), Tools.toString(transaction));
1084 //              
1085 //              String msg = sentHttpMessage.asString();
1086 //              System.out.println("Sending: \n" + msg + "\n------------------------ < message end > --------------");
1087 //              
1088 //              
1089 //              /* ---- RECEIVE ---- */
1090 //              
1091 //              // Emulate reception
1092 //              HttpMessage receivedMessage;
1093 //              try {
1094 //                      receivedMessage = HttpMessage.parse(msg, sentHttpMessage.getContentType());
1095 //              } catch (Exception e) {
1096 //                      System.out.println("Failed to parse incoming message body");
1097 //                      return;
1098 //              }
1099 //      
1100 //              if (receivedMessage.size() < 2) {
1101 //                      System.out.println("Request should have at least two parts");
1102 //                      return;
1103 //              }
1104 //
1105 //              // parse all request parts
1106 //              java.util.Map<String,MessagePart> partsMap = receivedMessage.getParts();
1107 //              Obj[] objects = new Obj[partsMap.size()];
1108 //              String[] parts = new String[partsMap.size()];
1109 //              int mainRequestIndex = -1;
1110 //              Request mainRequest = null;
1111 //              try {
1112 //                      int mi = 0;
1113 //                      for (String partId : partsMap.keySet()) {
1114 //                              MessagePart part = partsMap.get(partId);
1115 //                              objects[mi] = Tools.toObj(part.getBody());
1116 //                              parts[mi] = part.getBody();
1117 //                              if (objects[mi] == null) {
1118 //                                      System.out.println("No object returned when parsing the following part: " + parts[mi]);
1119 //                                      return;
1120 //                              }
1121 //              
1122 //                              if (partId.equals("Main")) {
1123 //                                      // main Request found
1124 //                                      if (objects[mi] instanceof Request) {
1125 //                                              mainRequest = (Request)objects[mi];
1126 //                                              mainRequestIndex = mi;
1127 //                                      } else {
1128 //                                              System.out.println("Main part should contain a Request object");
1129 //                                              return;
1130 //                                      }
1131 //                              }
1132 //              
1133 //                              mi++;
1134 //                      }
1135 //              } catch (Exception e) {
1136 //                      System.out.println("Exception caught when parsing objects: " + e.getMessage());
1137 //                      return;
1138 //              }
1139 //              if (mainRequest == null) {
1140 //                      System.out.println("No main Request found");
1141 //                      return;
1142 //              }
1143 //
1144 //              // now find the main transaction, which satisfies the following:
1145 //              // (a) its id is not listed in main request as a sub-transaction
1146 //              // (b) its seas id matches the main request seas id
1147 //              Transaction mainTransaction = null;
1148 //              
1149 //              // get contained transaction ids
1150 //              Activity transactionIdActivity = mainRequest.getFirstActivity();
1151 //              ArrayList<Variant> transactionIds = new ArrayList<Variant>();
1152 //              ArrayList<String> transactionIdStrings = new ArrayList<String>(); // used for checking that transactions match
1153 //              Parameter transactionIdParameter = new Parameter(); // needed for constructing the response
1154 //              if (transactionIdActivity != null) {
1155 //                      ArrayList<Input> inputs = transactionIdActivity.getInputs();
1156 //                      for (Input ii : inputs) {
1157 //                              transactionIds = ii.get("transactions");
1158 //                              for (Variant v : transactionIds) {
1159 //                                      transactionIdParameter.addValue(v);
1160 //                                      transactionIdStrings.add(v.toString());
1161 //                              }
1162 //                      }
1163 //              }
1164 //              // verify that transaction ids match the contained transactions
1165 //              // by going through all transactions and removing their ids from
1166 //              // transactionIdStrings; they should all be there and list should
1167 //              // be empty in the end
1168 //              for (Obj o : objects) {
1169 //                      if (o instanceof Transaction) {
1170 //                              String transactionId = o.getIdentifierUri();
1171 //                              if (!transactionIdStrings.remove(transactionId)) {
1172 //                                      // this transaction id was not in the request,
1173 //                                      // so it could be the main transaction
1174 //                                      Transaction t = (Transaction)o;
1175 //                                      if (mainTransaction == null &&
1176 //                                                      t.hasNotarizedObject()) {
1177 //                                      // transaction message id matches main request id, so this is indeed the main transaction
1178 //                                      mainTransaction = (Transaction)o;
1179 //                                      } else {
1180 //                                              // this isn't the main transaction but its id
1181 //                                              // cannot be found in the main request either
1182 //                                              System.out.println("Transaction id " + transactionId + " is missing from the main request");
1183 //                                              return;
1184 //                                      }
1185 //                              }
1186 //                      }
1187 //              }
1188 //
1189 //              if (mainTransaction == null) {
1190 //                      System.out.println("Main transaction not found in the request");
1191 //                      return;
1192 //              }
1193 //      
1194 //              // now all elements should have been removed from transactionIdStrings
1195 //              if (transactionIdStrings.size() > 0) {
1196 //                      System.out.println("Main request contains " + transactionIds.size() + " unknown transaction ids");
1197 //                      return;
1198 //              }
1199 //
1200 //              // verify signatures in the two main parts
1201 //              try {
1202 //                      // request (message) signature
1203 //                      if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
1204 //                              String messageSignature = mainTransaction.getNotarizedObject().getSignature();
1205 //                              String messageHash = mainTransaction.getNotarizedObject().getHashCode();
1206 //                              
1207 //                              if (!TransactionAgent.verifyTransactionHash(messageHash, parts[mainRequestIndex])) {
1208 //                                      // invalid request signature!
1209 //                                      System.out.println("Main request hash verification failed!");
1210 //                                      return;
1211 //                              }
1212 //                              if (!TransactionAgent.verifyTransactionSignature(messageSignature, pubKey, messageHash)) {
1213 //                                      // invalid request signature!
1214 //                                      System.out.println("Main request signature verification failed!");
1215 //                                      return;
1216 //                              } else {
1217 //                                      System.out.println("Request signature verified");
1218 //                              }
1219 //                      } else {
1220 //                              System.out.println("Message signature not found");
1221 //                              return;
1222 //                      }
1223 //      
1224 //                      // transaction signature
1225 //                      if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
1226 //                              String transactionSignature = mainTransaction.getNotarizedObject().getSignature();
1227 //                              String transactionHash = mainTransaction.getNotarizedObject().getHashCode();
1228 //                              
1229 //                              if (!TransactionAgent.verifyTransactionSignature(transactionSignature, pubKey, transactionHash)) {
1230 //                                      // invalid transaction signature!
1231 //                                      System.out.println("Transaction signature verification failed!");
1232 //                                      return;
1233 //                              } else {
1234 //                                      System.out.println("Transaction signature verified");
1235 //                              }
1236 //                      } else {
1237 //                              System.out.println("Transaction signature not found");
1238 //                              return;
1239 //                      }
1240 //              } catch (Exception e) {
1241 //                      System.out.println("Exception caught when verifying signatures: " + e.getMessage());
1242 //                      return;
1243 //              }
1244 //      }
1245         
1246         public void routingAndEnergyRegistrationTest()
1247         {
1248                 String serverIdentity = "http://seasexamples.asema.com/api/Ctestserver";
1249                 String serverName = "A sample charging plan calculation service";
1250                 
1251                 Service service = new Service(serverIdentity);
1252                 
1253                 // Service metadata
1254                 Organization owner = new Organization();
1255                 Address acmeAddress = new Address();
1256                 InterfaceAddress iface = new InterfaceAddress();
1257                 
1258                 iface.setHost("www.acme.com");
1259                 iface.setScheme("https");
1260                 iface.setPath("/seas/v1.0e1.0/access");
1261                 acmeAddress.setStreetAddress("Giant Rubber Band Street");
1262                 acmeAddress.setZipCode("12345");
1263                 acmeAddress.setCity("Fairfield, New Jersey");
1264                 owner.setName("Acme Industries");
1265                 owner.setAddress(acmeAddress);
1266                 
1267                 service.addInterface(iface);
1268                 service.addOwner(owner);
1269                 service.setName(serverName);
1270                 service.setDescription("A charging plan service that supplies the available energy for charging in timeslots at a charging point.");
1271                 service.addWebsite("http://www.acme.com/acmeoptimizers/roadrunner/beep/beep");
1272                 
1273                 
1274                 // API payload data
1275                 Activity a = new Activity();
1276                 Input i = new Input();
1277                 Output o = new Output();
1278                 a.addOutput(o);
1279                 a.addInput(i);
1280                 service.addCapability(a);
1281                 
1282                 // Input
1283                 Map charge_need = new Map();
1284                 charge_need.insert("Energy", Factory.createValueObject(NS.UNIT + "KilowattHour", "Total amount of energy requested to complete the charge."));
1285                 charge_need.insert("PowerMax", Factory.createValueObject(NS.UNIT + "Watt", "Maximum allowed instant power for charging the vehicle."));
1286                 charge_need.insert("PowerMin", Factory.createValueObject(NS.UNIT + "Watt", "Minumum allowed instant power for charging the vehicle."));
1287                 charge_need.insert("Priority", new Obj(DATATYPE.INTEGER));
1288                 charge_need.insert("Type", new Enumeration("Immediate", "Delayed"));
1289                 TemporalContext tci = new TemporalContext();
1290                 tci.setDescription("The desired schedule at which the charging should take place (start (optional) and end)");
1291                 charge_need.insert("Schedule", tci);
1292                 i.add("ChargingNeed", charge_need);
1293
1294                 // Output
1295                 Map charge_plan = new Map();
1296                 ArrayList<Map> orders = new ArrayList<Map>();
1297                 Map order = new Map();
1298                 TemporalContext tco = new TemporalContext();
1299                 tco.setDescription("The start and end times of this charging slot.");
1300                 order.insert("Schedule", tco);
1301                 order.insert("Power", Factory.createValueObject(NS.UNIT + "Watt", "The instant power supplied in this slot."));
1302                 orders.add(order);
1303                 charge_plan.insert("Orders", orders);
1304                 o.add("ChargingPlan", charge_plan);
1305         
1306                 
1307                 RegistrationAgent agent = new RegistrationAgent(serverIdentity);
1308                 String payload = agent.generateRegistrationMessage(service).toTurtle();
1309                 System.out.println(payload);
1310         }
1311         
1312         public void hugeDataTest(int itemSize)
1313         {
1314                 System.out.println("Running HugeDataTest (data size: " + itemSize + ")");
1315                 Date testStartTime = new Date();
1316
1317                 // create data
1318                 String myId = "http://seasdemos.asema.com/cplusplus/controlcommandsender/Cabcd";
1319
1320                 Date now = new Date();
1321                 Calendar calendar = Calendar.getInstance();
1322                 calendar.setTime(now);
1323
1324                 Response res = null;
1325                 try {
1326                         res = Factory.createResponse(myId);
1327                 } catch (Exception e) {
1328                         System.err.println("Exception while creating Response with ResponseFactory for " + myId + ".");
1329                         printTestTime(testStartTime, "Test interrupted in");
1330                         e.printStackTrace();
1331                 }
1332                 res.setSameAs("http://hugedata.test");
1333                 res.setName("Huge dataset test");
1334                 res.setIdentifierUri("http://huge.data.uri");
1335
1336                 for ( int i = 0; i < itemSize; i++ ) {
1337                         Evaluation ev = new Evaluation();
1338                         ev.setValue(new Variant(i));
1339                         ev.setInstant(calendar.getTime());
1340                         calendar.add(Calendar.DATE, 1);
1341                         res.add("http://evaluation.com", ev);   
1342                 }
1343                 printTestTime(testStartTime, "Time");
1344                 
1345                 // serialize
1346                 System.out.println("Serializing data...");
1347                 String stringData = Tools.toString(res, SERIALIZATION.TURTLE);
1348                 printTestTime(testStartTime, "Time");
1349                 
1350                 // parse back
1351                 System.out.println("Parsing back the serialized data...");
1352                 Model model = Tools.fromString(stringData, SERIALIZATION.TURTLE);
1353                 Resource resource = null;
1354                 try {
1355                         resource = Tools.getResourceByType(RESOURCE.RESPONSE, model);
1356                 } catch (Exception e) {
1357                         System.err.println("Exception while trying to get smartapi:Response resource from the model.");
1358                         printTestTime(testStartTime, "Test interrupted in");
1359                         e.printStackTrace();
1360                 }
1361                 
1362                 try {
1363                         Response resParsed = Obj.parse(Response.class, resource);
1364                         
1365                         // test if list items are still there
1366                         java.util.List<Variant> items = resParsed.get("http://evaluation.com");
1367                         if ( items.size() != 0 ) {
1368                                 if ( items.size() == itemSize ) {
1369                                         System.out.println("HugeDataTest (data size: " + itemSize + ") passed.");
1370                                         printTestTime(testStartTime, "Test executed in");
1371                                 } else {
1372                                         System.err.println("HugeDataTest (data size: " + itemSize + ") failed!");
1373                                         System.err.println("Size of serialized and parsed data is " + items.size() + ".");
1374                                         printTestTime(testStartTime, "Test executed in");
1375                                 }
1376                         } else {
1377                                 System.err.println("HugeDataTest (data size: " + itemSize + ") failed!");
1378                                 System.err.println("Size of serialized and parsed data is 0.");
1379                                 printTestTime(testStartTime, "Test executed in");
1380                         }
1381                 }
1382                 catch (NoSuchMethodException e) {}
1383                 catch (InvocationTargetException e) {}
1384         }
1385         
1386         public void fileInputTest(String fileName, String serialization)
1387         {
1388                 Obj o = Tools.fromFileAsObj(fileName, serialization);
1389                 serializeParse(o, true);
1390         }
1391         
1392         public void requestResponseTest1()
1393         {
1394                 String clientIdentity = "http://www.client.com/seas/Cclient";
1395                 String serverIdentity = "http://www.server.com/seas/Cserver";
1396
1397                 /*
1398                  * Test sequence 1, basic request / response
1399                  */
1400                 System.out.println("\n\nREQUEST/RESPONSE, TEST 1");
1401                 
1402                 // Send request
1403                 Request rc = null;
1404                 try {
1405                         rc = Factory.createRequest(clientIdentity);
1406                 } catch (Exception ex) {}
1407                 rc.setMethod(RESOURCE.READ);
1408                 Activity a = new Activity();
1409                 Input i = new Input();
1410                 a.addInput(i);
1411                 i.setSystemOfInterestWithSameAs("http://a.com/b");
1412                 rc.addActivity(a);
1413                         
1414                 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1415                 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1416                 
1417                 // Receive request
1418                 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1419                 String clientId = rs.getGeneratedBy().toString();
1420                 Activity aa = rs.getActivities().get(0);
1421                 Input ii = aa.getInputs().get(0);
1422                 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1423                 
1424                 // Send response
1425                 Response resp = null;
1426                 try {
1427                         resp = Factory.createResponse(serverIdentity);
1428                 } catch (Exception ex) {}
1429                 resp.setMethod(RESOURCE.READ);
1430                 Activity ars = new Activity();
1431                 Output ors = new Output();
1432                 ars.addOutput(ors);
1433                 ors.setSystemOfInterestWithSameAs("http://a.com/b");
1434                 resp.addActivity(ars);
1435                         
1436                 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1437                 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1438                 
1439                 // Receive response
1440                 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1441                 String serverId = respc.getGeneratedBy().toString();
1442                 Activity ac = respc.getActivities().get(0);
1443                 Output oc = ac.getOutputs().get(0);
1444                 System.out.println("Response, sys of interest " + oc.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + serverId);
1445         }
1446         
1447         public void requestResponseTest2()
1448         {
1449                 String clientIdentity = "http://www.client.com/seas/Cclient";
1450                 String serverIdentity = "http://www.server.com/seas/Cserver";
1451
1452                 /*
1453                  * Test sequence 2, request and response with an offer
1454                  */
1455                 System.out.println("\n\nREQUEST/RESPONSE, TEST 2");
1456                 
1457                 // Send request
1458                 Request rc = null;
1459                 try {
1460                         rc = Factory.createRequest(clientIdentity);
1461                 } catch (Exception ex) {}
1462                 rc.setMethod(RESOURCE.READ);
1463                 Activity a = new Activity();
1464                 Input i = new Input();
1465                 a.addInput(i);
1466                 i.setSystemOfInterestWithSameAs("http://a.com/b");
1467                 rc.addActivity(a);
1468                         
1469                 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1470                 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1471                 
1472                 // Receive request
1473                 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1474                 String clientId = rs.getGeneratedBy().toString();
1475                 Activity aa = rs.getActivities().get(0);
1476                 Input ii = aa.getInputs().get(0);
1477                 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1478                 
1479                 // Send response
1480                 Response resp = null;
1481                 try {
1482                         resp = Factory.createResponse(serverIdentity);
1483                 } catch (Exception ex) {}
1484                 resp.setMethod(RESOURCE.READ);
1485                 
1486                 Offering offering = new Offering("http://a.com/b#" + Crypto.generate16ByteCryptoRandomString(), "Test offer", "Test offer description");
1487                 offering.setBusinessFunction(RESOURCE.SELL);
1488                 
1489                 PriceSpecification priceSpecification = new UnitPriceSpecification();
1490                 priceSpecification.setCurrency("EUR");
1491                 priceSpecification.setCurrencyValue(123);
1492                 offering.addPriceSpecification(priceSpecification);
1493                 SomeItems items = new SomeItems(RESOURCE.REQUEST, "Service request", "Any kind of service request.", serverIdentity);
1494                 offering.addIncludes(items);
1495                 
1496                 aa.addOffering(offering);
1497                 resp.addActivity(aa);
1498                         
1499                 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1500                 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1501                 
1502                 // Receive response
1503                 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1504                 String serverId = respc.getGeneratedBy().toString();
1505                 Activity ac = respc.getActivities().get(0);
1506                 Offering oc = ac.getOfferings().get(0);
1507                 System.out.println("Response, offering at price " + oc.getPriceSpecification().get(0).getCurrencyValue());
1508         }
1509         
1510         public void requestResponseTest3()
1511         {
1512                 String clientIdentity = "http://www.client.com/seas/Cclient";
1513                 String serverIdentity = "http://www.server.com/seas/Cserver";
1514
1515                 SecretKey sessionKey = Crypto.generateSymmetricKey();
1516                 
1517                 /*
1518                  * Test sequence 3, request and response with encrypted data
1519                  */
1520                 System.out.println("\n\nREQUEST/RESPONSE, TEST 3");
1521                 
1522                 // Send request
1523                 Request rc = null;
1524                 try {
1525                         rc = Factory.createRequest(clientIdentity);
1526                 } catch (Exception ex) {}
1527                 rc.setMethod(RESOURCE.READ);
1528                 Activity a = new Activity();
1529                 Input i = new Input();
1530                 a.addInput(i);
1531                 i.setSystemOfInterestWithSameAs("http://a.com/b");
1532                 rc.addActivity(a);
1533                 
1534                 System.out.println("---------explain()-----");
1535                 rc.explain();
1536                 System.out.println("---------turtlePrint()----------");
1537                 rc.turtlePrint();
1538                 System.out.println("-------------------");
1539                 
1540                 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1541                 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1542                 System.out.println("Request Content-Type:  " + serializedRequest.getRight());
1543                 
1544                 // Receive request
1545                 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1546                 String clientId = rs.getGeneratedBy();
1547                 Activity aa = rs.getActivities().get(0);
1548                 Input ii = aa.getInputs().get(0);
1549                 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1550                 
1551                 // Send response
1552                 Response resp = null;
1553                 try {
1554                         resp = Factory.createResponse(serverIdentity);
1555                 } catch (Exception ex) {}
1556                 resp.setMethod(RESOURCE.READ);
1557                 Activity ars = new Activity();
1558                 Output ors = new Output();
1559                 ars.addOutput(ors);
1560                 ors.setSystemOfInterestWithSameAs("http://a.com/b");
1561                 ors.encrypt(sessionKey);
1562                 resp.addActivity(ars);
1563                                                 
1564                 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1565                 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1566                 System.out.println("Reponse Content-Type:  " + serializedResponse.getRight());
1567                 
1568                 // Receive response
1569                 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1570                 String serverId = respc.getGeneratedBy();
1571                 Activity ac = respc.getActivities().get(0);
1572                 Output oc = ac.getOutputs().get(0);
1573                 oc.decrypt(sessionKey);
1574                 System.out.println("Response, sys of interest " + oc.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + serverId);
1575         }
1576         
1577         public void requestResponseTest4()
1578         {
1579                 String clientIdentity = "http://www.client.com/seas/Cclient";
1580                 String serverIdentity = "http://www.server.com/seas/Cserver";
1581
1582                 PublicKey pubKey = null;
1583                 PrivateKey privKey = null;
1584                 
1585                                 
1586                 try {
1587                         pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1588                         privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1589                 } catch (Exception ex) {
1590                         System.out.println("Could not find keys for the test.");
1591                         System.out.println(ex);
1592                 }
1593                 
1594                 /*
1595                  * Test sequence 4, request and response with signed data
1596                  */
1597                 System.out.println("\n\nREQUEST/RESPONSE, TEST 4");
1598                 
1599                 // Send request
1600                 Request rc = null;
1601                 try {
1602                         rc = Factory.createRequest(clientIdentity);
1603                 } catch (Exception ex) {}
1604                 rc.setMethod(RESOURCE.READ);
1605                 Activity a = new Activity();
1606                 Input i = new Input();
1607                 a.addInput(i);
1608                 i.setSystemOfInterestWithSameAs("http://a.com/b");
1609                 rc.addActivity(a);
1610                 
1611                 rc.sign(privKey);
1612                         
1613                 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1614                 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1615                 
1616                 // Receive request
1617                 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1618                 
1619                 rs.turtlePrint();
1620                 String clientId = rs.getGeneratedBy();
1621                 System.out.println("after parsing, we get GeneratedBy: "+ clientId);
1622                 Activity aa = rs.getActivities().get(0);
1623                 Input ii = aa.getInputs().get(0);
1624                 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1625                 
1626                 // Send response
1627                 Response resp = null;
1628                 try {
1629                         resp = Factory.createResponse(serverIdentity);
1630                 } catch (Exception ex) {}
1631                 resp.setMethod(RESOURCE.READ);
1632                 Activity ars = new Activity();
1633                 Output ors = new Output();
1634                 ars.addOutput(ors);
1635                 ors.setSystemOfInterestWithSameAs("http://a.com/b");
1636                 ors.sign(privKey);
1637                 resp.addActivity(ars);
1638                 
1639                 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1640                 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1641                 
1642                 // Receive response
1643                 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1644                 String serverId = respc.getGeneratedBy();
1645                 Activity ac = respc.getActivities().get(0);
1646                 Output oc = ac.getOutputs().get(0);
1647                 boolean verified = false;
1648                 try {
1649                         verified = oc.verifySignature(pubKey);
1650                 } catch (Exception e) {}
1651                 System.out.println("Signature verification " + (verified ? "successful" : "failed") );
1652                 System.out.println("Response, sys of interest " + oc.getSystemOfInterest()+ " from " + serverId);
1653         }
1654         
1655         void notaryKeyStoreTest()
1656         {
1657                 String myId = "http://seas.test.asema.com/notarykeytest";
1658                 String referenceId = "http://seas.test.asema.com/notarykeytest/ref1" + Crypto.generate16ByteCryptoRandomString();
1659                 String 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.";
1660                 // to make the content different during each run, otherwise test will fail
1661                 content = content + Crypto.generate16ByteCryptoRandomString();
1662                 
1663                 PublicKey pubKey = null;
1664                 PrivateKey privKey = null;
1665                 try {
1666                         pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1667                         privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1668                 } catch (Exception ex) {
1669                         System.out.println("Could not find keys for the test.");
1670                         System.out.println(ex);
1671                 }
1672                 CryptoKeyWallet.setPublicKey(pubKey);
1673                 CryptoKeyWallet.setPrivateKey(privKey);
1674                 
1675                 Base64.Encoder b64e = Base64.getEncoder();
1676                 String notary = TransactionAgent.getDefaultNotary();
1677                 SecretKey key = Crypto.generateSymmetricKey();
1678                 String sessionKeySent = new String(b64e.encode(key.getEncoded()));
1679                 String contentHash = Crypto.createEncodedMessageDigest(content);
1680                 String signature = Crypto.sign(privKey, content);
1681                 boolean sentOK = TransactionAgent.sendKeyToNotary(myId, referenceId, contentHash, sessionKeySent, signature, notary, privKey) != null;
1682                 String sessionKeyReceived = TransactionAgent.fetchKeyFromNotary(myId, referenceId, contentHash, signature, notary, privKey);
1683                 
1684                 System.out.println("Sent ok: " + sentOK);
1685                 System.out.println("Sent key: " + sessionKeySent);
1686                 System.out.println("Received key: " + sessionKeyReceived);
1687                 System.out.println("Keys match?: " + sessionKeyReceived.equals(sessionKeySent));
1688         }
1689
1690         void keyServerTest()
1691         {
1692                 String 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.";
1693                 String keyId = "http://www.acme.com/services/abcd/";
1694                 String publicKeyServer = "http://127.0.0.1:11371";
1695                 PublicKey downloadedKey = Crypto.downloadPublicKey(keyId, publicKeyServer);
1696                 PublicKey pubKey = null;
1697                 PrivateKey privKey = null;
1698                 try {
1699                         pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1700                         privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1701                 } catch (Exception ex) {
1702                         System.out.println("Could not find keys for the test.");
1703                         System.out.println(ex);
1704                 }
1705                 
1706                 String signature = Crypto.sign(privKey, content);
1707                 boolean verified = false;
1708                 try {
1709                         verified = Crypto.verifySignature(signature, pubKey, content);
1710                 } catch (Exception e) {}
1711                 System.out.println("Signature verification, key on disk " + (verified ? "successful" : "failed") );
1712                 
1713                 try {
1714                         verified = Crypto.verifySignature(signature, downloadedKey, content);
1715                 } catch (Exception e) {
1716                         verified = false;
1717                 }
1718                 System.out.println("Signature verification, downloaded key " + (verified ? "successful" : "failed") );
1719         }
1720         
1721         public boolean keyHandlingTest()
1722         {
1723                 System.out.println("Running keyHandlingTest..");
1724                 try {
1725                         ImmutablePair<String,String> keyPair = Tools.createCryptoKeys();
1726                         System.out.println("public key: \n" + keyPair.getRight());
1727                         System.out.println("private key: \n" + keyPair.getLeft());  
1728                         Tools.uploadPublicKey(keyPair.getRight(), "http://demo.smart-api.io/testkey", "test", "test", "http://127.0.0.1:11371");
1729                         Tools.revokePublicKey("http://demo.smart-api.io/testkey", "test", "test", "http://127.0.0.1:11371");                    
1730                 } catch ( Exception e ) {
1731                         System.out.println("KeyHandlingTest failed.");
1732                         e.printStackTrace();
1733                         return false;
1734                 }
1735                 System.out.println("KeyHandlingTest passed.");
1736                 return true;
1737         }
1738         
1739         
1740         void simpleHashTest()
1741         {
1742                 Base64.Decoder b64d = Base64.getDecoder();
1743                 String r = "Simple hash input";
1744                 String responseHash = Crypto.createEncodedMessageDigest(r);
1745                 System.out.println("Hash for the text: " + responseHash);
1746         }
1747         
1748         public void printTestTime(Date testStartTime, String text) {
1749                 Date testEndTime = new Date();
1750                 long testDuration = testEndTime.getTime() - testStartTime.getTime();
1751                 long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(testDuration);
1752                 long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(testDuration);
1753                 long diffInHours = TimeUnit.MILLISECONDS.toHours(testDuration);
1754                 if ( diffInSeconds != 0 ) {
1755                         testDuration = testDuration - diffInSeconds*1000;
1756                 }
1757                 if ( diffInMinutes != 0 ) {
1758                         diffInSeconds = diffInSeconds - diffInMinutes*60;
1759                 }
1760                 if ( diffInHours != 0 ) {
1761                         diffInMinutes = diffInMinutes - diffInHours*60;
1762                 }
1763                 System.out.println("\n" + text + ": " + (diffInHours != 0 ? (diffInHours + "h ") : "") + 
1764                                 (diffInMinutes != 0 ? (diffInMinutes + "m ") : "") +
1765                                 (diffInSeconds != 0 ? (diffInSeconds + "s ") : "") +
1766                                 (testDuration != 0 ? (testDuration + "ms ") : "") + "\n");
1767         }
1768         
1769         private void serializeReserialize(Obj o)
1770         {
1771                 Obj o_parsed = serializeParse(o, true);
1772                 String reserialized = Tools.toString(o_parsed, SERIALIZATION.TURTLE);
1773                 
1774                 System.out.println("----");
1775                 System.out.println("Re-serialized: " + reserialized);
1776         }
1777         
1778         private Obj serializeParse(Obj o, boolean doPrint)
1779         {
1780                 String serialized = Tools.toString(o, SERIALIZATION.TURTLE);
1781                 if (doPrint) System.out.println("Serialized: " + serialized);
1782                 return Tools.fromStringAsObj(serialized, SERIALIZATION.TURTLE);
1783         }
1784         
1785         /**
1786          * 1. Registers boiler device with an Offering for controlling its power.
1787          * 2. Shares boiler by creating Availability and using SharingAgent.
1788          * 3. Searches for available devices that can be controlled with reasonable price.
1789          * 4. Removes sharing.
1790          * 5. Searches again to confirm sharing removal.
1791          */
1792         public boolean availabilityTest()
1793         {
1794                 System.out.println("Running TestSequence.testAvailability()");
1795
1796                 boolean testFailed = false;
1797                 
1798                 // identifiers
1799                 String myIdentity = "http://acme.com/boiler/C756fdg76dgfh4376dshg";
1800                 String powerIdentifier = "/Cpower";
1801                 String volumeIdentifier = "/Cvolume";
1802                 String offeringIdentifier = "/Coffering";
1803                 
1804                 // create boiler
1805                 Device boiler = new Device(myIdentity);
1806                 boiler.addType(RESOURCE.WATERBOILER);
1807                 
1808                 // info about energy consumption (power capacity)
1809                 Capacity power = new Capacity(myIdentity + powerIdentifier);
1810                 power.setSystemOfInterestWithType(RESOURCE.RESISTOR);
1811                 power.setQuantity(RESOURCE.POWER);
1812                 power.setUnit(RESOURCE.KILOWATT);
1813                 power.setMaximum(new Variant(6));
1814                 power.setStep(new Variant(3));
1815                 power.setValue(new Variant(6));
1816                 boiler.addCapacity(power);
1817                 
1818                 // info about water volume (volume capacity)
1819                 Capacity volume = new Capacity(myIdentity + volumeIdentifier);
1820                 volume.setSystemOfInterestWithType(RESOURCE.WATERTANK);
1821                 volume.setQuantity(RESOURCE.VOLUME);
1822                 volume.setUnit(RESOURCE.LITER);
1823                 volume.setMaximum(new Variant(500));
1824                 volume.setValue(new Variant(500));
1825                 boiler.addCapacity(volume);
1826                 
1827                 // price for controlling on/off of this device
1828                 Offering offering = new Offering(myIdentity + offeringIdentifier);
1829                 boiler.addOffering(offering);
1830                 PriceSpecification priceSpecification = new UnitPriceSpecification();
1831                 priceSpecification.setGrName("Price to control this boiler");
1832                 priceSpecification.setGrDescription("The amount in Euro to be paid for being able to control the two 3 kW resistors of this boiler for one hour.");
1833                 priceSpecification.setCurrency("EUR");
1834                 priceSpecification.setCurrencyValue(1.5);
1835                 offering.addPriceSpecification(priceSpecification);             
1836                 SomeItems items = new SomeItems(RESOURCE.SERVICESUBSCRIPTION, "Service subscription", "Right to control this device for one hour.", null);
1837                 items.setDuration(0, 0, 0, 1, 0, 0); // one hour
1838                 offering.addIncludes(items);
1839
1840                 // activity for controlling this device
1841                 Activity activity = new Activity();
1842                 boiler.addCapability(activity);
1843                 Input input = new Input();
1844                 activity.addInput(input);
1845                 input.addEntity(new Entity());
1846                 Output output = new Output();
1847                 activity.addOutput(output);
1848                 output.addEntity(new Entity());
1849                 
1850                 // register boiler description (including offering)
1851                 RegistrationAgent registrationAgent = new RegistrationAgent(myIdentity);
1852                 registrationAgent.addEntity(boiler);
1853                 Response response = registrationAgent.registrate();
1854                 // print out possible errors on the response
1855                 Tools.printErrors(response);
1856                 // get response status
1857                 if ( response.hasStatus() ) {
1858                         Status status = response.getStatus();
1859                         // check if the operation was successful
1860                         if ( status.hasType(RESOURCE.ERROR) ) {
1861                                 System.out.println(" ..Registration failed.");
1862                                 testFailed = true;
1863                         } else {
1864                                 System.out.println(" ..Registration successful. ");
1865                         }
1866                 } else {
1867                         System.out.println(" ..No status found in response. Registration probably failed.");
1868                 }
1869                 
1870                 // create availability of the control of this boiler
1871                 Availability availability = new Availability();
1872                 // available from now on for two weeks
1873                 Date now = new Date();
1874                 availability.addAvailability(now, Tools.add(now, 0, 0, 14, 0, 0, 0));
1875                 // available local time from 8 am to 4 pm and 1 am to 4 am (local time) on weekdays
1876                 availability.addAvailability(Factory.createTimeFromLocalTimeString("08:00:00"), Factory.createTimeFromLocalTimeString("16:00:00"), RESOURCE.WEEKDAY);
1877                 availability.addAvailability(Factory.createTimeFromLocalTimeString("01:00:00"), Factory.createTimeFromLocalTimeString("04:00:00"), RESOURCE.WEEKDAY);
1878                 // available local time from 1 am to 9 am (local time) on weekends
1879                 availability.addAvailability(Factory.createTimeFromLocalTimeString("01:00:00"), Factory.createTimeFromLocalTimeString("09:00:00"), RESOURCE.WEEKEND);
1880                 // available in Finland
1881                 availability.addAvailability(new Address("Finland", null, null, null));
1882
1883                 // share boiler with defined availability
1884                 SharingAgent sharingAgent = new SharingAgent(myIdentity);
1885                 /**
1886                  *  add authentication information
1887                  */
1888                 String username = "senni";
1889                 String password = "12345";
1890                 
1891                 // for now using HTTP basic authentication, i.e., using username:password combination.             
1892                 sharingAgent.setHTTPBasicAccessAuthenticationCredentials(username, password);
1893                 
1894                 
1895                 boolean addAvailabilitySuccessful = sharingAgent.share(myIdentity, availability) != null;
1896                 if ( !addAvailabilitySuccessful ) {
1897                         System.out.println(" ..Adding availability failed.");
1898                         testFailed = true;
1899                 } else {
1900                         System.out.println(" ..Adding availability successful. ");
1901                 }
1902                 
1903                 // search for available devices with power capacity..
1904                 Entity entity = new Device();
1905                 Capacity capacity = new Capacity();
1906                 capacity.setQuantity(RESOURCE.POWER);
1907                 entity.addCapacity(capacity);
1908                 
1909                 // ..that are available for control from now on for at least 3 hours..
1910                 Availability av = new Availability();
1911                 Date currentDateTime = new Date();
1912                 av.setTemporalContext(currentDateTime, Tools.add(currentDateTime, 0, 0, 0, 3, 0, 0));
1913                 
1914                 // ..with maximum price of 1.8 euros per hour
1915                 Offering offer = new Offering();
1916                 PriceSpecification ps = new UnitPriceSpecification();
1917                 ps.setCurrency("EUR");
1918                 ps.setCurrencyValue(1.8);
1919                 offer.addPriceSpecification(ps);
1920                 SomeItems si = new SomeItems(RESOURCE.SERVICESUBSCRIPTION, null, null, null);
1921                 si.setDuration(0, 0, 0, 1, 0, 0);
1922                 offer.addIncludes(si);
1923                 
1924 //              SharingAgent searchAgent = new SharingAgent("http://acme.com/test/searcher");
1925 //              boolean foundBoiler = false;
1926 //              java.util.List<Entity> found = searchAgent.search(entity, av, offer);
1927 //              for ( Entity e : found ) {
1928 //                      if ( boiler.getIdentifierUri().equals(e.getIdentifierUri()) ) {
1929 //                              foundBoiler = true;
1930 //                      }
1931 //              }
1932 //              if ( !foundBoiler ) {
1933 //                      System.out.println(" ..Error: could not find boiler using sharing agent!");
1934 //                      testFailed = true;
1935 //              } else {
1936 //            System.out.println(" ..Searching shared entity successful. ");            
1937 //        }
1938 //
1939 //        // remove sharing
1940 //        boolean deregistrationSuccessful = sharingAgent.removeSharing(myIdentity);
1941 //        if ( !deregistrationSuccessful ) {
1942 //            System.out.println(" ..Removing availability failed.");                                
1943 //        } else {
1944 //            System.out.println(" ..Removing sharing successful. ");                           
1945 //        }
1946 //        
1947 //        // search again for available devices to make sure it is not found anymore
1948 //              foundBoiler = false;
1949 //              found = searchAgent.search(entity, av, offer);
1950 //              for ( Entity e : found ) {
1951 //                      if ( boiler.getIdentifierUri().equals(e.getIdentifierUri()) ) {
1952 //                              foundBoiler = true;
1953 //                      }
1954 //              }
1955 //              if ( foundBoiler ) {
1956 //                      System.out.println(" ..Error: found boiler even though its sharing should be removed!");
1957 //                      testFailed = true;
1958 //              } else {
1959 //            System.out.println(" ..Confirmed removing sharing successful. ");                 
1960 //              }
1961 //              
1962 //              if ( testFailed ) {
1963 //                      System.out.println("TestSequence.testAvailability() FAILED");
1964 //                      return false;
1965 //              } else {
1966 //                      System.out.println("TestSequence.testAvailability() passed");
1967 //                      return true;
1968 //              }
1969                 return false;
1970         }
1971         
1972         public void simpleSignatureVerificationTest() 
1973         {
1974                 String signature = "r6mUVMZyGD//o7zFAttovTQwDxD3Wx/uvmDfTZTJQ2MZt9iQYaBHRMbFS4eY3O3erwf12T1v5KJR+CbbPyFvjNReoGVn6TUWNxe7mYf0Oqp38qxFnGDH2c/7wP/G1gqbAu3QConw2be7jCdWNV+YTaf28w4zB5S5O6Ig3J8OwAZdbTWjYMpWOtYzcZa4wPwDSO/QZ948mKEHSIOXcGqt1GZxn3cmFkwfkASr0hT//Y1PRZKUamZpXhViZZLeE0TfwhRhKcMyOzYk5Ht2kZKaKKETEZ4aMf6wKF6bMwG/ud70Z5X8DVBZ3uS7b8+kND3oYhQvAl/ayWSWaNvi18e4pA==";
1975                 
1976                 String 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.";
1977                 
1978                 PublicKey pubKey = null;
1979                 PrivateKey privKey = null;
1980                 try {
1981                         pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1982                         privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1983                 } catch (Exception ex) {
1984                         System.out.println("Could not find keys for the test.");
1985                         System.out.println(ex);
1986                 }
1987                 
1988                 String refSignature = Crypto.sign(privKey, content);
1989                 System.out.println("Reference signature: " + refSignature);
1990                 System.out.println("Received signature:  " + signature);
1991                 
1992                 boolean signedProperly = false;
1993                 try {
1994                         signedProperly = Crypto.verifySignature(signature, pubKey, content);
1995                 } catch (Exception e) {}
1996                 System.out.println("Signature test result: " + signedProperly);
1997         }
1998
1999         public void printLists()
2000         {
2001                 Calendar calendar = Calendar.getInstance();
2002                 calendar.setTime(new Date());
2003
2004                 TimeSeries ts = new TimeSeries();
2005
2006                 // orderedlist
2007                 smartapi.rdf.List testList = new OrderedList();              
2008                 for ( int i = 0; i < 3; i++ ) {
2009                         Evaluation e = new Evaluation();
2010                         e.setValue(new Variant(i));
2011                         e.setInstant(calendar.getTime());
2012                         calendar.add(Calendar.DATE, 1);
2013                         testList.addItems(e);
2014                 }
2015                 ts.setList(testList);  
2016                 System.out.println("\n-------- orderedlist! -----------\n");
2017                 ts.turtlePrint();
2018                 
2019                 testList = new OrderedList();           
2020                 for ( int i = 0; i < 3; i++ ) {
2021                         testList.addItems(i);
2022                 }
2023                 ts.setList(testList);   
2024                 Evaluation baseObject = new Evaluation();
2025                 baseObject.setQuantity(RESOURCE.ENERGYANDWORK);
2026                 baseObject.setUnit(RESOURCE.KILOWATTHOUR);
2027                 ts.setBaseObject(baseObject);
2028                 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2029                 ts.setTimeStep("PT1S");
2030                 ts.turtlePrint();
2031                 
2032                 // linkedlist
2033                 testList = new LinkedList();            
2034                 for ( int i = 0; i < 3; i++ ) {
2035                         Evaluation e = new Evaluation();
2036                         e.setValue(new Variant(i));
2037                         e.setInstant(calendar.getTime());
2038                         calendar.add(Calendar.DATE, 1);
2039                         testList.addItems(e);
2040                 }
2041                 ts.setList(testList);    
2042                 System.out.println("\n-------- linkedlist! -----------\n");
2043                 ts.turtlePrint();
2044                 
2045                 testList = new LinkedList();            
2046                 for ( int i = 0; i < 3; i++ ) {
2047                         testList.addItems(i);
2048                 }
2049                 ts.setList(testList);           
2050                 ts.setBaseObject(baseObject);
2051                 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2052                 ts.setTimeStep("PT1S");
2053                 System.out.println("\n--------also linkedlist! -----------\n");
2054                 ts.turtlePrint();
2055                 
2056                 
2057                 // nudelist
2058                 testList = new NudeList();
2059                 for ( int i = 0; i < 3; i++ ) {
2060                         Evaluation e = new Evaluation();
2061                         e.setValue(new Variant(i));
2062                         e.setInstant(calendar.getTime());
2063                         calendar.add(Calendar.DATE, 1);
2064                         testList.addItems(e);
2065                 }
2066                 ts.setList(testList);
2067                 System.out.println("\n-------- nudelist! -----------\n");
2068                 ts.turtlePrint();
2069
2070                 testList = new NudeList();
2071                 for ( int i = 0; i < 3; i++ ) {
2072                         testList.addItems(i);
2073                 }
2074                 ts.setList(testList);
2075                 ts.setBaseObject(baseObject);
2076                 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2077                 ts.setTimeStep("PT1S");
2078                 ts.turtlePrint();
2079                 
2080                 // itemedlist
2081                 testList = new ItemizedList();
2082                 for ( int i = 0; i < 3; i++ ) {
2083                         Evaluation e = new Evaluation();
2084                         e.setValue(new Variant(i));
2085                         e.setInstant(calendar.getTime());
2086                         calendar.add(Calendar.DATE, 1);
2087                         testList.addItems(e);
2088                 }
2089                 ts.setList(testList);
2090                 System.out.println("\n-------- itemizedlist! -----------\n");
2091                 ts.turtlePrint();
2092
2093                 testList = new ItemizedList();
2094                 for ( int i = 0; i < 3; i++ ) {
2095                         testList.addItems(i);
2096                 }
2097                 ts.setList(testList);
2098                 ts.setBaseObject(baseObject);
2099                 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2100                 ts.setTimeStep("PT1S");
2101                 ts.turtlePrint();
2102         }
2103         
2104         /**
2105          * Testing serialization and parsing of cross-linked objects
2106          * @return
2107          */
2108         public boolean serializeParseLoopTest()
2109         {
2110                 System.out.println("Running serializeParseLoopTest..");
2111                 String rootId = "http://serializeParseLoopTest.test/root";
2112                 String requestId = "http://serializeParseLoopTest.test/request";
2113                 String entityId = "http://serializeParseLoopTest.test/entity";
2114                 String rootProp = NS.SMARTAPI + "testPropertyRoot";
2115                 String loopProp = NS.SMARTAPI + "testPropertyLoop";
2116                 String selfRefProp = NS.SMARTAPI + "testPropertySelfRef";
2117                 try {
2118                         Entity root = new Entity(rootId);
2119                         Request r = new Request(requestId);
2120                         Entity e = new Entity(entityId);
2121                         root.add(rootProp, r);
2122                         // make loop
2123                         r.newActivity().addEntity(e);
2124                         e.add(loopProp, r);
2125                         // also make one link to self
2126                         e.add(selfRefProp, e);
2127                         // serialize
2128                         String rdf = Tools.toString(root);
2129                         System.out.println("serialization successful");
2130                         // debug print
2131                         System.out.println(rdf);
2132                         // parse back
2133                         Entity parsedRoot = (Entity)Tools.toObj(rdf);
2134                         System.out.println("parsing successful");
2135                         // debug print
2136                         System.out.println(Tools.toString(parsedRoot));
2137                         // test if content is still valid
2138                         Request r2 = parsedRoot.getFirstAs(Request.class, rootProp);
2139                         Entity e2 = r2.getFirstActivity().getEntities().get(0);
2140                         if ( !(r2.getIdentifierUri().equals(e2.getFirstAs(Obj.class, loopProp).getIdentifierUri())) ) {
2141                                 System.out.println("serializeParseLoopTest FAILED!");
2142                                 return false;
2143                         }
2144                         if ( !(e2.getIdentifierUri().equals(e2.getFirstAs(Obj.class, selfRefProp).getIdentifierUri())) ) {
2145                                 System.out.println("serializeParseLoopTest FAILED!");
2146                                 return false;
2147                         }
2148                         System.out.println("content check successful");
2149                 } catch ( Exception e ) {
2150                         System.out.println("serializeParseLoopTest FAILED!");
2151                         e.printStackTrace();
2152                         return false;
2153                 }
2154                 System.out.println("serializeParseLoopTest passed");
2155                 return true;
2156         }
2157         
2158         public boolean identifierManagementTest()
2159         {
2160                 System.out.println("Running identifierManagementTest..");
2161                 String domain = "asema.com";
2162                 String systemId = "iotc/123";
2163                 String objId = "/obj%567&/>qwerty/";
2164                 
2165                 try {
2166                         Entity e = new Entity(Tools.createIdentifierUri(domain, systemId, objId));
2167                         System.out.println("identifier creation successful");
2168                         e.turtlePrint();
2169                         String domain2 = e.getDomain();
2170                         String systemId2 = e.getSystemIdentifier();
2171                         String objId2 = e.getObjectIdentifier();
2172                         String secondObjetcId = e.getObjectIdentifier(2);
2173                         System.out.println("domain: " + domain2);
2174                         System.out.println("systemId: " + systemId2);
2175                         System.out.println("objectId: " + objId2);
2176                         System.out.println("secondObjetcId: " + secondObjetcId);
2177                         System.out.println("identifier partition successful");
2178                         if ( domain.equals(domain2) ) {
2179                                 System.out.println("domain correct");
2180                         } else {
2181                                 System.err.println("domain match FAILED!");
2182                                 return false;
2183                         }
2184                         if ( systemId.equals(systemId2) ) {
2185                                 System.out.println("systemId correct");
2186                         } else {
2187                                 System.err.println("systemId match FAILED!");
2188                                 return false;
2189                         }
2190                         if ( objId.equals(objId2) ) {
2191                                 System.out.println("objId correct");
2192                         } else {
2193                                 System.err.println("objId match FAILED!");
2194                                 return false;
2195                         }
2196                         if ( secondObjetcId == null ) {
2197                                 System.out.println("secondObjetcId correct");
2198                         } else {
2199                                 System.err.println("secondObjetcId match FAILED!");
2200                                 return false;
2201                         }
2202                 } catch ( Exception e ) {
2203                         e.printStackTrace();
2204                 }
2205                 System.out.println("identifierManagementTest passed");
2206                 return true;
2207         }
2208         
2209         public void readAndWriteObjectTest()
2210         {
2211                 System.out.println("Running readAndWriteObjectTest..");
2212                 String domain = "asema.com";
2213                 String systemId = "iotc123";
2214                 String objId = "lamp";
2215                 try {
2216                         Device d = new Device(Tools.createIdentifierUri(domain, systemId, objId));
2217
2218                         InterfaceAddress itf = Factory.createInterface("http://asema.com:8082/smartapi/v1.0e1.0/access/nonstandard");
2219
2220                         ValueObject vo = new ValueObject(NS.SMARTAPI + "Brightness", RESOURCE.PERCENT, null, null, "smartapi:Actuator", "smartapi:Dimmer");
2221                         d.addValueObject(vo);
2222
2223                         ValueObject vo2 = new ValueObject(NS.SMARTAPI + "Powered", DATATYPE.BOOLEAN, null, null, "smartapi:Actuator", "smartapi:PowerSwitch");
2224                         d.addValueObject(vo2);
2225
2226                         ValueObject vo3 = new ValueObject(null, null, DATATYPE.STRING, "String message shown on lamp screen, use the lamp keyboard to change the message", "smartapi:Sensor");
2227                         d.addValueObject(vo3);
2228
2229                         Activity aRead = Factory.createStandardReadActivity(itf, vo, vo2, vo3);
2230                         d.addCapability(aRead);
2231                         Activity aReadts = Factory.createStandardReadTimeSeriesActivity(itf, vo, vo2);
2232                         d.addCapability(aReadts);
2233                         Activity aWrite = Factory.createStandardWriteActivity(itf, vo, vo2);
2234                         d.addCapability(aWrite);
2235                         Activity aWritets = Factory.createStandardWriteTimeSeriesActivity(itf, vo);
2236                         d.addCapability(aWritets);
2237                         
2238                         
2239                         // debug print device description
2240                         d.turtlePrint();
2241                         
2242                         HttpClient client = new HttpClient();
2243                         // enable debug mode to see printout of uri and request body
2244                         client.debugMode(true);
2245                         // just some random temporal context
2246                         TemporalContext tcx = new TemporalContext(Tools.add(new Date(), 0, 0, 0, -6, 0, 0), new Date());
2247
2248                         // test call to read whole lamp device object
2249                         client.getObject(d);
2250                         // test call to read brightness value object time series data
2251                         client.getValueObject(d, tcx, d.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness"), d.getFirstValueObjectByQuantity((NS.SMARTAPI + "PowerOnState")));
2252                         // test call to write time series data to lamp
2253                         client.setObject(d, new TimeSeries());
2254                         // test call to write brightness value
2255                         d.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").setValue(80);
2256                         client.setValueObject(d, d.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness"));
2257
2258                 } catch ( Exception e ) {
2259                         System.err.println("Exception in readAndWriteObjectTest. It is normal if it is caused by network problem because there is no server to actually respond for these requests.");
2260                         e.printStackTrace();
2261                 }
2262         }
2263         
2264         /**
2265          * See values changing by reloading page on browser:
2266          * http://seas.asema.com/webapps/SimpleRW/API/smartapi/v1.0e1.0/access
2267          * @return
2268          */
2269         public boolean standardRWtest()
2270         {
2271                 System.out.println("Running standard RW test against SimpleRW servlet...");
2272
2273                 // search for SimpleRW device, should find one
2274                 for ( Entity e : SearchAgent.searchByNameAndType(SmartAPI.getMyIdentity(), 500, new String[]{"SimpleRW"}, new String[]{RESOURCE.DEVICE}) ) {
2275
2276                         // debug print
2277                         e.turtlePrint();
2278                         
2279                         ValueObject brightness = e.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness");
2280                         ValueObject powerOnState = e.getFirstValueObjectByQuantity(NS.SMARTAPI + "Powered");
2281                         HttpClient client = new HttpClient();
2282                         // enable debug mode to see printout of uri and request body
2283                         //client.debugMode(true);
2284                         int brightnessValue = 0;
2285                         boolean powerValue = true;
2286                         
2287                         // fetch brightness value
2288                         Entity updated = client.getValueObject(e, brightness).getEntities().get(0);
2289                         brightnessValue = updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").getValueAsInt();
2290                         //System.out.println("Read: " + brightnessValue);
2291                         
2292                         // set new brightness value
2293                         if ( brightnessValue > 50 ) {
2294                                 brightnessValue = 30;
2295                         } else {
2296                                 brightnessValue = 80;
2297                         }
2298                         
2299                         // send new brightness value
2300                         updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").setValue(brightnessValue);
2301                         updated = client.setValueObject(e, updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness")).getEntities().get(0);
2302                         
2303                         // fetch brightness value again to see if it changed correctly
2304                         updated = client.getValueObject(e, brightness).getEntities().get(0);
2305                         int newValue = updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").getValueAsInt();
2306                         
2307                         if ( brightnessValue != newValue ) {
2308                                 System.err.println("Standard RW test failed. Value (brightness) was not set correctly!");
2309                                 return false;
2310                         }
2311
2312                         // fetch power on state value
2313                         updated = client.getValueObject(e, powerOnState).getEntities().get(0);
2314                         powerValue = updated.getFirstValueObjectByQuantity(RESOURCE.POWERED).getValueAsBoolean();
2315
2316                         // set new power on value
2317                         powerValue = !powerValue;
2318                         
2319                         // send new power on state value
2320                         updated.getFirstValueObjectByQuantity(RESOURCE.POWERED).setValue(powerValue);
2321                         updated = client.setValueObject(e, updated.getFirstValueObjectByQuantity(RESOURCE.POWERED)).getEntities().get(0);
2322
2323                         // fetch power on state value
2324                         updated = client.getValueObject(e, powerOnState).getEntities().get(0);
2325                         boolean newPowerValue = updated.getFirstValueObjectByQuantity(RESOURCE.POWERED).getValueAsBoolean();
2326
2327                         if ( powerValue != newPowerValue ) {
2328                                 System.err.println("Standard RW test failed. Value (power on state) was not set correctly!");
2329                                 return false;
2330                         }
2331                         
2332                         // note that all read timeseries are just generated, not real values and wrote timeseries values 
2333                         // are not followed by any actions on the server side
2334                         
2335                         // fetch brightness timeseries for the last 5 hours
2336                         Date now = new Date();
2337                         TimeSeries readBrightnessTS = null;
2338                         try {
2339                                 readBrightnessTS = client.getValueObject(e, new TemporalContext(Tools.add(now, 0, 0, 0, -5, 0, 0), now), brightness).getTimeSeries().get(0);                            
2340                         } catch ( Exception ex ) {
2341                                 System.err.println("Standard RW test failed. Error while fetching brightness timeseries!");
2342                                 return false;
2343                         }
2344                         
2345                         // debug printing for comparing with the ts seen on browser ui
2346                         System.out.println("Read brightness timeseries:");
2347                         for ( int count = 0; count < readBrightnessTS.getListSize(); count++ ) {
2348                                 System.out.print(((ValueObject)readBrightnessTS.getListItem(count)).getValueAsInt() + " ");
2349                         }
2350                         System.out.println("\n"); // line break
2351
2352                         if ( readBrightnessTS.getListSize() < 1 ) {
2353                                 System.err.println("Standard RW test failed. Error while fetching brightness timeseries! Zero items in returned list.");
2354                                 return false;
2355                         }
2356
2357                         // fetch poweronstate timeseries for the last 5 hours
2358                         TimeSeries readPowerOnStateTS = null;
2359                         try {
2360                                 readPowerOnStateTS = client.getValueObject(e, new TemporalContext(Tools.add(now, 0, 0, 0, -5, 0, 0), now), powerOnState).getTimeSeries().get(0);                                
2361                         } catch ( Exception ex ) {
2362                                 System.err.println("Standard RW test failed. Error while fetching brightness timeseries!");
2363                                 return false;
2364                         }
2365
2366                         // debug printing for comparing with the ts seen on browser ui
2367                         System.out.println("Read PowerOnState timeseries:");
2368                         for ( int count = 0; count < readPowerOnStateTS.getListSize(); count++ ) {
2369                                 System.out.print(((ValueObject)readPowerOnStateTS.getListItem(count)).getValueAsBoolean() + " ");
2370                         }
2371                         System.out.println("\n"); // line break                 
2372                         
2373                         if ( readPowerOnStateTS.getListSize() < 1 ) {
2374                                 System.err.println("Standard RW test failed. Error while fetching power on state timeseries! Zero items in returned list.");
2375                                 return false;
2376                         }
2377
2378                         // send timeseries command (next 5 hours)
2379                         Date end = Tools.add(now, 0, 0, 0, 5, 0, 0);
2380                         TemporalContext tcx = new TemporalContext(now, end);
2381                         TimeSeries ts = new TimeSeries();
2382                         ts.setTemporalContext(tcx);
2383                         // set list type
2384                         ts.setList(new smartapi.rdf.OrderedList());
2385                         // 1 hour timestep between data values
2386                         Duration timeStep = Factory.createDuration(0, 0, 0, 1, 0, 0);
2387                         ts.setTimeStep(timeStep.toString());
2388                         Random rnd = new Random();
2389                         Date currentDate = (Date)now.clone();
2390                         ValueObject baseObject = (ValueObject)brightness.clone();
2391                         baseObject.setValue((Variant)null);
2392                         ts.setBaseObject(baseObject);
2393                         while ( currentDate.before(end) ) {
2394                                 // list items as int
2395                                 ts.addListItem(rnd.nextInt(101));
2396                                 timeStep.addTo(currentDate);
2397                         }
2398                         
2399                         // debug printing for comparing with the ts seen on browser ui
2400                         System.out.println("Wrote brightness timeseries:");
2401                         for ( int count = 0; count < ts.getListSize(); count++ ) {
2402                                 System.out.print(((ValueObject)ts.getListItem(count)).getValueAsInt() + " ");
2403                         }
2404                         System.out.println("\n"); // line break
2405                         
2406                         TimeSeries wroteBrightnessTS = null;
2407                         try {
2408                                 wroteBrightnessTS = client.setValueObject(e, ts, brightness).getTimeSeries().get(0);
2409                         } catch ( Exception ex ) {
2410                                 System.err.println("Standard RW test failed. Error while writing brightness timeserie!");
2411                                 return false;
2412                         }
2413                         
2414                         if ( wroteBrightnessTS.getListSize() < 1 ) {
2415                                 System.err.println("Standard RW test failed. Error while writing brightness timeserie! Zero items in returned list.");
2416                                 return false;
2417                         }
2418                 }
2419                 System.out.println("Standard RW test passed.");
2420                 return true;
2421         }
2422         
2423         public boolean UnitConversionTest()
2424         {
2425                 System.out.println("Running UnitConversionTest...");
2426                 //SmartAPI.setValidationMode(ValidationMode.DONT_UPDATE);
2427
2428                 System.out.println("ENERGYPRICE from e/kWh to pound/MWh");
2429                 ValueObject vo = new ValueObject(RESOURCE.CURRENCY, RESOURCE.EURO, RESOURCE.ENERGYANDWORK, RESOURCE.KILOWATTHOUR, 0.02);
2430                 vo.turtlePrint();
2431                 ValueObject vo2 = UnitConverter.convert(vo, RESOURCE.POUNDSTERLING, RESOURCE.WATTHOUR);
2432                 vo2.turtlePrint();
2433                 if ( !vo2.getUnit().equals(RESOURCE.POUNDSTERLING) || !vo2.getSecondaryUnit().equals(RESOURCE.WATTHOUR) ||
2434                                 vo2.getValue().equals(new Variant(0.02)) ) {
2435                         System.err.println("EnergyPrice conversion from e/kWh to pound/MWh failed!");
2436                         return false;
2437                 }
2438
2439                 System.out.println("ANGLE from radian to degree");
2440                 ValueObject vo3 = new ValueObject(RESOURCE.PLANEANGLE, RESOURCE.RADIAN, 3.14159265);
2441                 vo3.turtlePrint();
2442                 ValueObject vo4 = UnitConverter.convert(vo3, RESOURCE.DEGREEANGLE);
2443                 vo4.turtlePrint();
2444                 if ( !vo4.getUnit().equals(RESOURCE.DEGREEANGLE) || 
2445                                 vo4.getValue().equals(new Variant(3.14159265)) ) {
2446                         System.err.println("Angle conversion from radian to degree failed!");
2447                         return false;
2448                 }
2449
2450                 System.out.println("CURRENCY from euro to pound");
2451                 ValueObject vo5 = new ValueObject(RESOURCE.CURRENCY, RESOURCE.EURO, 5);
2452                 vo5.turtlePrint();
2453                 ValueObject vo6 = UnitConverter.convert(vo5, RESOURCE.POUNDSTERLING);
2454                 vo6.turtlePrint();
2455                 if ( !vo6.getUnit().equals(RESOURCE.POUNDSTERLING) || 
2456                                 vo6.getValue().equals(new Variant(5)) ) {
2457                         System.err.println("Currency conversion from euro to pound failed!");
2458                         return false;
2459                 }
2460
2461                 System.out.println("ENERGY CONSUMPTION from kWh/km to Wh/m");
2462                 ValueObject vo7 = new ValueObject(RESOURCE.ENERGYANDWORK, RESOURCE.KILOWATTHOUR, RESOURCE.LENGTH, RESOURCE.KILOMETER, 8);
2463                 vo7.turtlePrint();
2464                 ValueObject vo8 = UnitConverter.convert(vo7, RESOURCE.WATTHOUR, RESOURCE.METER);
2465                 vo8.turtlePrint();
2466                 if ( !vo8.getUnit().equals(RESOURCE.WATTHOUR) || !vo8.getSecondaryUnit().equals(RESOURCE.METER) || 
2467                                 vo8.getValue().asInt() != 8 ) {
2468                         System.err.println("Energy consumption conversion from kWh/km to Wh/m failed!");
2469                         return false;
2470                 }
2471                 
2472                 System.out.println("UnitConversionTest passed.");
2473                 return true;
2474         }
2475         
2476         public boolean graphTests()
2477         {
2478                 GraphTests gt = new GraphTests();
2479                 return gt.runTests();
2480         }
2481         
2482         /*
2483          * Tests serialization and parsing of objects where signing has been done to multiple levels in objects,
2484          * resulting in several multipart objects
2485          */
2486         public boolean recursiveMultipartTest()
2487         {
2488                 System.out.println("Running recursive multipart test...");
2489                 PublicKey pubKey = null;
2490                 PrivateKey privKey = null;
2491                 Transaction transaction = null;
2492                 Request req =  null;
2493                 
2494                 try {
2495                         pubKey = getPemPublicKey("testkey_public.pem", "RSA");
2496                         privKey = getPemPrivateKey("testkey_private.pem", "RSA");
2497                         transaction = Factory.createTransaction("http://www.my.org/sender");
2498                         req =  Factory.createRequest("http://www.my.org/me");
2499                 } catch (Exception ex) {
2500                         System.out.println("Could not find keys for the test.");
2501                         System.out.println(ex);
2502                 }
2503                 
2504                 Entity e = new Entity("http://www.my.org/entity");
2505                 Offering o = new Offering();
2506                 e.addOffering(o);
2507                 e.sign(privKey);
2508
2509                 transaction.setSigner("http://www.my.org/signer");
2510                 transaction.setNotarizedObject(e);
2511                 transaction.sign(privKey);
2512                                 
2513                 Activity a = new Activity("http://www.my.org/activity");
2514                 a.setTransaction(transaction);
2515                 a.setMethod(RESOURCE.WRITE);
2516                 req.addActivity(a);
2517                 
2518                 req.sign(privKey);
2519
2520                 // The data is now ready to be serialized into the message.
2521                 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(req, SERIALIZATION.TURTLE);
2522                 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
2523                 
2524                 Request rr = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
2525                 System.out.println("Resulting Activity: " + rr.getFirstActivity());
2526                 Transaction tt = (Transaction)rr.getFirstActivity().getTransaction();
2527                 System.out.println("Resulting Transaction: " + tt);
2528                 System.out.println("Resulting Object: " + tt.getNotarizedObject());
2529                 System.out.println("Resulting Offerings: " + tt.getNotarizedObject().getOfferings());
2530                 return tt.getNotarizedObject().getOfferings().size() > 0;
2531         }
2532         
2533         public boolean conceptValidationTest()
2534         {
2535                 System.out.println("Running concept validation test...");
2536                 
2537                 try {
2538                         Service s = new Service("http://concept.validation.test/");
2539                         // add undefined concept
2540                         s.addType(NS.SMARTAPI + "MyType");
2541                         s.add(PROPERTY.METHOD, new Obj(RESOURCE.READ));
2542                         // add illegal value type (string instead of resource)
2543                         s.add(PROPERTY.METHOD, RESOURCE.READ);
2544                         // add undefined concept
2545                         s.add(PROPERTY.METHOD, new Obj(NS.SMARTAPI + "MyMethod"));
2546                         // add undefined property
2547                         s.add(NS.SMARTAPI + "myProp", "helloy");
2548                         s.setName("Concept validation test Service ");
2549                         s.setDescription("Sample service description for concept validation test.");
2550                         s.setInterface(Factory.createStandardInterface("acme.com"));
2551                         s.addCapability(Factory.createStandardReadActivity("http://acme.com/service/Cread"));
2552                         
2553         &n