multiworldclock/multiworldclock.c
#include "SCA.h"
#include "SDO.h"
static DATAOBJECT assembleBaseWorldclockRequest(char *city, int hour,
char *cityToRequestTypeFor);
static DATAOBJECT extractResultTime(DATAOBJECT worldclockResponse);
DATAOBJECT getLocalTimesForCities(DATAOBJECT request) {
SDOFACTORY df = getDataFactory();
SDOTYPE requestType =
findType(df,
"http://www.example.com/multiworldclock.xsd",
"worldclockRequest");
SDOPROPERTY requestTimeProp =
getTypePropertyByName(requestType, "localTime");
DATAOBJECT requestTimeObj = getDataObject(request, requestTimeProp);
SDOPROPERTY cityProp =
getTypePropertyByName(getPropertyType(requestTimeProp), "city");
SDOPROPERTY hourProp =
getTypePropertyByName(getPropertyType(requestTimeProp), "hour");
char* requestCity = getCString(requestTimeObj, cityProp);
int requestTime = getInt(requestTimeObj, hourProp);
SDOPROPERTY otherCitiesProp =
getTypePropertyByName(requestType, "cityToRequestTimeFor");
SDOLIST otherCities = getList(request, otherCitiesProp);
// Locate service reference to invoke
SCAREF worldclockServiceRef;
token_t worldclockServiceRefToken;
worldclockServiceRef = &worldclockServiceRefToken;
int compCode;
int reason;
SCAGetReference("worldclock", worldclockServiceRef, &compCode, &reason);
// TODO: handle error
SDOLIST resultList = listAlloc();
for (int i = 0; i < getCountList(otherCities); i++) {
int compCode, reason;
DATAOBJECT otherCity = getDataObjectList(otherCities, i);
char *otherCityStr = getCString(otherCity, otherCitiesProp);
// assemble (base, single-city) worldclockRequest for each requested
// city in list
DATAOBJECT baseWorldclockRequest =
assembleBaseWorldclockRequest(requestCity, requestTime, otherCityStr);
DATAOBJECT baseWorldclockResponse;
SCAInvoke(worldclockServiceRef, "getLocalTimeForCity",
0, baseWorldclockRequest,
0, &baseWorldclockResponse,
&compCode, &reason);
// handle error: skip a "worldclock-fault" response
// indicating an unknown city to request time for,
// while keeping reporting results for known cities;
// other errors will terminate the service invocation
// and propgagte as failure of the aggregated service
// as a whole
if (compCode != SCACC_OK) {
DATAOBJECT faultObj = doAlloc(df,
"http://www.w3.org/2001/XMLSchema",
"anyType");
size_t buflen = 0;
char *faultName;
SCAGetFaultMessage(worldclockServiceRef,
&buflen,
&faultName,
faultObj,
&compCode, &reason);
if (strcmp("worldclock-fault", faultName)) {
DATAOBJECT faultResponse = doAlloc(df,
"http://www.w3.org/2001/XMLSchema",
"anyType");
setCStringByName(faultResponse,
"faultstring",
"unrecognized city name");
setCStringByName(faultResponse,
"faultcode",
"soap:Client");
SCASetFaultMessage("worldclock",
"getLocalTimeForCities",
"worldclock-fault",
0,
faultResponse,
&compCode,
&reason);
return 0;
}
continue;
}
// dig out result (city, hour) pair,
// re-assemble, and append to aggregate result
DATAOBJECT multiWorldclockTime = extractResultTime(baseWorldclockResponse);
appendDataObjectList(resultList, multiWorldclockTime);
}
// construct aggregate response
SDOTYPE multiWorldclockResponseType =
findType(df,
"http://www.example.com/multiworldclock.xsd",
"worldclockResponse");
SDOPROPERTY multiWorldclockResponseTimeProp =
getTypePropertyByName(multiWorldclockResponseType, "remoteTime");
DATAOBJECT multiWorldclockResponse =
doAllocByType(getDataFactory(), multiWorldclockResponseType);
setList(multiWorldclockResponse, multiWorldclockResponseTimeProp, resultList);
return multiWorldclockResponse;
}
// returns a request obj for base (non-multi) worldclock service
static DATAOBJECT assembleBaseWorldclockRequest(char *city, int hour, char *cityToRequestTimeFor) {
SDOFACTORY df = getDataFactory();
SDOTYPE baseWorldclockRequestType =
findType(df,
"http://www.example.com/worldclock.xsd",
"worldclockRequest");
SDOTYPE baseWorldclockRequestTimeType =
findType(df,
"http://www.example.com/worldclock.xsd",
"time");
DATAOBJECT baseWorldclockRequest =
doAllocByType(getDataFactory(), baseWorldclockRequestType);
SDOPROPERTY baseWorldclockRequestTimeProp =
getTypePropertyByName(baseWorldclockRequestType, "local-time");
DATAOBJECT baseWorldclockRequestTime =
doAllocByType(getDataFactory(), baseWorldclockRequestTimeType);
setCStringByName(baseWorldclockRequestTime, "city", city);
setIntByName(baseWorldclockRequestTime, "hour", hour);
setDataObject(baseWorldclockRequest, baseWorldclockRequestTimeProp,
baseWorldclockRequestTime);
setCStringByName(baseWorldclockRequest, "city-to-request-time-for", cityToRequestTimeFor);
return baseWorldclockRequest;
}
DATAOBJECT extractResultTime(DATAOBJECT worldclockResponse) {
SDOFACTORY df = getDataFactory();
SDOTYPE responseType = findType(df,
"http://www.example.com/worldclock.xsd",
"worldclockResponse");
SDOTYPE timeType = findType(df,
"http://www.example.com/worldclock.xsd",
"time");
SDOPROPERTY responseTimeProp = getTypePropertyByName(responseType, "remote-time");
DATAOBJECT responseTime = getDataObject(worldclockResponse, responseTimeProp);
char *city = getCStringByName(responseTime, "city");
int hour = getIntByName(responseTime, "hour");
SDOTYPE multiworldclockTimeType = findType(df,
"http://www.example.com/multiworldclock.xsd",
"time");
DATAOBJECT multiworldclockTime =
doAllocByType(getDataFactory(), multiworldclockTimeType);
// set city, hour in result obj
SDOPROPERTY multiworldclockTimeCityProp =
getTypePropertyByName(multiworldclockTimeType, "city");
SDOPROPERTY multiworldclockTimeHourProp =
getTypePropertyByName(multiworldclockTimeType, "hour");
setCString(multiworldclockTime, multiworldclockTimeCityProp, city);
setInt(multiworldclockTime, multiworldclockTimeHourProp, hour);
return multiworldclockTime;
}