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