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