1 package smartapi.tests;
3 import java.util.ArrayList;
4 import java.util.Calendar;
6 import java.util.HashMap;
7 import java.util.Random;
8 import java.util.concurrent.TimeUnit;
9 import java.util.Base64;
11 import java.io.DataInputStream;
13 import java.io.FileInputStream;
14 import java.nio.charset.StandardCharsets;
15 import java.lang.reflect.InvocationTargetException;
17 import java.security.PrivateKey;
18 import java.security.PublicKey;
19 import javax.crypto.SecretKey;
20 import javax.xml.datatype.Duration;
22 import org.apache.jena.rdf.model.Model;
23 import org.apache.jena.rdf.model.Resource;
24 import org.apache.commons.lang3.time.DateUtils;
25 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import smartapi.agents.OntologyAgent;
28 import smartapi.agents.RegistrationAgent;
29 import smartapi.agents.SearchAgent;
30 import smartapi.agents.SharingAgent;
31 import smartapi.agents.TradingAgent;
32 import smartapi.agents.TransactionAgent;
33 import smartapi.common.ConceptValidator;
34 import smartapi.common.Crypto;
35 import smartapi.common.CryptoKeyWallet;
36 import smartapi.common.DATATYPE;
37 import smartapi.common.HttpClient;
38 import smartapi.common.HttpMessage;
39 import smartapi.common.MessagePart;
40 import smartapi.common.NS;
41 import smartapi.common.PROPERTY;
42 import smartapi.common.RESOURCE;
43 import smartapi.common.SERIALIZATION;
44 import smartapi.common.SmartAPI;
45 import smartapi.common.Tools;
46 import smartapi.factory.Factory;
47 import smartapi.model.Account;
48 import smartapi.model.Activity;
49 import smartapi.model.Address;
50 import smartapi.model.Availability;
51 import smartapi.model.Capacity;
52 import smartapi.model.Condition;
53 import smartapi.model.Coordinates;
54 import smartapi.model.Device;
55 import smartapi.model.Entity;
56 import smartapi.model.Enumeration;
57 import smartapi.model.Evaluation;
58 import smartapi.model.Grading;
59 import smartapi.model.Input;
60 import smartapi.model.InterfaceAddress;
61 import smartapi.model.Map;
62 import smartapi.model.Message;
63 import smartapi.model.Obj;
64 import smartapi.model.Offering;
65 import smartapi.model.Organization;
66 import smartapi.model.Output;
67 import smartapi.model.Parameter;
68 import smartapi.model.PhysicalEntity;
69 import smartapi.model.PriceSpecification;
70 import smartapi.model.PropertyDependentPriceSpecification;
71 import smartapi.model.Request;
72 import smartapi.model.Response;
73 import smartapi.model.Route;
74 import smartapi.model.Service;
75 import smartapi.model.SomeItems;
76 import smartapi.model.Status;
77 import smartapi.model.SystemOfInterest;
78 import smartapi.model.TemporalContext;
79 import smartapi.model.TimeSeries;
80 import smartapi.model.Transaction;
81 import smartapi.model.UnitPriceSpecification;
82 import smartapi.model.ValueObject;
83 import smartapi.model.Velocity;
84 import smartapi.rdf.*;
85 import smartapi.reasoner.UnitConverter;
88 public class TestSequence {
94 public static void main(String[] args)
97 TestSequence testSequence = new TestSequence();
98 testSequence.runSequence();
101 public void simpleSerializeParseTest()
103 Activity a = new Activity();
104 Input i = new Input();
105 Output o = new Output();
109 Route route = new Route();
110 Velocity averageSpeed = new Velocity();
111 averageSpeed.setGroundSpeed(new ValueObject(NS.UNIT + "KilometerPerHour", 10));
112 route.setAverageVelocity(averageSpeed);
114 o.add("routeData", route);
116 serializeReserialize(a);
119 public void classSerializeParseTest()
121 System.out.println("class Serialize Parse Test...");
124 String serialization = SERIALIZATION.TURTLE;
126 // // ALIVEREQUEST TEST
128 // // run TestAliveRequest and get the reference object string
129 // String javaAliveRequestString = TestAliveRequest.test(serialization);
131 // // parse to Java object
133 // AliveRequest javaAliveRequest = (AliveRequest)Tools.toObj(javaAliveRequestString, serialization);
135 // // test print, to be removed
136 // System.out.println("\nSecond serialization: \n\n" + Tools.toString(javaAliveRequest, serialization) + "\n\n");
138 // run C++ TestAliveRequest and get aliveRequest string from there
140 //String cppAliveRequestString = HttpClient.sendPost("http://seas.asema.com/webapps/tests/seasobjects/cpp", "TestAliveRequest");
141 // parse to Java object
142 //AliveRequest cppAliveRequest = AliveRequest.fromString(cppAliveRequestString, serialization);
144 // run C# TestAliveRequest and get aliveRequest string from there
146 //String csAliveRequestString = HttpClient.sendPost("http://seas.asema.com/webapps/tests/seasobjects/cs", "TestAliveRequest");
147 // parse to Java object
148 //AliveRequest csAliveRequest = AliveRequest.fromString(csAliveRequestString, serialization);
150 // compare Java object with c++
151 //javaAliveRequest.equals(cppAliveRequest);
152 // report here if cross-platform test failed
154 // compare Java object with c#
155 //javaAliveRequest.equals(csAliveRequest);
156 // report here if cross-platform test failed
157 } catch ( Exception e ) {
163 public void listSerializeParseTest(int listSize)
165 System.out.println("Running listSerializeParseTest (list size: " + listSize + ")");
166 Date testStartTime = new Date();
169 Date now = new Date();
170 Calendar calendar = Calendar.getInstance();
171 calendar.setTime(now);
173 TimeSeries ts = new TimeSeries();
175 //ArrayList<Evaluation> testList = new ArrayList<Evaluation>();
176 smartapi.rdf.List testList = new LinkedList();
178 for ( int i = 0; i < listSize; i++ ) {
179 Evaluation e = new Evaluation();
180 e.setValue(new Variant(i));
181 e.setInstant(calendar.getTime());
182 calendar.add(Calendar.DATE, 1);
187 ts.setList(testList);
188 printTestTime(testStartTime, "Time");
191 System.out.println("Serializing data...\n");
192 String stringData = Tools.toString(ts, SERIALIZATION.TURTLE);
193 System.out.println(stringData+"\n");
194 System.out.println("---test print() function \n");
196 printTestTime(testStartTime, "Time");
199 System.out.println("Parsing back the serialized data...");
200 Model model = Tools.fromString(stringData, SERIALIZATION.TURTLE);
203 res = Tools.getResourceByType(RESOURCE.TIMESERIES, model);
204 } catch (Exception e) {
205 System.err.println("Exception while trying to get smartapi:TimeSeries resource from the model.");
206 printTestTime(testStartTime, "Test interrupted in");
211 TimeSeries tsParsed = Obj.parse(TimeSeries.class, res);
212 // test if list items are still there
213 if ( tsParsed.hasList() ) {
214 ArrayList<Evaluation> tsl = (ArrayList<Evaluation>)(ArrayList<?>)tsParsed.getList().getItems();
215 if ( tsl.size() == listSize ) {
216 System.out.println("ListSerializeParseTest (list size: " + listSize + ") passed.");
217 printTestTime(testStartTime, "Test executed in");
219 System.err.println("ListSerializeParseTest (list size: " + listSize + ") failed!");
220 System.err.println("Size of serialized and parsed list is " + tsl.size() + ".");
221 printTestTime(testStartTime, "Test executed in");
224 System.err.println("ListSerializeParseTest (list size: " + listSize + ") failed!");
225 System.err.println("Size of serialized and parsed list is 0.");
226 printTestTime(testStartTime, "Test executed in");
229 catch (NoSuchMethodException e) {}
230 catch (InvocationTargetException e) {}
233 public void arraySerializeParseTest(int listSize)
235 System.out.println("Running arraySerializeParseTest (array size: " + listSize + ")");
236 Date testStartTime = new Date();
239 Date now = new Date();
240 Calendar calendar = Calendar.getInstance();
241 calendar.setTime(now);
243 TimeSeries ts = new TimeSeries();
244 OrderedList testList = new OrderedList();
246 for ( int i = 0; i < listSize; i++ ) {
247 Evaluation e = new Evaluation();
248 e.setValue(new Variant(i));
249 e.setInstant(calendar.getTime());
250 calendar.add(Calendar.DATE, 1);
251 testList.addItems(e);
254 ts.setList(testList);
255 printTestTime(testStartTime, "Time");
258 System.out.println("Serializing data...");
259 String stringData = Tools.toString(ts, SERIALIZATION.TURTLE);
260 printTestTime(testStartTime, "Time");
263 System.out.println("Parsing back the serialized data...");
264 Model model = Tools.fromString(stringData, SERIALIZATION.TURTLE);
267 res = Tools.getResourceByType(RESOURCE.TIMESERIES, model);
268 } catch (Exception e) {
269 System.err.println("Exception while trying to get smartapi:TimeSeries resource from the model.");
270 printTestTime(testStartTime, "Test interrupted in");
275 TimeSeries tsParsed = Obj.parse(TimeSeries.class, res);
277 // test if list items are still there
278 if ( tsParsed.hasList() ) {
279 ArrayList<Evaluation> tsl = (ArrayList<Evaluation>)(ArrayList<?>)tsParsed.getList().getItems();
280 if ( tsl.size() == listSize ) {
281 System.out.println("ArraySerializeParseTest (array size: " + listSize + ") passed.");
282 printTestTime(testStartTime, "Test executed in");
284 System.err.println("ArraySerializeParseTest (array size: " + listSize + ") failed!");
285 System.err.println("Size of serialized and parsed array is " + tsl.size() + ".");
286 printTestTime(testStartTime, "Test executed in");
289 System.err.println("ArraySerializeParseTest (array size: " + listSize + ") failed!");
290 System.err.println("Size of serialized and parsed array is 0.");
291 printTestTime(testStartTime, "Test executed in");
294 catch (NoSuchMethodException e) {}
295 catch (InvocationTargetException e) {}
297 public void listOfMapsTest()
299 System.out.println("List of maps test");
301 Activity a = new Activity();
302 Input i = new Input();
303 Output o = new Output();
309 ArrayList<Map> controllable_appliances = new ArrayList<Map>();
310 i.add("ControllableAppliances", controllable_appliances);
312 Map appliance1 = new Map();
313 appliance1.insert("Active", true);
314 appliance1.insert("ConsumptionRate", 1.267);
315 appliance1.insert("Name", "String content");
317 ArrayList<Map> controllable_works = new ArrayList<Map>();
318 Map works1 = new Map();
319 works1.insert("EarlyStartPeriod", 2147483647);
320 works1.insert("LateStopPeriod", 2147483647);
321 works1.insert("WorkDuration", 2147483647);
322 controllable_works.add(works1);
323 appliance1.insert("ControllableWorks", works1);
324 controllable_appliances.add(appliance1);
327 ArrayList<Map> controllable_appliance_result = new ArrayList<Map>();
328 ArrayList<Map> controllable_appliance_work_result = new ArrayList<Map>();
330 Map appliance_result_1 = new Map();
331 Map work_result_1 = new Map();
332 Map usage_information = new Map();
334 appliance_result_1.insert("Name", "String content");
335 appliance_result_1.insert("ControllableWorkResult", controllable_appliance_work_result);
336 controllable_appliance_work_result.add(work_result_1);
337 usage_information.insert("StartPeriod", 2147483647);
338 usage_information.insert("StopPeriod", 2147483647);
339 usage_information.insert("WorkDuration", 2147483647);
340 work_result_1.insert("UsageInformation", usage_information);
342 ArrayList<Map> period_consumptions = new ArrayList<Map>();
343 Map period_1 = new Map();
344 period_1.insert("Period", 2147483647);
345 period_1.insert("Value", 1.26743);
346 period_consumptions.add(period_1);
347 work_result_1.insert("PeriodConsumption", period_consumptions);
348 controllable_appliance_result.add(appliance_result_1);
349 o.add("ControllableApplianceResult", controllable_appliance_result);
351 serializeReserialize(a);
354 public void listOfMapsWithValueObjectsTest()
356 System.out.println("List of maps test");
358 Activity a = new Activity();
359 Input i = new Input();
360 Output o = new Output();
366 ArrayList<Map> controllable_appliances = new ArrayList<Map>();
367 i.add("ControllableAppliances", controllable_appliances);
369 Map appliance1 = new Map();
370 appliance1.insert("Active", true);
371 appliance1.insert("ConsumptionRate", 1.267);
372 appliance1.insert("Name", "String content");
374 ArrayList<Map> controllable_works = new ArrayList<Map>();
375 Map works1 = new Map();
376 works1.insert("EarlyStartPeriod", 2147483647);
377 works1.insert("LateStopPeriod", 2147483647);
378 works1.insert("WorkDuration", 2147483647);
379 controllable_works.add(works1);
380 appliance1.insert("ControllableWorks", works1);
381 controllable_appliances.add(appliance1);
384 ArrayList<Map> controllable_appliance_result = new ArrayList<Map>();
385 ArrayList<Map> controllable_appliance_work_result = new ArrayList<Map>();
387 Map appliance_result_1 = new Map();
388 Map work_result_1 = new Map();
389 Map usage_information = new Map();
391 appliance_result_1.insert("Name", "String content");
392 appliance_result_1.insert("ControllableWorkResult", controllable_appliance_work_result);
393 controllable_appliance_work_result.add(work_result_1);
394 usage_information.insert("StartPeriod", 2147483647);
395 usage_information.insert("StopPeriod", 2147483647);
396 usage_information.insert("WorkDuration", 2147483647);
397 work_result_1.insert("UsageInformation", usage_information);
399 ArrayList<Map> period_consumptions = new ArrayList<Map>();
400 Map period_1 = new Map();
401 period_1.insert("Period", 2147483647);
402 period_1.insert("Value", 1.26743);
403 period_consumptions.add(period_1);
404 work_result_1.insert("PeriodConsumption", period_consumptions);
405 controllable_appliance_result.add(appliance_result_1);
406 o.add("ControllableApplianceResult", controllable_appliance_result);
408 serializeReserialize(a);
411 public void routingAndEnergyTest()
413 String requesterIdentity = "http://seasexamples.asema.com/api/Crequest";
418 r = Factory.createRequest(requesterIdentity);
419 } catch (Exception ex) {}
421 Input i = new Input();
422 Activity ar = new Activity();
426 PhysicalEntity car = new PhysicalEntity();
427 car.setWeight( new ValueObject(NS.UNIT + "Kilogram", 1500));
428 car.add("frontalAerodynamicCoefficient", new ValueObject(NS.UNIT + "SquareMeter", 0.73));
429 car.add("tireRollingResistanceCoefficient", new ValueObject(0.2));
430 car.add("gearEfficiencyCoefficient", new ValueObject(0.3));
431 car.add("batteryCapacity", new ValueObject(NS.UNIT + "KilowattHour", 115000));
432 car.add("extraLoadWeight", new ValueObject(NS.UNIT + "Kilogram", 510));
433 car.add("auxiliaryEquipmentConsumption", new ValueObject(NS.UNIT + "Watt", 365));
434 car.add("maximumAcceleration", new ValueObject(NS.UNIT + "MeterPerSecondSquared", 3.4));
435 car.add("maximumDeceleration", new ValueObject(NS.UNIT + "MeterPerSecondSquared", 4.2));
436 i.add("vehicleData", car);
438 Request r_received = (Request)serializeParse(r, false);
440 // Read some value from the response
441 PhysicalEntity inputtedCar = r_received.getFirstActivity().getFirstInput().getFirstAs(PhysicalEntity.class, "vehicleData");
442 ValueObject frontalAerodynamicCoefficient = inputtedCar.getFirstAs(ValueObject.class, "frontalAerodynamicCoefficient");
443 System.out.println("Got input value for frontalAerodynamicCoefficient: " + frontalAerodynamicCoefficient.getValue().asDouble() + " which is in " + frontalAerodynamicCoefficient.getUnit());
447 String responderIdentity = "http://seasexamples.asema.com/api/Cresponse";
450 r_s = Factory.createResponse(responderIdentity);
451 } catch (Exception ex) {}
453 Activity ar_s = new Activity();
454 Output o_s = new Output();
456 r_s.addActivity(ar_s);
458 TemporalContext tc = new TemporalContext();
459 Velocity averageSpeed = new Velocity();
460 Route route = new Route();
462 averageSpeed.setGroundSpeed(new ValueObject(NS.UNIT + "KilometerPerHour", 34.1));
463 tc.setDuration("PT1H");
465 route.setLength(new ValueObject(NS.UNIT + "Kilometer", 42.3));
466 route.setEnergyConsumption(new ValueObject(NS.UNIT + "KilowattHour", 12000));
467 route.setAverageVelocity(averageSpeed);
468 route.setDuration(tc);
470 route.add(PROPERTY.ADDON, 1.22);
471 route.add(PROPERTY.FRESHNESS, Factory.createDuration(1, 2,3,4,5,6));
473 System.out.println("DEBUG: "+route.get(PROPERTY.FRESHNESS));
475 o_s.add("routeData", route);
477 //serializeReserialize(r);
478 serializeReserialize(r_s);
481 public void registrationTest()
483 String serverIdentity = "http://seasexamples.asema.com/api/Ctestserver";
484 Service service = createSampleRegistrationEntity(serverIdentity);
486 RegistrationAgent agent = new RegistrationAgent(serverIdentity);
487 agent.addEntity(service);
489 Response response = agent.registrate();
490 // print out possible errors on the response
491 Tools.printErrors(response);
492 // get response status
493 if ( response.hasStatus() ) {
494 Status status = response.getStatus();
495 // check if the operation was successful
496 if ( status.hasType(RESOURCE.ERROR) ) {
497 System.out.println("Registration failed.");
499 System.out.println("Registration successful.");
503 System.out.println(" Now try deregister:");
504 Response response2 = agent.deRegistrate();
505 Tools.printErrors(response2);
507 System.out.println(" now try search:");
508 SearchAgent agent2 = new SearchAgent(serverIdentity);
509 agent2.debugMode(true);
510 // all entities in Otaniemi, Espoo as defined by the given polygon
511 ArrayList<Coordinates> polygon = new ArrayList<Coordinates>();
512 polygon.add(new Coordinates(60.178, 24.829));
513 polygon.add(new Coordinates(60.183, 24.83));
514 polygon.add(new Coordinates(60.1926, 24.842));
515 polygon.add(new Coordinates(60.187, 24.809));
516 polygon.add(new Coordinates(60.181, 24.818));
517 agent2.polygonSearchArea(polygon);
519 java.util.List<Entity> entities = agent2.search();
520 System.out.println(entities.size());
521 for (Entity e: entities){
522 System.out.println(e.getName()+ "-"+ e.getIdentifierUri());
523 System.out.println(e.getTypes());
527 public void symmetricCryptoTest()
529 SecretKey key = Crypto.generateSymmetricKey();
530 String content = "The two men entered the Starbucks on Thursday and asked to use to the bathroom. An employee told them it was only for paying customers. When they then sat in the store without ordering anything, the manager called police, and the men were arrested for trespassing. No charges were filed. ";
532 String encrypted = Crypto.symmetricEncrypt(key, content);
533 String decrypted = Crypto.symmetricDecrypt(key, encrypted);
535 System.out.println("Crypto test.");
536 System.out.println("Original:\n" + content);
537 System.out.println("Encrypted:\n" + encrypted);
538 System.out.println("Decrypted:\n" + decrypted);
539 System.out.println("Key:\n" + Crypto.encodeKeyToBase64(key));
542 public void cryptoRegistrationTest()
544 PublicKey pubKey = null;
545 PrivateKey privKey = null;
548 pubKey = getPemPublicKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_public.pem", "RSA");
549 privKey = getPemPrivateKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_private.pem", "RSA");
550 } catch (Exception ex) {
551 System.out.println("Could not find keys.");
552 System.out.println(ex);
554 String serverIdentity = "http://seasexamples.asema.com/api/Ctestserver";
555 Service service = createSampleRegistrationEntity(serverIdentity);
557 RegistrationAgent agent = new RegistrationAgent(serverIdentity);
558 String payload = agent.generateEncryptedRegistrationMessage(pubKey, service).getLeft();
559 System.out.println("------");
560 System.out.println(payload);
561 System.out.println("------");
564 //payload = "PDvrIUEup/eiTAolieUHSFBgV+UI2h0vvuGhHQjnS5QXlBmPKgO4WrJTUyV60Yqx7/baPg28or6Zat4HokK0ZbXux6xUMvYUTkGpzSjrnaulrn7biv5g/p7dTKx89JkVuW0K3Oci2ICDdg4PcYC1EH/7EWVaLUoUcPb1qRn/qBpsDwieBvvHU4Solo59meo26Ch+CL4hLtsTtrdZmtCvUkn1lIFm9vc3WRo5jXZP9vpR5UMRVXDCu007fqeAD7ppgJHI6/U3kIiyc3n54yvgyzKShlAeORIaxNxMSY09QTEtoGr92M5iBoOZYsfdxndfHy0yPNuGvOhO9ab6nrXwlA==";
566 //payload += "LCBcyYE+8ILCD43DOQGBsg==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";
569 //payload = "fYM/MR0yq2nDAvDM8xEg6VvEyvz9eWZefFylY6vaQr3syQw2vATDpv7DZIUdb3fsGbX9kboJNSSQTOTEG/VDhjnPz9DWLJXygRE3868ywyhzn5ojKrBMwf+ehvYfMnJI5gco+EzbO8zFuCC2yukJV/FA72y3OV3r/BGRSsJ+r+vZrwzF92m0rAJD0qrZ/ENfxEOgtXYUAs/glcxSi0fKUtrXledAnblusSXbg6iIdPBb7+5A+OadBg8oPZqIkZT2RwscsshEUDWlXYmZhmWjAkcNhiJiU1SJU9bt0oXBTVprmMBdzxlmU00xBnBj9qsu44e73I3YDIz04jnrcS8PzQ==";
571 //payload += "Zh8VwrOxzMgke5nGy2WVaQ==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";
573 ImmutablePair<String, SecretKey> decrypted = Crypto.asymmetricDecrypt(privKey, payload);
574 System.out.println(decrypted.getLeft());
575 System.out.println("------");
576 String ct = Crypto.symmetricEncrypt(decrypted.getRight(), decrypted.getLeft());
577 //System.out.println(ct);
578 String pt = Crypto.symmetricDecrypt(decrypted.getRight(), ct);
579 //System.out.println(pt);
582 private String loadKeyFile(String filename) throws Exception {
583 System.out.println("Loading key: " + filename);
585 File f = new File("src/smartapi/tests/"+filename);
586 System.out.println(f.getAbsolutePath());
589 //File f = new File(filename);
590 FileInputStream fis = new FileInputStream(f);
591 DataInputStream dis = new DataInputStream(fis);
592 byte[] keyBytes = new byte[(int) f.length()];
593 dis.readFully(keyBytes);
596 return new String(keyBytes);
599 private PrivateKey getPemPrivateKey(String fileName, String algorithm) throws Exception {
600 String keyData = loadKeyFile(fileName);
601 return Crypto.extractPemFormatPrivateKey(keyData, algorithm);
604 private PublicKey getPemPublicKey(String fileName, String algorithm) throws Exception {
605 String keyData = loadKeyFile(fileName);
606 return Crypto.extractPemFormatPublicKey(keyData, algorithm);
609 public static Service createSampleRegistrationEntity(String serverIdentity)
611 String serverName = "A fantastic Java route energy calculation service";
613 Service service = new Service(serverIdentity);
616 Organization owner = new Organization();
617 Address acmeAddress = new Address();
618 InterfaceAddress iface = new InterfaceAddress();
620 iface.setHost("www.acme.com");
621 iface.setScheme("https");
622 iface.setPath("/seas/v1.0e1.0/access");
623 acmeAddress.setStreetAddress("Giant Rubber Band Street");
624 acmeAddress.setZipCode("12345");
625 acmeAddress.setCity("Fairfield, New Java");
626 owner.setName("Acme Industries");
627 owner.setAddress(acmeAddress);
629 service.addInterface(iface);
630 service.addOwner(owner);
631 service.setName(serverName);
632 service.setDescription("A route calculation service that in addition to length and driving time calculates the amount of energy consumed in the battery. Takes as parameters various efficiency factors such as weight and drag.");
633 service.addWebsite("http://www.acme.com/acmeoptimizers/roadrunner/beep/beep");
637 Activity a = new Activity();
638 Input i = new Input();
639 Output o = new Output();
642 service.addCapability(a);
644 PhysicalEntity car = new PhysicalEntity();
645 car.setWeight(Factory.createValueObject(NS.UNIT + "Kilogram", "Vehicle's weight without any consumables or passengers."));
646 car.add("frontalAerodynamicCoefficient", Factory.createValueObject(NS.UNIT + "SquareMeter", "Product of vehicle's frontal area and aerodynamic coefficient"));
647 car.add("tireRollingResistanceCoefficient", Factory.createValueObject(new Obj(DATATYPE.INTEGER), "Vehicle's tire rolling resistance coefficient, in interval ]0, 1["));
648 car.add("gearEfficiencyCoefficient", Factory.createValueObject("Vehicle's efficiency coefficient between engine and gear, in interval ]0, 1["));
649 car.add("batteryCapacity", Factory.createValueObject(NS.UNIT + "KilowattHour", "Vehicle's capacity of the battery (enter only if electric vehicle or hybrid rechargeable, 0 otherwise"));
650 car.add("extraLoadWeight", Factory.createValueObject(NS.UNIT + "Kilogram", "Vehicle's extra load (consumables and passengers weight)"));
651 car.add("auxiliaryEquipmentConsumption", Factory.createValueObject(NS.UNIT + "Watt", "Vehicle's instantaneous auxiliary equipments consumption"));
652 car.add("maximumAcceleration", Factory.createValueObject(NS.UNIT + "MeterPerSecondSquared", "Maximum acceleration (> 0.1), based on vehicle's acceleration capacity and expected driving behavior"));
653 car.add("maximumDeceleration", Factory.createValueObject(NS.UNIT + "MeterPerSecondSquared", "Maximum deceleration (< -0.1), based on vehicle's braking capacity and expected driving behavior"));
654 i.add("vehicleData", car);
656 TemporalContext tc = new TemporalContext();
657 Velocity averageSpeed = new Velocity();
658 Route route = new Route();
660 tc.setDescription("The timespan estimated for traveling the route.");
661 averageSpeed.setDescription("Estimated average speed for the travel.");
663 averageSpeed.setGroundSpeed(Factory.createValueObject(NS.UNIT + "KilometerPerHour", "Speed component in relation to road surface."));
665 route.setLength(Factory.createValueObject(NS.UNIT + "Kilometer", "Total length of the calculated route."));
666 route.setEnergyConsumption(Factory.createValueObject(NS.UNIT + "KilowattHour", "Total energy consumed in driving the route."));
667 route.setAverageVelocity(averageSpeed);
668 route.setDuration(tc);
670 o.add("routeData", route);
675 public void transactionProcessingTest()
677 String clientKeyId = "http://www.acme.com/services/abcd/";
678 String publicKeyServer = "http://127.0.0.1:11371";
680 // Fetch public key for clientIdUri
681 PublicKey clientPubKey = Crypto.downloadPublicKey(clientKeyId, publicKeyServer);
682 System.out.println("Got a public key");
683 System.out.println(clientPubKey);
685 PublicKey pubKey = null;
686 PrivateKey privKey = null;
689 pubKey = getPemPublicKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_public.pem", "RSA");
690 privKey = getPemPrivateKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_private.pem", "RSA");
691 } catch (Exception ex) {
692 System.out.println("Could not find keys for the test.");
693 System.out.println(ex);
696 String testData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras dapibus, sapien eu consequat faucibus, ligula purus tincidunt orci, tincidunt mattis orci dolor in eros. Praesent eget enim ante. Curabitur eleifend ipsum orci, quis vehicula lectus auctor vitae. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean congue nisl lectus. Fusce varius aliquam velit at varius. Integer eu bibendum mi, eget rhoncus metus. Morbi efficitur massa et leo viverra hendrerit. Integer fermentum, dui sed gravida interdum, orci nibh posuere elit, a tincidunt tortor urna a eros. Proin ornare ornare massa quis dignissim. Sed sit amet sapien turpis. Fusce tempus turpis vitae nunc tincidunt ornare. Nulla sit amet scelerisque lectus. Nulla facilisis ipsum ac elit fermentum pharetra. ";
697 String signature = Crypto.sign(privKey, testData);
698 System.out.println("Created signature: " + signature);
699 boolean signedProperly = false;
701 signedProperly = Crypto.verifySignature(signature, pubKey, testData);
702 } catch (Exception e) {}
703 System.out.println("Signature test result: " + signedProperly);
705 // Generate a session key
706 SecretKey sessionKey = Crypto.generateSymmetricKey();
708 // Encrypt data with sessionKey
709 String encryptedResponse = Crypto.symmetricEncrypt(sessionKey, testData.getBytes(StandardCharsets.UTF_8));
710 System.out.println("\nEncrypted response:\n" + encryptedResponse);
712 // Encrypt sessionKey with client's public key
713 String encryptedSessionKey = Crypto.encryptAndEncodeKey(pubKey, sessionKey);
714 System.out.println("\nEncrypted key:\n" + encryptedSessionKey);
716 // Calculate a hash for the encryptedResponse
717 String responseHash = Crypto.createEncodedMessageDigest(encryptedResponse);
719 System.out.println("\nHash for the response: " + responseHash);
722 boolean hashmatches = Crypto.verifyEncodedMessageDigest(responseHash, encryptedResponse);
723 System.out.println("Hash verification: " + hashmatches);
725 // Open the session key
726 SecretKey decryptedSessionKey = Crypto.decryptAndDecodeKey(privKey, encryptedSessionKey);
727 String descryptedData = Crypto.symmetricDecrypt(sessionKey, encryptedResponse);
728 System.out.println("Decrypted data: \n" + descryptedData);
731 public void transactionVerificationTestWrite()
733 String referenceId = "http://tests.b.c/ref";
734 String senderId = "http://tests.b.c/sender";
735 String myIdentity = senderId;
736 PublicKey pubKey = null;
737 PrivateKey privKey = null;
738 String testData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras dapibus, sapien eu consequat faucibus, ligula purus tincidunt orci, tincidunt mattis orci dolor in eros. Praesent eget enim ante. Curabitur eleifend ipsum orci, quis vehicula lectus auctor vitae. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean congue nisl lectus. Fusce varius aliquam velit at varius. Integer eu bibendum mi, eget rhoncus metus. Morbi efficitur massa et leo viverra hendrerit. Integer fermentum, dui sed gravida interdum, orci nibh posuere elit, a tincidunt tortor urna a eros. Proin ornare ornare massa quis dignissim. Sed sit amet sapien turpis. Fusce tempus turpis vitae nunc tincidunt ornare. Nulla sit amet scelerisque lectus. Nulla facilisis ipsum ac elit fermentum pharetra. ";
741 pubKey = getPemPublicKey("testkey_public.pem", "RSA");
742 privKey = getPemPrivateKey("testkey_private.pem", "RSA");
743 } catch (Exception ex) {
744 System.out.println("Could not find keys for the test.");
745 System.out.println(ex);
748 Base64.Encoder b64e = Base64.getEncoder();
749 String notary = TransactionAgent.getDefaultNotary();
750 SecretKey key = Crypto.generateSymmetricKey();
751 String sessionKeySent = Crypto.encryptAndEncodeKey(pubKey, key);
752 String contentHash = Crypto.createEncodedMessageDigest(testData);
753 String signature = Crypto.sign(privKey, contentHash);
755 System.out.println("Encrypted content key is: " + sessionKeySent);
756 System.out.println("Content signature is: " + signature);
757 System.out.println("Content hash is: " + contentHash);
760 // Emulate send operation
761 Transaction transaction = null;
763 transaction = Factory.createTransaction(referenceId, senderId);
764 } catch ( Exception e ) {
767 transaction.setSigner(senderId);
768 Message message = new Message();
769 message.setHashCode(contentHash);
770 message.setSignature(signature);
771 message.setSessionKey(sessionKeySent);
772 transaction.setNotarizedObject(message);
774 HttpMessage sentMessage = new HttpMessage();
779 r = Factory.createRequest(myIdentity);
780 } catch (Exception ex) {}
781 r.setMethod(RESOURCE.WRITE);
783 Activity a = new Activity();
786 Input i = new Input();
789 SystemOfInterest system = new SystemOfInterest();
790 system.setSameAs(TransactionAgent.getDefaultNotary());
791 i.setSystemOfInterest(system);
793 Parameter param = new Parameter();
794 param.setKey("transactions");
795 param.setName("Transaction id list");
796 param.setDescription("List of ids of transactions that are sent for storing into the database.");
797 param.addValue(new Variant(transaction.getIdentifierUri()));
798 i.addParameter(param);
800 String mainRequestString = Tools.toString(r);
801 sentMessage.add("Main", mainRequestString);
803 String mainRequestHash = Crypto.createEncodedMessageDigest(mainRequestString);
804 String requestSignature = Crypto.sign(privKey, mainRequestHash);
806 // create transaction for the main request
807 String transactionIdentifierUri = myIdentity + Crypto.generate16ByteCryptoRandomString();
808 Transaction requestTransaction = null;
810 requestTransaction = Factory.createTransaction(transactionIdentifierUri, myIdentity);
811 } catch ( Exception e ) {
814 requestTransaction.setSigner(myIdentity);
815 Message requestTransactionMessage = new Message();
816 requestTransactionMessage.setId(r.getId());
817 requestTransactionMessage.setHashCode(mainRequestHash);
818 requestTransactionMessage.setSignature(requestSignature);
819 requestTransaction.setNotarizedObject(requestTransactionMessage);
821 // Add the message signature
822 String requestTransactionString = Tools.toString(requestTransaction);
823 sentMessage.add(transactionIdentifierUri, requestTransactionString);
825 // Add transactions that are sent for storing
826 sentMessage.add(transaction.getIdentifierUri(), Tools.toString(transaction));
827 // with their respective signatures
828 sentMessage.add(transaction.getIdentifierUri(), Tools.toString(transaction));
830 String msg = sentMessage.asString();
831 System.out.println("Sending: \n" + msg + "\n------------------------ < message end > --------------");
834 /* ---- RECEIVE ---- */
837 HttpMessage receivedMessage;
839 receivedMessage = HttpMessage.parse(msg, sentMessage.getContentType());
840 } catch (Exception e) {
841 System.out.println("Failed to parse incoming message body");
845 if (receivedMessage.size() < 2) {
846 System.out.println("Request should have at least two parts");
850 // parse all request parts
851 java.util.Map<String,MessagePart> partsMap = receivedMessage.getParts();
852 Obj[] objects = new Obj[partsMap.size()];
853 String[] parts = new String[partsMap.size()];
854 int mainRequestIndex = -1;
855 Request mainRequest = null;
858 for (String partId : partsMap.keySet()) {
859 MessagePart part = partsMap.get(partId);
860 objects[mi] = Tools.toObj(part.getBody());
861 parts[mi] = part.getBody();
862 if (objects[mi] == null) {
863 System.out.println("No object returned when parsing the following part: " + parts[mi]);
867 if (partId.equals("Main")) {
868 // main Request found
869 if (objects[mi] instanceof Request) {
870 mainRequest = (Request)objects[mi];
871 mainRequestIndex = mi;
873 System.out.println("Main part should contain a Request object");
880 } catch (Exception e) {
881 System.out.println("Exception caught when parsing objects: " + e.getMessage());
884 if (mainRequest == null) {
885 System.out.println("No main Request found");
889 // now find the main transaction, which satisfies the following:
890 // (a) its id is not listed in main request as a sub-transaction
891 // (b) its seas id matches the main request seas id
892 Transaction mainTransaction = null;
894 // get contained transaction ids
895 Activity transactionIdActivity = mainRequest.getFirstActivity();
896 java.util.List<Variant> transactionIds = new ArrayList<Variant>();
897 ArrayList<String> transactionIdStrings = new ArrayList<String>(); // used for checking that transactions match
898 Parameter transactionIdParameter = new Parameter(); // needed for constructing the response
899 if (transactionIdActivity != null) {
900 java.util.List<Input> inputs = transactionIdActivity.getInputs();
901 for (Input ii : inputs) {
902 transactionIds = ii.get("transactions");
903 for (Variant v : transactionIds) {
904 transactionIdParameter.addValue(v);
905 transactionIdStrings.add(v.toString());
909 // verify that transaction ids match the contained transactions
910 // by going through all transactions and removing their ids from
911 // transactionIdStrings; they should all be there and list should
912 // be empty in the end
913 for (Obj o : objects) {
914 if (o instanceof Transaction) {
915 String transactionId = o.getIdentifierUri();
916 if (!transactionIdStrings.remove(transactionId)) {
917 // this transaction id was not in the request,
918 // so it could be the main transaction
919 Transaction t = (Transaction)o;
920 if (mainTransaction == null &&
921 t.hasNotarizedObject() &&
922 t.getNotarizedObject().hasIdentifierUri()) {
923 // transaction message id matches main request id, so this is indeed the main transaction
924 mainTransaction = (Transaction)o;
926 // this isn't the main transaction but its id
927 // cannot be found in the main request either
928 System.out.println("Transaction id " + transactionId + " is missing from the main request");
935 if (mainTransaction == null) {
936 System.out.println("Main transaction not found in the request");
940 // now all elements should have been removed from transactionIdStrings
941 if (transactionIdStrings.size() > 0) {
942 System.out.println("Main request contains " + transactionIds.size() + " unknown transaction ids");
946 // // verify signatures in the two main parts
948 // // request (message) signature
949 // if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
950 // String messageSignature = mainTransaction.getNotarizedObject().getSignature();
951 // String messageHash = mainTransaction.getNotarizedObject().getHashCode();
953 // if (!TransactionAgent.verifyTransactionHash(messageHash, parts[mainRequestIndex])) {
954 // // invalid request signature!
955 // System.out.println("Main request hash verification failed!");
958 // if (!TransactionAgent.verifyTransactionSignature(messageSignature, pubKey, messageHash)) {
959 // // invalid request signature!
960 // System.out.println("Main request signature verification failed!");
963 // System.out.println("Request signature verified");
966 // System.out.println("Message signature not found");
970 // // transaction signature
971 // if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
972 // String transactionSignature = mainTransaction.getNotarizedObject().getSignature();
973 // String transactionHash = mainTransaction.getNotarizedObject().getHashCode();
975 // if (!TransactionAgent.verifyTransactionSignature(transactionSignature, pubKey, transactionHash)) {
976 // // invalid transaction signature!
977 // System.out.println("Transaction signature verification failed!");
980 // System.out.println("Transaction signature verified");
983 // System.out.println("Transaction signature not found");
986 // } catch (Exception e) {
987 // System.out.println("Exception caught when verifying signatures: " + e.getMessage());
992 // public void transactionVerificationTestRead()
994 // String referenceId = "http://tests.b.c/ref";
995 // String senderId = "http://tests.b.c/sender";
996 // String myIdentity = senderId;
997 // String contentHash = "ABCDHashEFGH";
998 // PublicKey pubKey = null;
999 // PrivateKey privKey = null;
1002 // pubKey = getPemPublicKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_public.pem", "RSA");
1003 // privKey = getPemPrivateKey("/home/jani/workspace/git/seas/Common/Java/SeasObjects/src/seasobjects/tests/testkey_private.pem", "RSA");
1004 // } catch (Exception ex) {
1005 // System.out.println("Could not find keys for the test.");
1006 // System.out.println(ex);
1009 // Base64.Encoder b64e = Base64.getEncoder();
1010 // String notaryAddress = TransactionAgent.getDefaultNotary();
1011 // String signature = Crypto.sign(privKey, contentHash);
1013 // System.out.println("Content signature is: " + signature);
1014 // System.out.println("Content hash is: " + contentHash);
1016 // /* ---- SEND ---- */
1017 // // Emulate send operation
1018 // Transaction transaction = null;
1020 // transaction = Factory.createTransaction(referenceId, senderId);
1021 // } catch ( Exception e ) {
1022 // e.printStackTrace();
1025 // transaction.setSigner(senderId);
1026 // Message message = new Message();
1027 // message.setHashCode(contentHash);
1028 // message.setSignature(signature);
1029 // transaction.setNotarizedObject(message);
1031 // HttpMessage sentHttpMessage = new HttpMessage();
1034 // Request r = null;
1036 // r = Factory.createRequest(myIdentity);
1037 // } catch (Exception ex) {}
1038 // r.setMethod(RESOURCE.READ);
1040 // Activity a = new Activity();
1041 // r.addActivity(a);
1043 // Input i = new Input();
1046 // SystemOfInterest system = new SystemOfInterest();
1047 // system.setSameAs(notaryAddress);
1048 // i.setSystemOfInterest(system);
1050 // Parameter param = new Parameter();
1051 // param.setKey("transactions");
1052 // param.setName("Transaction id list");
1053 // param.setDescription("List of ids of transactions that are sent to be fetched from the database.");
1054 // param.addValue(new Variant(transaction.getIdentifierUri()));
1055 // i.addParameter(param);
1057 // String mainRequestString = Tools.toString(r);
1058 // sentHttpMessage.add("Main", mainRequestString);
1060 // String mainRequestHash = Crypto.createEncodedMessageDigest(mainRequestString);
1061 // String requestSignature = Crypto.sign(privKey, mainRequestHash);
1063 // // create transaction for the main request
1064 // String transactionIdentifierUri = myIdentity + Crypto.generate16ByteCryptoRandomString();
1065 // Transaction requestTransaction = null;
1067 // requestTransaction = Factory.createTransaction(transactionIdentifierUri, myIdentity);
1068 // } catch ( Exception e ) {
1069 // e.printStackTrace();
1072 // requestTransaction.setSigner(myIdentity);
1073 // Message requestTransactionMessage = new Message();
1074 // requestTransactionMessage.setId(r.getId());
1075 // requestTransactionMessage.setHashCode(mainRequestHash);
1076 // requestTransactionMessage.setSignature(requestSignature);
1077 // requestTransaction.setNotarizedObject(requestTransactionMessage);
1079 // String requestTransactionString = Tools.toString(requestTransaction);
1080 // sentHttpMessage.add(transactionIdentifierUri, requestTransactionString);
1082 // // add transactions that are sent for reading
1083 // sentHttpMessage.add(transaction.getIdentifierUri(), Tools.toString(transaction));
1085 // String msg = sentHttpMessage.asString();
1086 // System.out.println("Sending: \n" + msg + "\n------------------------ < message end > --------------");
1089 // /* ---- RECEIVE ---- */
1091 // // Emulate reception
1092 // HttpMessage receivedMessage;
1094 // receivedMessage = HttpMessage.parse(msg, sentHttpMessage.getContentType());
1095 // } catch (Exception e) {
1096 // System.out.println("Failed to parse incoming message body");
1100 // if (receivedMessage.size() < 2) {
1101 // System.out.println("Request should have at least two parts");
1105 // // parse all request parts
1106 // java.util.Map<String,MessagePart> partsMap = receivedMessage.getParts();
1107 // Obj[] objects = new Obj[partsMap.size()];
1108 // String[] parts = new String[partsMap.size()];
1109 // int mainRequestIndex = -1;
1110 // Request mainRequest = null;
1113 // for (String partId : partsMap.keySet()) {
1114 // MessagePart part = partsMap.get(partId);
1115 // objects[mi] = Tools.toObj(part.getBody());
1116 // parts[mi] = part.getBody();
1117 // if (objects[mi] == null) {
1118 // System.out.println("No object returned when parsing the following part: " + parts[mi]);
1122 // if (partId.equals("Main")) {
1123 // // main Request found
1124 // if (objects[mi] instanceof Request) {
1125 // mainRequest = (Request)objects[mi];
1126 // mainRequestIndex = mi;
1128 // System.out.println("Main part should contain a Request object");
1135 // } catch (Exception e) {
1136 // System.out.println("Exception caught when parsing objects: " + e.getMessage());
1139 // if (mainRequest == null) {
1140 // System.out.println("No main Request found");
1144 // // now find the main transaction, which satisfies the following:
1145 // // (a) its id is not listed in main request as a sub-transaction
1146 // // (b) its seas id matches the main request seas id
1147 // Transaction mainTransaction = null;
1149 // // get contained transaction ids
1150 // Activity transactionIdActivity = mainRequest.getFirstActivity();
1151 // ArrayList<Variant> transactionIds = new ArrayList<Variant>();
1152 // ArrayList<String> transactionIdStrings = new ArrayList<String>(); // used for checking that transactions match
1153 // Parameter transactionIdParameter = new Parameter(); // needed for constructing the response
1154 // if (transactionIdActivity != null) {
1155 // ArrayList<Input> inputs = transactionIdActivity.getInputs();
1156 // for (Input ii : inputs) {
1157 // transactionIds = ii.get("transactions");
1158 // for (Variant v : transactionIds) {
1159 // transactionIdParameter.addValue(v);
1160 // transactionIdStrings.add(v.toString());
1164 // // verify that transaction ids match the contained transactions
1165 // // by going through all transactions and removing their ids from
1166 // // transactionIdStrings; they should all be there and list should
1167 // // be empty in the end
1168 // for (Obj o : objects) {
1169 // if (o instanceof Transaction) {
1170 // String transactionId = o.getIdentifierUri();
1171 // if (!transactionIdStrings.remove(transactionId)) {
1172 // // this transaction id was not in the request,
1173 // // so it could be the main transaction
1174 // Transaction t = (Transaction)o;
1175 // if (mainTransaction == null &&
1176 // t.hasNotarizedObject()) {
1177 // // transaction message id matches main request id, so this is indeed the main transaction
1178 // mainTransaction = (Transaction)o;
1180 // // this isn't the main transaction but its id
1181 // // cannot be found in the main request either
1182 // System.out.println("Transaction id " + transactionId + " is missing from the main request");
1189 // if (mainTransaction == null) {
1190 // System.out.println("Main transaction not found in the request");
1194 // // now all elements should have been removed from transactionIdStrings
1195 // if (transactionIdStrings.size() > 0) {
1196 // System.out.println("Main request contains " + transactionIds.size() + " unknown transaction ids");
1200 // // verify signatures in the two main parts
1202 // // request (message) signature
1203 // if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
1204 // String messageSignature = mainTransaction.getNotarizedObject().getSignature();
1205 // String messageHash = mainTransaction.getNotarizedObject().getHashCode();
1207 // if (!TransactionAgent.verifyTransactionHash(messageHash, parts[mainRequestIndex])) {
1208 // // invalid request signature!
1209 // System.out.println("Main request hash verification failed!");
1212 // if (!TransactionAgent.verifyTransactionSignature(messageSignature, pubKey, messageHash)) {
1213 // // invalid request signature!
1214 // System.out.println("Main request signature verification failed!");
1217 // System.out.println("Request signature verified");
1220 // System.out.println("Message signature not found");
1224 // // transaction signature
1225 // if (mainTransaction.hasNotarizedObject() && mainTransaction.getNotarizedObject().hasSignature()) {
1226 // String transactionSignature = mainTransaction.getNotarizedObject().getSignature();
1227 // String transactionHash = mainTransaction.getNotarizedObject().getHashCode();
1229 // if (!TransactionAgent.verifyTransactionSignature(transactionSignature, pubKey, transactionHash)) {
1230 // // invalid transaction signature!
1231 // System.out.println("Transaction signature verification failed!");
1234 // System.out.println("Transaction signature verified");
1237 // System.out.println("Transaction signature not found");
1240 // } catch (Exception e) {
1241 // System.out.println("Exception caught when verifying signatures: " + e.getMessage());
1246 public void routingAndEnergyRegistrationTest()
1248 String serverIdentity = "http://seasexamples.asema.com/api/Ctestserver";
1249 String serverName = "A sample charging plan calculation service";
1251 Service service = new Service(serverIdentity);
1254 Organization owner = new Organization();
1255 Address acmeAddress = new Address();
1256 InterfaceAddress iface = new InterfaceAddress();
1258 iface.setHost("www.acme.com");
1259 iface.setScheme("https");
1260 iface.setPath("/seas/v1.0e1.0/access");
1261 acmeAddress.setStreetAddress("Giant Rubber Band Street");
1262 acmeAddress.setZipCode("12345");
1263 acmeAddress.setCity("Fairfield, New Jersey");
1264 owner.setName("Acme Industries");
1265 owner.setAddress(acmeAddress);
1267 service.addInterface(iface);
1268 service.addOwner(owner);
1269 service.setName(serverName);
1270 service.setDescription("A charging plan service that supplies the available energy for charging in timeslots at a charging point.");
1271 service.addWebsite("http://www.acme.com/acmeoptimizers/roadrunner/beep/beep");
1275 Activity a = new Activity();
1276 Input i = new Input();
1277 Output o = new Output();
1280 service.addCapability(a);
1283 Map charge_need = new Map();
1284 charge_need.insert("Energy", Factory.createValueObject(NS.UNIT + "KilowattHour", "Total amount of energy requested to complete the charge."));
1285 charge_need.insert("PowerMax", Factory.createValueObject(NS.UNIT + "Watt", "Maximum allowed instant power for charging the vehicle."));
1286 charge_need.insert("PowerMin", Factory.createValueObject(NS.UNIT + "Watt", "Minumum allowed instant power for charging the vehicle."));
1287 charge_need.insert("Priority", new Obj(DATATYPE.INTEGER));
1288 charge_need.insert("Type", new Enumeration("Immediate", "Delayed"));
1289 TemporalContext tci = new TemporalContext();
1290 tci.setDescription("The desired schedule at which the charging should take place (start (optional) and end)");
1291 charge_need.insert("Schedule", tci);
1292 i.add("ChargingNeed", charge_need);
1295 Map charge_plan = new Map();
1296 ArrayList<Map> orders = new ArrayList<Map>();
1297 Map order = new Map();
1298 TemporalContext tco = new TemporalContext();
1299 tco.setDescription("The start and end times of this charging slot.");
1300 order.insert("Schedule", tco);
1301 order.insert("Power", Factory.createValueObject(NS.UNIT + "Watt", "The instant power supplied in this slot."));
1303 charge_plan.insert("Orders", orders);
1304 o.add("ChargingPlan", charge_plan);
1307 RegistrationAgent agent = new RegistrationAgent(serverIdentity);
1308 String payload = agent.generateRegistrationMessage(service).toTurtle();
1309 System.out.println(payload);
1312 public void hugeDataTest(int itemSize)
1314 System.out.println("Running HugeDataTest (data size: " + itemSize + ")");
1315 Date testStartTime = new Date();
1318 String myId = "http://seasdemos.asema.com/cplusplus/controlcommandsender/Cabcd";
1320 Date now = new Date();
1321 Calendar calendar = Calendar.getInstance();
1322 calendar.setTime(now);
1324 Response res = null;
1326 res = Factory.createResponse(myId);
1327 } catch (Exception e) {
1328 System.err.println("Exception while creating Response with ResponseFactory for " + myId + ".");
1329 printTestTime(testStartTime, "Test interrupted in");
1330 e.printStackTrace();
1332 res.setSameAs("http://hugedata.test");
1333 res.setName("Huge dataset test");
1334 res.setIdentifierUri("http://huge.data.uri");
1336 for ( int i = 0; i < itemSize; i++ ) {
1337 Evaluation ev = new Evaluation();
1338 ev.setValue(new Variant(i));
1339 ev.setInstant(calendar.getTime());
1340 calendar.add(Calendar.DATE, 1);
1341 res.add("http://evaluation.com", ev);
1343 printTestTime(testStartTime, "Time");
1346 System.out.println("Serializing data...");
1347 String stringData = Tools.toString(res, SERIALIZATION.TURTLE);
1348 printTestTime(testStartTime, "Time");
1351 System.out.println("Parsing back the serialized data...");
1352 Model model = Tools.fromString(stringData, SERIALIZATION.TURTLE);
1353 Resource resource = null;
1355 resource = Tools.getResourceByType(RESOURCE.RESPONSE, model);
1356 } catch (Exception e) {
1357 System.err.println("Exception while trying to get smartapi:Response resource from the model.");
1358 printTestTime(testStartTime, "Test interrupted in");
1359 e.printStackTrace();
1363 Response resParsed = Obj.parse(Response.class, resource);
1365 // test if list items are still there
1366 java.util.List<Variant> items = resParsed.get("http://evaluation.com");
1367 if ( items.size() != 0 ) {
1368 if ( items.size() == itemSize ) {
1369 System.out.println("HugeDataTest (data size: " + itemSize + ") passed.");
1370 printTestTime(testStartTime, "Test executed in");
1372 System.err.println("HugeDataTest (data size: " + itemSize + ") failed!");
1373 System.err.println("Size of serialized and parsed data is " + items.size() + ".");
1374 printTestTime(testStartTime, "Test executed in");
1377 System.err.println("HugeDataTest (data size: " + itemSize + ") failed!");
1378 System.err.println("Size of serialized and parsed data is 0.");
1379 printTestTime(testStartTime, "Test executed in");
1382 catch (NoSuchMethodException e) {}
1383 catch (InvocationTargetException e) {}
1386 public void fileInputTest(String fileName, String serialization)
1388 Obj o = Tools.fromFileAsObj(fileName, serialization);
1389 serializeParse(o, true);
1392 public void requestResponseTest1()
1394 String clientIdentity = "http://www.client.com/seas/Cclient";
1395 String serverIdentity = "http://www.server.com/seas/Cserver";
1398 * Test sequence 1, basic request / response
1400 System.out.println("\n\nREQUEST/RESPONSE, TEST 1");
1405 rc = Factory.createRequest(clientIdentity);
1406 } catch (Exception ex) {}
1407 rc.setMethod(RESOURCE.READ);
1408 Activity a = new Activity();
1409 Input i = new Input();
1411 i.setSystemOfInterestWithSameAs("http://a.com/b");
1414 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1415 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1418 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1419 String clientId = rs.getGeneratedBy().toString();
1420 Activity aa = rs.getActivities().get(0);
1421 Input ii = aa.getInputs().get(0);
1422 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1425 Response resp = null;
1427 resp = Factory.createResponse(serverIdentity);
1428 } catch (Exception ex) {}
1429 resp.setMethod(RESOURCE.READ);
1430 Activity ars = new Activity();
1431 Output ors = new Output();
1433 ors.setSystemOfInterestWithSameAs("http://a.com/b");
1434 resp.addActivity(ars);
1436 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1437 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1440 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1441 String serverId = respc.getGeneratedBy().toString();
1442 Activity ac = respc.getActivities().get(0);
1443 Output oc = ac.getOutputs().get(0);
1444 System.out.println("Response, sys of interest " + oc.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + serverId);
1447 public void requestResponseTest2()
1449 String clientIdentity = "http://www.client.com/seas/Cclient";
1450 String serverIdentity = "http://www.server.com/seas/Cserver";
1453 * Test sequence 2, request and response with an offer
1455 System.out.println("\n\nREQUEST/RESPONSE, TEST 2");
1460 rc = Factory.createRequest(clientIdentity);
1461 } catch (Exception ex) {}
1462 rc.setMethod(RESOURCE.READ);
1463 Activity a = new Activity();
1464 Input i = new Input();
1466 i.setSystemOfInterestWithSameAs("http://a.com/b");
1469 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1470 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1473 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1474 String clientId = rs.getGeneratedBy().toString();
1475 Activity aa = rs.getActivities().get(0);
1476 Input ii = aa.getInputs().get(0);
1477 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1480 Response resp = null;
1482 resp = Factory.createResponse(serverIdentity);
1483 } catch (Exception ex) {}
1484 resp.setMethod(RESOURCE.READ);
1486 Offering offering = new Offering("http://a.com/b#" + Crypto.generate16ByteCryptoRandomString(), "Test offer", "Test offer description");
1487 offering.setBusinessFunction(RESOURCE.SELL);
1489 PriceSpecification priceSpecification = new UnitPriceSpecification();
1490 priceSpecification.setCurrency("EUR");
1491 priceSpecification.setCurrencyValue(123);
1492 offering.addPriceSpecification(priceSpecification);
1493 SomeItems items = new SomeItems(RESOURCE.REQUEST, "Service request", "Any kind of service request.", serverIdentity);
1494 offering.addIncludes(items);
1496 aa.addOffering(offering);
1497 resp.addActivity(aa);
1499 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1500 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1503 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1504 String serverId = respc.getGeneratedBy().toString();
1505 Activity ac = respc.getActivities().get(0);
1506 Offering oc = ac.getOfferings().get(0);
1507 System.out.println("Response, offering at price " + oc.getPriceSpecification().get(0).getCurrencyValue());
1510 public void requestResponseTest3()
1512 String clientIdentity = "http://www.client.com/seas/Cclient";
1513 String serverIdentity = "http://www.server.com/seas/Cserver";
1515 SecretKey sessionKey = Crypto.generateSymmetricKey();
1518 * Test sequence 3, request and response with encrypted data
1520 System.out.println("\n\nREQUEST/RESPONSE, TEST 3");
1525 rc = Factory.createRequest(clientIdentity);
1526 } catch (Exception ex) {}
1527 rc.setMethod(RESOURCE.READ);
1528 Activity a = new Activity();
1529 Input i = new Input();
1531 i.setSystemOfInterestWithSameAs("http://a.com/b");
1534 System.out.println("---------explain()-----");
1536 System.out.println("---------turtlePrint()----------");
1538 System.out.println("-------------------");
1540 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1541 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1542 System.out.println("Request Content-Type: " + serializedRequest.getRight());
1545 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1546 String clientId = rs.getGeneratedBy();
1547 Activity aa = rs.getActivities().get(0);
1548 Input ii = aa.getInputs().get(0);
1549 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1552 Response resp = null;
1554 resp = Factory.createResponse(serverIdentity);
1555 } catch (Exception ex) {}
1556 resp.setMethod(RESOURCE.READ);
1557 Activity ars = new Activity();
1558 Output ors = new Output();
1560 ors.setSystemOfInterestWithSameAs("http://a.com/b");
1561 ors.encrypt(sessionKey);
1562 resp.addActivity(ars);
1564 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1565 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1566 System.out.println("Reponse Content-Type: " + serializedResponse.getRight());
1569 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1570 String serverId = respc.getGeneratedBy();
1571 Activity ac = respc.getActivities().get(0);
1572 Output oc = ac.getOutputs().get(0);
1573 oc.decrypt(sessionKey);
1574 System.out.println("Response, sys of interest " + oc.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + serverId);
1577 public void requestResponseTest4()
1579 String clientIdentity = "http://www.client.com/seas/Cclient";
1580 String serverIdentity = "http://www.server.com/seas/Cserver";
1582 PublicKey pubKey = null;
1583 PrivateKey privKey = null;
1587 pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1588 privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1589 } catch (Exception ex) {
1590 System.out.println("Could not find keys for the test.");
1591 System.out.println(ex);
1595 * Test sequence 4, request and response with signed data
1597 System.out.println("\n\nREQUEST/RESPONSE, TEST 4");
1602 rc = Factory.createRequest(clientIdentity);
1603 } catch (Exception ex) {}
1604 rc.setMethod(RESOURCE.READ);
1605 Activity a = new Activity();
1606 Input i = new Input();
1608 i.setSystemOfInterestWithSameAs("http://a.com/b");
1613 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(rc, SERIALIZATION.TURTLE);
1614 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
1617 Request rs = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
1620 String clientId = rs.getGeneratedBy();
1621 System.out.println("after parsing, we get GeneratedBy: "+ clientId);
1622 Activity aa = rs.getActivities().get(0);
1623 Input ii = aa.getInputs().get(0);
1624 System.out.println("Request, sys of interest " + ii.getSystemOfInterest().getSameAs().getIdentifierUri() + " from " + clientId);
1627 Response resp = null;
1629 resp = Factory.createResponse(serverIdentity);
1630 } catch (Exception ex) {}
1631 resp.setMethod(RESOURCE.READ);
1632 Activity ars = new Activity();
1633 Output ors = new Output();
1635 ors.setSystemOfInterestWithSameAs("http://a.com/b");
1637 resp.addActivity(ars);
1639 ImmutablePair<String, String> serializedResponse = Tools.serializeResponse(resp, SERIALIZATION.TURTLE);
1640 System.out.println("RESPONSE:\n" + serializedResponse.getLeft());
1643 Response respc = Tools.parseResponse(serializedResponse.getLeft(), serializedResponse.getRight());
1644 String serverId = respc.getGeneratedBy();
1645 Activity ac = respc.getActivities().get(0);
1646 Output oc = ac.getOutputs().get(0);
1647 boolean verified = false;
1649 verified = oc.verifySignature(pubKey);
1650 } catch (Exception e) {}
1651 System.out.println("Signature verification " + (verified ? "successful" : "failed") );
1652 System.out.println("Response, sys of interest " + oc.getSystemOfInterest()+ " from " + serverId);
1655 void notaryKeyStoreTest()
1657 String myId = "http://seas.test.asema.com/notarykeytest";
1658 String referenceId = "http://seas.test.asema.com/notarykeytest/ref1" + Crypto.generate16ByteCryptoRandomString();
1659 String content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in lectus at sem commodo venenatis. Fusce in eros ex. In hac habitasse platea dictumst. Phasellus dignissim, augue vel aliquet pretium, nibh eros tristique est, dignissim aliquet elit justo vel mauris. Vestibulum a posuere nulla. Curabitur aliquam semper sagittis.";
1660 // to make the content different during each run, otherwise test will fail
1661 content = content + Crypto.generate16ByteCryptoRandomString();
1663 PublicKey pubKey = null;
1664 PrivateKey privKey = null;
1666 pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1667 privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1668 } catch (Exception ex) {
1669 System.out.println("Could not find keys for the test.");
1670 System.out.println(ex);
1672 CryptoKeyWallet.setPublicKey(pubKey);
1673 CryptoKeyWallet.setPrivateKey(privKey);
1675 Base64.Encoder b64e = Base64.getEncoder();
1676 String notary = TransactionAgent.getDefaultNotary();
1677 SecretKey key = Crypto.generateSymmetricKey();
1678 String sessionKeySent = new String(b64e.encode(key.getEncoded()));
1679 String contentHash = Crypto.createEncodedMessageDigest(content);
1680 String signature = Crypto.sign(privKey, content);
1681 boolean sentOK = TransactionAgent.sendKeyToNotary(myId, referenceId, contentHash, sessionKeySent, signature, notary, privKey) != null;
1682 String sessionKeyReceived = TransactionAgent.fetchKeyFromNotary(myId, referenceId, contentHash, signature, notary, privKey);
1684 System.out.println("Sent ok: " + sentOK);
1685 System.out.println("Sent key: " + sessionKeySent);
1686 System.out.println("Received key: " + sessionKeyReceived);
1687 System.out.println("Keys match?: " + sessionKeyReceived.equals(sessionKeySent));
1690 void keyServerTest()
1692 String content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in lectus at sem commodo venenatis. Fusce in eros ex. In hac habitasse platea dictumst. Phasellus dignissim, augue vel aliquet pretium, nibh eros tristique est, dignissim aliquet elit justo vel mauris. Vestibulum a posuere nulla. Curabitur aliquam semper sagittis.";
1693 String keyId = "http://www.acme.com/services/abcd/";
1694 String publicKeyServer = "http://127.0.0.1:11371";
1695 PublicKey downloadedKey = Crypto.downloadPublicKey(keyId, publicKeyServer);
1696 PublicKey pubKey = null;
1697 PrivateKey privKey = null;
1699 pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1700 privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1701 } catch (Exception ex) {
1702 System.out.println("Could not find keys for the test.");
1703 System.out.println(ex);
1706 String signature = Crypto.sign(privKey, content);
1707 boolean verified = false;
1709 verified = Crypto.verifySignature(signature, pubKey, content);
1710 } catch (Exception e) {}
1711 System.out.println("Signature verification, key on disk " + (verified ? "successful" : "failed") );
1714 verified = Crypto.verifySignature(signature, downloadedKey, content);
1715 } catch (Exception e) {
1718 System.out.println("Signature verification, downloaded key " + (verified ? "successful" : "failed") );
1721 public boolean keyHandlingTest()
1723 System.out.println("Running keyHandlingTest..");
1725 ImmutablePair<String,String> keyPair = Tools.createCryptoKeys();
1726 System.out.println("public key: \n" + keyPair.getRight());
1727 System.out.println("private key: \n" + keyPair.getLeft());
1728 Tools.uploadPublicKey(keyPair.getRight(), "http://demo.smart-api.io/testkey", "test", "test", "http://127.0.0.1:11371");
1729 Tools.revokePublicKey("http://demo.smart-api.io/testkey", "test", "test", "http://127.0.0.1:11371");
1730 } catch ( Exception e ) {
1731 System.out.println("KeyHandlingTest failed.");
1732 e.printStackTrace();
1735 System.out.println("KeyHandlingTest passed.");
1740 void simpleHashTest()
1742 Base64.Decoder b64d = Base64.getDecoder();
1743 String r = "Simple hash input";
1744 String responseHash = Crypto.createEncodedMessageDigest(r);
1745 System.out.println("Hash for the text: " + responseHash);
1748 public void printTestTime(Date testStartTime, String text) {
1749 Date testEndTime = new Date();
1750 long testDuration = testEndTime.getTime() - testStartTime.getTime();
1751 long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(testDuration);
1752 long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(testDuration);
1753 long diffInHours = TimeUnit.MILLISECONDS.toHours(testDuration);
1754 if ( diffInSeconds != 0 ) {
1755 testDuration = testDuration - diffInSeconds*1000;
1757 if ( diffInMinutes != 0 ) {
1758 diffInSeconds = diffInSeconds - diffInMinutes*60;
1760 if ( diffInHours != 0 ) {
1761 diffInMinutes = diffInMinutes - diffInHours*60;
1763 System.out.println("\n" + text + ": " + (diffInHours != 0 ? (diffInHours + "h ") : "") +
1764 (diffInMinutes != 0 ? (diffInMinutes + "m ") : "") +
1765 (diffInSeconds != 0 ? (diffInSeconds + "s ") : "") +
1766 (testDuration != 0 ? (testDuration + "ms ") : "") + "\n");
1769 private void serializeReserialize(Obj o)
1771 Obj o_parsed = serializeParse(o, true);
1772 String reserialized = Tools.toString(o_parsed, SERIALIZATION.TURTLE);
1774 System.out.println("----");
1775 System.out.println("Re-serialized: " + reserialized);
1778 private Obj serializeParse(Obj o, boolean doPrint)
1780 String serialized = Tools.toString(o, SERIALIZATION.TURTLE);
1781 if (doPrint) System.out.println("Serialized: " + serialized);
1782 return Tools.fromStringAsObj(serialized, SERIALIZATION.TURTLE);
1786 * 1. Registers boiler device with an Offering for controlling its power.
1787 * 2. Shares boiler by creating Availability and using SharingAgent.
1788 * 3. Searches for available devices that can be controlled with reasonable price.
1789 * 4. Removes sharing.
1790 * 5. Searches again to confirm sharing removal.
1792 public boolean availabilityTest()
1794 System.out.println("Running TestSequence.testAvailability()");
1796 boolean testFailed = false;
1799 String myIdentity = "http://acme.com/boiler/C756fdg76dgfh4376dshg";
1800 String powerIdentifier = "/Cpower";
1801 String volumeIdentifier = "/Cvolume";
1802 String offeringIdentifier = "/Coffering";
1805 Device boiler = new Device(myIdentity);
1806 boiler.addType(RESOURCE.WATERBOILER);
1808 // info about energy consumption (power capacity)
1809 Capacity power = new Capacity(myIdentity + powerIdentifier);
1810 power.setSystemOfInterestWithType(RESOURCE.RESISTOR);
1811 power.setQuantity(RESOURCE.POWER);
1812 power.setUnit(RESOURCE.KILOWATT);
1813 power.setMaximum(new Variant(6));
1814 power.setStep(new Variant(3));
1815 power.setValue(new Variant(6));
1816 boiler.addCapacity(power);
1818 // info about water volume (volume capacity)
1819 Capacity volume = new Capacity(myIdentity + volumeIdentifier);
1820 volume.setSystemOfInterestWithType(RESOURCE.WATERTANK);
1821 volume.setQuantity(RESOURCE.VOLUME);
1822 volume.setUnit(RESOURCE.LITER);
1823 volume.setMaximum(new Variant(500));
1824 volume.setValue(new Variant(500));
1825 boiler.addCapacity(volume);
1827 // price for controlling on/off of this device
1828 Offering offering = new Offering(myIdentity + offeringIdentifier);
1829 boiler.addOffering(offering);
1830 PriceSpecification priceSpecification = new UnitPriceSpecification();
1831 priceSpecification.setGrName("Price to control this boiler");
1832 priceSpecification.setGrDescription("The amount in Euro to be paid for being able to control the two 3 kW resistors of this boiler for one hour.");
1833 priceSpecification.setCurrency("EUR");
1834 priceSpecification.setCurrencyValue(1.5);
1835 offering.addPriceSpecification(priceSpecification);
1836 SomeItems items = new SomeItems(RESOURCE.SERVICESUBSCRIPTION, "Service subscription", "Right to control this device for one hour.", null);
1837 items.setDuration(0, 0, 0, 1, 0, 0); // one hour
1838 offering.addIncludes(items);
1840 // activity for controlling this device
1841 Activity activity = new Activity();
1842 boiler.addCapability(activity);
1843 Input input = new Input();
1844 activity.addInput(input);
1845 input.addEntity(new Entity());
1846 Output output = new Output();
1847 activity.addOutput(output);
1848 output.addEntity(new Entity());
1850 // register boiler description (including offering)
1851 RegistrationAgent registrationAgent = new RegistrationAgent(myIdentity);
1852 registrationAgent.addEntity(boiler);
1853 Response response = registrationAgent.registrate();
1854 // print out possible errors on the response
1855 Tools.printErrors(response);
1856 // get response status
1857 if ( response.hasStatus() ) {
1858 Status status = response.getStatus();
1859 // check if the operation was successful
1860 if ( status.hasType(RESOURCE.ERROR) ) {
1861 System.out.println(" ..Registration failed.");
1864 System.out.println(" ..Registration successful. ");
1867 System.out.println(" ..No status found in response. Registration probably failed.");
1870 // create availability of the control of this boiler
1871 Availability availability = new Availability();
1872 // available from now on for two weeks
1873 Date now = new Date();
1874 availability.addAvailability(now, Tools.add(now, 0, 0, 14, 0, 0, 0));
1875 // available local time from 8 am to 4 pm and 1 am to 4 am (local time) on weekdays
1876 availability.addAvailability(Factory.createTimeFromLocalTimeString("08:00:00"), Factory.createTimeFromLocalTimeString("16:00:00"), RESOURCE.WEEKDAY);
1877 availability.addAvailability(Factory.createTimeFromLocalTimeString("01:00:00"), Factory.createTimeFromLocalTimeString("04:00:00"), RESOURCE.WEEKDAY);
1878 // available local time from 1 am to 9 am (local time) on weekends
1879 availability.addAvailability(Factory.createTimeFromLocalTimeString("01:00:00"), Factory.createTimeFromLocalTimeString("09:00:00"), RESOURCE.WEEKEND);
1880 // available in Finland
1881 availability.addAvailability(new Address("Finland", null, null, null));
1883 // share boiler with defined availability
1884 SharingAgent sharingAgent = new SharingAgent(myIdentity);
1886 * add authentication information
1888 String username = "senni";
1889 String password = "12345";
1891 // for now using HTTP basic authentication, i.e., using username:password combination.
1892 sharingAgent.setHTTPBasicAccessAuthenticationCredentials(username, password);
1895 boolean addAvailabilitySuccessful = sharingAgent.share(myIdentity, availability) != null;
1896 if ( !addAvailabilitySuccessful ) {
1897 System.out.println(" ..Adding availability failed.");
1900 System.out.println(" ..Adding availability successful. ");
1903 // search for available devices with power capacity..
1904 Entity entity = new Device();
1905 Capacity capacity = new Capacity();
1906 capacity.setQuantity(RESOURCE.POWER);
1907 entity.addCapacity(capacity);
1909 // ..that are available for control from now on for at least 3 hours..
1910 Availability av = new Availability();
1911 Date currentDateTime = new Date();
1912 av.setTemporalContext(currentDateTime, Tools.add(currentDateTime, 0, 0, 0, 3, 0, 0));
1914 // ..with maximum price of 1.8 euros per hour
1915 Offering offer = new Offering();
1916 PriceSpecification ps = new UnitPriceSpecification();
1917 ps.setCurrency("EUR");
1918 ps.setCurrencyValue(1.8);
1919 offer.addPriceSpecification(ps);
1920 SomeItems si = new SomeItems(RESOURCE.SERVICESUBSCRIPTION, null, null, null);
1921 si.setDuration(0, 0, 0, 1, 0, 0);
1922 offer.addIncludes(si);
1924 // SharingAgent searchAgent = new SharingAgent("http://acme.com/test/searcher");
1925 // boolean foundBoiler = false;
1926 // java.util.List<Entity> found = searchAgent.search(entity, av, offer);
1927 // for ( Entity e : found ) {
1928 // if ( boiler.getIdentifierUri().equals(e.getIdentifierUri()) ) {
1929 // foundBoiler = true;
1932 // if ( !foundBoiler ) {
1933 // System.out.println(" ..Error: could not find boiler using sharing agent!");
1934 // testFailed = true;
1936 // System.out.println(" ..Searching shared entity successful. ");
1939 // // remove sharing
1940 // boolean deregistrationSuccessful = sharingAgent.removeSharing(myIdentity);
1941 // if ( !deregistrationSuccessful ) {
1942 // System.out.println(" ..Removing availability failed.");
1944 // System.out.println(" ..Removing sharing successful. ");
1947 // // search again for available devices to make sure it is not found anymore
1948 // foundBoiler = false;
1949 // found = searchAgent.search(entity, av, offer);
1950 // for ( Entity e : found ) {
1951 // if ( boiler.getIdentifierUri().equals(e.getIdentifierUri()) ) {
1952 // foundBoiler = true;
1955 // if ( foundBoiler ) {
1956 // System.out.println(" ..Error: found boiler even though its sharing should be removed!");
1957 // testFailed = true;
1959 // System.out.println(" ..Confirmed removing sharing successful. ");
1962 // if ( testFailed ) {
1963 // System.out.println("TestSequence.testAvailability() FAILED");
1966 // System.out.println("TestSequence.testAvailability() passed");
1972 public void simpleSignatureVerificationTest()
1974 String signature = "r6mUVMZyGD//o7zFAttovTQwDxD3Wx/uvmDfTZTJQ2MZt9iQYaBHRMbFS4eY3O3erwf12T1v5KJR+CbbPyFvjNReoGVn6TUWNxe7mYf0Oqp38qxFnGDH2c/7wP/G1gqbAu3QConw2be7jCdWNV+YTaf28w4zB5S5O6Ig3J8OwAZdbTWjYMpWOtYzcZa4wPwDSO/QZ948mKEHSIOXcGqt1GZxn3cmFkwfkASr0hT//Y1PRZKUamZpXhViZZLeE0TfwhRhKcMyOzYk5Ht2kZKaKKETEZ4aMf6wKF6bMwG/ud70Z5X8DVBZ3uS7b8+kND3oYhQvAl/ayWSWaNvi18e4pA==";
1976 String content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in lectus at sem commodo venenatis. Fusce in eros ex. In hac habitasse platea dictumst. Phasellus dignissim, augue vel aliquet pretium, nibh eros tristique est, dignissim aliquet elit justo vel mauris. Vestibulum a posuere nulla. Curabitur aliquam semper sagittis.";
1978 PublicKey pubKey = null;
1979 PrivateKey privKey = null;
1981 pubKey = getPemPublicKey("testkey_public.pem", "RSA");
1982 privKey = getPemPrivateKey("testkey_private.pem", "RSA");
1983 } catch (Exception ex) {
1984 System.out.println("Could not find keys for the test.");
1985 System.out.println(ex);
1988 String refSignature = Crypto.sign(privKey, content);
1989 System.out.println("Reference signature: " + refSignature);
1990 System.out.println("Received signature: " + signature);
1992 boolean signedProperly = false;
1994 signedProperly = Crypto.verifySignature(signature, pubKey, content);
1995 } catch (Exception e) {}
1996 System.out.println("Signature test result: " + signedProperly);
1999 public void printLists()
2001 Calendar calendar = Calendar.getInstance();
2002 calendar.setTime(new Date());
2004 TimeSeries ts = new TimeSeries();
2007 smartapi.rdf.List testList = new OrderedList();
2008 for ( int i = 0; i < 3; i++ ) {
2009 Evaluation e = new Evaluation();
2010 e.setValue(new Variant(i));
2011 e.setInstant(calendar.getTime());
2012 calendar.add(Calendar.DATE, 1);
2013 testList.addItems(e);
2015 ts.setList(testList);
2016 System.out.println("\n-------- orderedlist! -----------\n");
2019 testList = new OrderedList();
2020 for ( int i = 0; i < 3; i++ ) {
2021 testList.addItems(i);
2023 ts.setList(testList);
2024 Evaluation baseObject = new Evaluation();
2025 baseObject.setQuantity(RESOURCE.ENERGYANDWORK);
2026 baseObject.setUnit(RESOURCE.KILOWATTHOUR);
2027 ts.setBaseObject(baseObject);
2028 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2029 ts.setTimeStep("PT1S");
2033 testList = new LinkedList();
2034 for ( int i = 0; i < 3; i++ ) {
2035 Evaluation e = new Evaluation();
2036 e.setValue(new Variant(i));
2037 e.setInstant(calendar.getTime());
2038 calendar.add(Calendar.DATE, 1);
2039 testList.addItems(e);
2041 ts.setList(testList);
2042 System.out.println("\n-------- linkedlist! -----------\n");
2045 testList = new LinkedList();
2046 for ( int i = 0; i < 3; i++ ) {
2047 testList.addItems(i);
2049 ts.setList(testList);
2050 ts.setBaseObject(baseObject);
2051 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2052 ts.setTimeStep("PT1S");
2053 System.out.println("\n--------also linkedlist! -----------\n");
2058 testList = new NudeList();
2059 for ( int i = 0; i < 3; i++ ) {
2060 Evaluation e = new Evaluation();
2061 e.setValue(new Variant(i));
2062 e.setInstant(calendar.getTime());
2063 calendar.add(Calendar.DATE, 1);
2064 testList.addItems(e);
2066 ts.setList(testList);
2067 System.out.println("\n-------- nudelist! -----------\n");
2070 testList = new NudeList();
2071 for ( int i = 0; i < 3; i++ ) {
2072 testList.addItems(i);
2074 ts.setList(testList);
2075 ts.setBaseObject(baseObject);
2076 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2077 ts.setTimeStep("PT1S");
2081 testList = new ItemizedList();
2082 for ( int i = 0; i < 3; i++ ) {
2083 Evaluation e = new Evaluation();
2084 e.setValue(new Variant(i));
2085 e.setInstant(calendar.getTime());
2086 calendar.add(Calendar.DATE, 1);
2087 testList.addItems(e);
2089 ts.setList(testList);
2090 System.out.println("\n-------- itemizedlist! -----------\n");
2093 testList = new ItemizedList();
2094 for ( int i = 0; i < 3; i++ ) {
2095 testList.addItems(i);
2097 ts.setList(testList);
2098 ts.setBaseObject(baseObject);
2099 ts.setTemporalContext(new TemporalContext(Tools.stringToDate("2017-02-17T15:30:50.000")));
2100 ts.setTimeStep("PT1S");
2105 * Testing serialization and parsing of cross-linked objects
2108 public boolean serializeParseLoopTest()
2110 System.out.println("Running serializeParseLoopTest..");
2111 String rootId = "http://serializeParseLoopTest.test/root";
2112 String requestId = "http://serializeParseLoopTest.test/request";
2113 String entityId = "http://serializeParseLoopTest.test/entity";
2114 String rootProp = NS.SMARTAPI + "testPropertyRoot";
2115 String loopProp = NS.SMARTAPI + "testPropertyLoop";
2116 String selfRefProp = NS.SMARTAPI + "testPropertySelfRef";
2118 Entity root = new Entity(rootId);
2119 Request r = new Request(requestId);
2120 Entity e = new Entity(entityId);
2121 root.add(rootProp, r);
2123 r.newActivity().addEntity(e);
2125 // also make one link to self
2126 e.add(selfRefProp, e);
2128 String rdf = Tools.toString(root);
2129 System.out.println("serialization successful");
2131 System.out.println(rdf);
2133 Entity parsedRoot = (Entity)Tools.toObj(rdf);
2134 System.out.println("parsing successful");
2136 System.out.println(Tools.toString(parsedRoot));
2137 // test if content is still valid
2138 Request r2 = parsedRoot.getFirstAs(Request.class, rootProp);
2139 Entity e2 = r2.getFirstActivity().getEntities().get(0);
2140 if ( !(r2.getIdentifierUri().equals(e2.getFirstAs(Obj.class, loopProp).getIdentifierUri())) ) {
2141 System.out.println("serializeParseLoopTest FAILED!");
2144 if ( !(e2.getIdentifierUri().equals(e2.getFirstAs(Obj.class, selfRefProp).getIdentifierUri())) ) {
2145 System.out.println("serializeParseLoopTest FAILED!");
2148 System.out.println("content check successful");
2149 } catch ( Exception e ) {
2150 System.out.println("serializeParseLoopTest FAILED!");
2151 e.printStackTrace();
2154 System.out.println("serializeParseLoopTest passed");
2158 public boolean identifierManagementTest()
2160 System.out.println("Running identifierManagementTest..");
2161 String domain = "asema.com";
2162 String systemId = "iotc/123";
2163 String objId = "/obj%567&/>qwerty/";
2166 Entity e = new Entity(Tools.createIdentifierUri(domain, systemId, objId));
2167 System.out.println("identifier creation successful");
2169 String domain2 = e.getDomain();
2170 String systemId2 = e.getSystemIdentifier();
2171 String objId2 = e.getObjectIdentifier();
2172 String secondObjetcId = e.getObjectIdentifier(2);
2173 System.out.println("domain: " + domain2);
2174 System.out.println("systemId: " + systemId2);
2175 System.out.println("objectId: " + objId2);
2176 System.out.println("secondObjetcId: " + secondObjetcId);
2177 System.out.println("identifier partition successful");
2178 if ( domain.equals(domain2) ) {
2179 System.out.println("domain correct");
2181 System.err.println("domain match FAILED!");
2184 if ( systemId.equals(systemId2) ) {
2185 System.out.println("systemId correct");
2187 System.err.println("systemId match FAILED!");
2190 if ( objId.equals(objId2) ) {
2191 System.out.println("objId correct");
2193 System.err.println("objId match FAILED!");
2196 if ( secondObjetcId == null ) {
2197 System.out.println("secondObjetcId correct");
2199 System.err.println("secondObjetcId match FAILED!");
2202 } catch ( Exception e ) {
2203 e.printStackTrace();
2205 System.out.println("identifierManagementTest passed");
2209 public void readAndWriteObjectTest()
2211 System.out.println("Running readAndWriteObjectTest..");
2212 String domain = "asema.com";
2213 String systemId = "iotc123";
2214 String objId = "lamp";
2216 Device d = new Device(Tools.createIdentifierUri(domain, systemId, objId));
2218 InterfaceAddress itf = Factory.createInterface("http://asema.com:8082/smartapi/v1.0e1.0/access/nonstandard");
2220 ValueObject vo = new ValueObject(NS.SMARTAPI + "Brightness", RESOURCE.PERCENT, null, null, "smartapi:Actuator", "smartapi:Dimmer");
2221 d.addValueObject(vo);
2223 ValueObject vo2 = new ValueObject(NS.SMARTAPI + "Powered", DATATYPE.BOOLEAN, null, null, "smartapi:Actuator", "smartapi:PowerSwitch");
2224 d.addValueObject(vo2);
2226 ValueObject vo3 = new ValueObject(null, null, DATATYPE.STRING, "String message shown on lamp screen, use the lamp keyboard to change the message", "smartapi:Sensor");
2227 d.addValueObject(vo3);
2229 Activity aRead = Factory.createStandardReadActivity(itf, vo, vo2, vo3);
2230 d.addCapability(aRead);
2231 Activity aReadts = Factory.createStandardReadTimeSeriesActivity(itf, vo, vo2);
2232 d.addCapability(aReadts);
2233 Activity aWrite = Factory.createStandardWriteActivity(itf, vo, vo2);
2234 d.addCapability(aWrite);
2235 Activity aWritets = Factory.createStandardWriteTimeSeriesActivity(itf, vo);
2236 d.addCapability(aWritets);
2239 // debug print device description
2242 HttpClient client = new HttpClient();
2243 // enable debug mode to see printout of uri and request body
2244 client.debugMode(true);
2245 // just some random temporal context
2246 TemporalContext tcx = new TemporalContext(Tools.add(new Date(), 0, 0, 0, -6, 0, 0), new Date());
2248 // test call to read whole lamp device object
2249 client.getObject(d);
2250 // test call to read brightness value object time series data
2251 client.getValueObject(d, tcx, d.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness"), d.getFirstValueObjectByQuantity((NS.SMARTAPI + "PowerOnState")));
2252 // test call to write time series data to lamp
2253 client.setObject(d, new TimeSeries());
2254 // test call to write brightness value
2255 d.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").setValue(80);
2256 client.setValueObject(d, d.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness"));
2258 } catch ( Exception e ) {
2259 System.err.println("Exception in readAndWriteObjectTest. It is normal if it is caused by network problem because there is no server to actually respond for these requests.");
2260 e.printStackTrace();
2265 * See values changing by reloading page on browser:
2266 * http://seas.asema.com/webapps/SimpleRW/API/smartapi/v1.0e1.0/access
2269 public boolean standardRWtest()
2271 System.out.println("Running standard RW test against SimpleRW servlet...");
2273 // search for SimpleRW device, should find one
2274 for ( Entity e : SearchAgent.searchByNameAndType(SmartAPI.getMyIdentity(), 500, new String[]{"SimpleRW"}, new String[]{RESOURCE.DEVICE}) ) {
2279 ValueObject brightness = e.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness");
2280 ValueObject powerOnState = e.getFirstValueObjectByQuantity(NS.SMARTAPI + "Powered");
2281 HttpClient client = new HttpClient();
2282 // enable debug mode to see printout of uri and request body
2283 //client.debugMode(true);
2284 int brightnessValue = 0;
2285 boolean powerValue = true;
2287 // fetch brightness value
2288 Entity updated = client.getValueObject(e, brightness).getEntities().get(0);
2289 brightnessValue = updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").getValueAsInt();
2290 //System.out.println("Read: " + brightnessValue);
2292 // set new brightness value
2293 if ( brightnessValue > 50 ) {
2294 brightnessValue = 30;
2296 brightnessValue = 80;
2299 // send new brightness value
2300 updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").setValue(brightnessValue);
2301 updated = client.setValueObject(e, updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness")).getEntities().get(0);
2303 // fetch brightness value again to see if it changed correctly
2304 updated = client.getValueObject(e, brightness).getEntities().get(0);
2305 int newValue = updated.getFirstValueObjectByQuantity(NS.SMARTAPI + "Brightness").getValueAsInt();
2307 if ( brightnessValue != newValue ) {
2308 System.err.println("Standard RW test failed. Value (brightness) was not set correctly!");
2312 // fetch power on state value
2313 updated = client.getValueObject(e, powerOnState).getEntities().get(0);
2314 powerValue = updated.getFirstValueObjectByQuantity(RESOURCE.POWERED).getValueAsBoolean();
2316 // set new power on value
2317 powerValue = !powerValue;
2319 // send new power on state value
2320 updated.getFirstValueObjectByQuantity(RESOURCE.POWERED).setValue(powerValue);
2321 updated = client.setValueObject(e, updated.getFirstValueObjectByQuantity(RESOURCE.POWERED)).getEntities().get(0);
2323 // fetch power on state value
2324 updated = client.getValueObject(e, powerOnState).getEntities().get(0);
2325 boolean newPowerValue = updated.getFirstValueObjectByQuantity(RESOURCE.POWERED).getValueAsBoolean();
2327 if ( powerValue != newPowerValue ) {
2328 System.err.println("Standard RW test failed. Value (power on state) was not set correctly!");
2332 // note that all read timeseries are just generated, not real values and wrote timeseries values
2333 // are not followed by any actions on the server side
2335 // fetch brightness timeseries for the last 5 hours
2336 Date now = new Date();
2337 TimeSeries readBrightnessTS = null;
2339 readBrightnessTS = client.getValueObject(e, new TemporalContext(Tools.add(now, 0, 0, 0, -5, 0, 0), now), brightness).getTimeSeries().get(0);
2340 } catch ( Exception ex ) {
2341 System.err.println("Standard RW test failed. Error while fetching brightness timeseries!");
2345 // debug printing for comparing with the ts seen on browser ui
2346 System.out.println("Read brightness timeseries:");
2347 for ( int count = 0; count < readBrightnessTS.getListSize(); count++ ) {
2348 System.out.print(((ValueObject)readBrightnessTS.getListItem(count)).getValueAsInt() + " ");
2350 System.out.println("\n"); // line break
2352 if ( readBrightnessTS.getListSize() < 1 ) {
2353 System.err.println("Standard RW test failed. Error while fetching brightness timeseries! Zero items in returned list.");
2357 // fetch poweronstate timeseries for the last 5 hours
2358 TimeSeries readPowerOnStateTS = null;
2360 readPowerOnStateTS = client.getValueObject(e, new TemporalContext(Tools.add(now, 0, 0, 0, -5, 0, 0), now), powerOnState).getTimeSeries().get(0);
2361 } catch ( Exception ex ) {
2362 System.err.println("Standard RW test failed. Error while fetching brightness timeseries!");
2366 // debug printing for comparing with the ts seen on browser ui
2367 System.out.println("Read PowerOnState timeseries:");
2368 for ( int count = 0; count < readPowerOnStateTS.getListSize(); count++ ) {
2369 System.out.print(((ValueObject)readPowerOnStateTS.getListItem(count)).getValueAsBoolean() + " ");
2371 System.out.println("\n"); // line break
2373 if ( readPowerOnStateTS.getListSize() < 1 ) {
2374 System.err.println("Standard RW test failed. Error while fetching power on state timeseries! Zero items in returned list.");
2378 // send timeseries command (next 5 hours)
2379 Date end = Tools.add(now, 0, 0, 0, 5, 0, 0);
2380 TemporalContext tcx = new TemporalContext(now, end);
2381 TimeSeries ts = new TimeSeries();
2382 ts.setTemporalContext(tcx);
2384 ts.setList(new smartapi.rdf.OrderedList());
2385 // 1 hour timestep between data values
2386 Duration timeStep = Factory.createDuration(0, 0, 0, 1, 0, 0);
2387 ts.setTimeStep(timeStep.toString());
2388 Random rnd = new Random();
2389 Date currentDate = (Date)now.clone();
2390 ValueObject baseObject = (ValueObject)brightness.clone();
2391 baseObject.setValue((Variant)null);
2392 ts.setBaseObject(baseObject);
2393 while ( currentDate.before(end) ) {
2394 // list items as int
2395 ts.addListItem(rnd.nextInt(101));
2396 timeStep.addTo(currentDate);
2399 // debug printing for comparing with the ts seen on browser ui
2400 System.out.println("Wrote brightness timeseries:");
2401 for ( int count = 0; count < ts.getListSize(); count++ ) {
2402 System.out.print(((ValueObject)ts.getListItem(count)).getValueAsInt() + " ");
2404 System.out.println("\n"); // line break
2406 TimeSeries wroteBrightnessTS = null;
2408 wroteBrightnessTS = client.setValueObject(e, ts, brightness).getTimeSeries().get(0);
2409 } catch ( Exception ex ) {
2410 System.err.println("Standard RW test failed. Error while writing brightness timeserie!");
2414 if ( wroteBrightnessTS.getListSize() < 1 ) {
2415 System.err.println("Standard RW test failed. Error while writing brightness timeserie! Zero items in returned list.");
2419 System.out.println("Standard RW test passed.");
2423 public boolean UnitConversionTest()
2425 System.out.println("Running UnitConversionTest...");
2426 //SmartAPI.setValidationMode(ValidationMode.DONT_UPDATE);
2428 System.out.println("ENERGYPRICE from e/kWh to pound/MWh");
2429 ValueObject vo = new ValueObject(RESOURCE.CURRENCY, RESOURCE.EURO, RESOURCE.ENERGYANDWORK, RESOURCE.KILOWATTHOUR, 0.02);
2431 ValueObject vo2 = UnitConverter.convert(vo, RESOURCE.POUNDSTERLING, RESOURCE.WATTHOUR);
2433 if ( !vo2.getUnit().equals(RESOURCE.POUNDSTERLING) || !vo2.getSecondaryUnit().equals(RESOURCE.WATTHOUR) ||
2434 vo2.getValue().equals(new Variant(0.02)) ) {
2435 System.err.println("EnergyPrice conversion from e/kWh to pound/MWh failed!");
2439 System.out.println("ANGLE from radian to degree");
2440 ValueObject vo3 = new ValueObject(RESOURCE.PLANEANGLE, RESOURCE.RADIAN, 3.14159265);
2442 ValueObject vo4 = UnitConverter.convert(vo3, RESOURCE.DEGREEANGLE);
2444 if ( !vo4.getUnit().equals(RESOURCE.DEGREEANGLE) ||
2445 vo4.getValue().equals(new Variant(3.14159265)) ) {
2446 System.err.println("Angle conversion from radian to degree failed!");
2450 System.out.println("CURRENCY from euro to pound");
2451 ValueObject vo5 = new ValueObject(RESOURCE.CURRENCY, RESOURCE.EURO, 5);
2453 ValueObject vo6 = UnitConverter.convert(vo5, RESOURCE.POUNDSTERLING);
2455 if ( !vo6.getUnit().equals(RESOURCE.POUNDSTERLING) ||
2456 vo6.getValue().equals(new Variant(5)) ) {
2457 System.err.println("Currency conversion from euro to pound failed!");
2461 System.out.println("ENERGY CONSUMPTION from kWh/km to Wh/m");
2462 ValueObject vo7 = new ValueObject(RESOURCE.ENERGYANDWORK, RESOURCE.KILOWATTHOUR, RESOURCE.LENGTH, RESOURCE.KILOMETER, 8);
2464 ValueObject vo8 = UnitConverter.convert(vo7, RESOURCE.WATTHOUR, RESOURCE.METER);
2466 if ( !vo8.getUnit().equals(RESOURCE.WATTHOUR) || !vo8.getSecondaryUnit().equals(RESOURCE.METER) ||
2467 vo8.getValue().asInt() != 8 ) {
2468 System.err.println("Energy consumption conversion from kWh/km to Wh/m failed!");
2472 System.out.println("UnitConversionTest passed.");
2476 public boolean graphTests()
2478 GraphTests gt = new GraphTests();
2479 return gt.runTests();
2483 * Tests serialization and parsing of objects where signing has been done to multiple levels in objects,
2484 * resulting in several multipart objects
2486 public boolean recursiveMultipartTest()
2488 System.out.println("Running recursive multipart test...");
2489 PublicKey pubKey = null;
2490 PrivateKey privKey = null;
2491 Transaction transaction = null;
2495 pubKey = getPemPublicKey("testkey_public.pem", "RSA");
2496 privKey = getPemPrivateKey("testkey_private.pem", "RSA");
2497 transaction = Factory.createTransaction("http://www.my.org/sender");
2498 req = Factory.createRequest("http://www.my.org/me");
2499 } catch (Exception ex) {
2500 System.out.println("Could not find keys for the test.");
2501 System.out.println(ex);
2504 Entity e = new Entity("http://www.my.org/entity");
2505 Offering o = new Offering();
2509 transaction.setSigner("http://www.my.org/signer");
2510 transaction.setNotarizedObject(e);
2511 transaction.sign(privKey);
2513 Activity a = new Activity("http://www.my.org/activity");
2514 a.setTransaction(transaction);
2515 a.setMethod(RESOURCE.WRITE);
2520 // The data is now ready to be serialized into the message.
2521 ImmutablePair<String, String> serializedRequest = Tools.serializeRequest(req, SERIALIZATION.TURTLE);
2522 System.out.println("REQUEST:\n" + serializedRequest.getLeft());
2524 Request rr = Tools.parseRequest(serializedRequest.getLeft(), serializedRequest.getRight());
2525 System.out.println("Resulting Activity: " + rr.getFirstActivity());
2526 Transaction tt = (Transaction)rr.getFirstActivity().getTransaction();
2527 System.out.println("Resulting Transaction: " + tt);
2528 System.out.println("Resulting Object: " + tt.getNotarizedObject());
2529 System.out.println("Resulting Offerings: " + tt.getNotarizedObject().getOfferings());
2530 return tt.getNotarizedObject().getOfferings().size() > 0;
2533 public boolean conceptValidationTest()
2535 System.out.println("Running concept validation test...");
2538 Service s = new Service("http://concept.validation.test/");
2539 // add undefined concept
2540 s.addType(NS.SMARTAPI + "MyType");
2541 s.add(PROPERTY.METHOD, new Obj(RESOURCE.READ));
2542 // add illegal value type (string instead of resource)
2543 s.add(PROPERTY.METHOD, RESOURCE.READ);
2544 // add undefined concept
2545 s.add(PROPERTY.METHOD, new Obj(NS.SMARTAPI + "MyMethod"));
2546 // add undefined property
2547 s.add(NS.SMARTAPI + "myProp", "helloy");
2548 s.setName("Concept validation test Service ");
2549 s.setDescription("Sample service description for concept validation test.");
2550 s.setInterface(Factory.createStandardInterface("acme.com"));
2551 s.addCapability(Factory.createStandardReadActivity("http://acme.com/service/Cread"));