2 //=============================================================================
6 * @author Source code used in TAO has been modified and adapted from the codeprovided in the book
7 * @author "Advanced CORBA Programming with C++" by MichiHenning and Steve Vinoski. Copyright 1999. Addison-Wesley
9 * @author MA.Modified for TAO by Mike Moran <mm4@cs.wustl.edu>
11 //=============================================================================
17 //#include <iostream.h>
19 //----------------------------------------------------------------
22 // Generic ostream inserter for exceptions. Inserts the exception
23 // name, if available, and the repository ID otherwise.
25 #if 0 //This inserter may or may not be needed for your ORB.
28 operator<< (ostream
& os
, const CORBA::Exception
& e
)
32 CORBA::TypeCode_var tc
= tmp
.type ();
33 const char * p
= tc
->name ();
43 //----------------------------------------------------------------
45 Controller_impl
* Thermometer_impl::m_ctrl
; // static member
47 // Helper function to read the model string from a device.
54 assert (ICP_get (m_anum
, "model", buf
, sizeof (buf
)) == 0);
55 return CORBA::string_dup (buf
);
58 // Helper function to read the temperature from a device.
66 ICP_get (m_anum
, "temperature", &temp
, sizeof (temp
)
71 // Helper function to read the location from a device.
78 assert (ICP_get (m_anum
, "location", buf
, sizeof (buf
)) == 0);
79 return CORBA::string_dup (buf
);
82 // Helper function to set the location of a device.
86 set_loc (const char * loc
)
89 result
= ICP_set (m_anum
, "location", loc
);
101 assert (ICP_online (anum
) == 0); // Mark device as on-line
103 m_ctrl
->add_impl (anum
, this); // Add self to controller's map
112 m_ctrl
->remove_impl (m_anum
); // Remove self from map
113 ICP_offline (m_anum
); // Mark device as off-line
116 assert (0); // Prevent exceptions from escaping
120 // IDL model attribute.
123 Thermometer_impl::model ()
128 // IDL asset_num attribute.
131 Thermometer_impl::asset_num ()
136 // IDL temperature attribute.
139 Thermometer_impl::temperature ()
144 // IDL location attribute accessor.
147 Thermometer_impl::location ()
152 // IDL location attribute modifier.
155 Thermometer_impl::location (const char * loc
)
160 //----------------------------------------------------------------
162 // Helper function to get a thermostat's nominal temperature.
165 Thermostat_impl::get_nominal_temp ()
169 ICP_get (m_anum
, "nominal_temp", &temp
, sizeof (temp
)
174 // Helper function to set a thermostat's nominal temperature.
178 set_nominal_temp (CCS::TempType new_temp
)
182 // We need to return the previous nominal temperature,
183 // so we first read the current nominal temperature before
186 m_anum
, "nominal_temp",
187 &old_temp
, sizeof (old_temp
)
191 // Now set the nominal temperature to the new value.
192 if (ICP_set (m_anum
, "nominal_temp", &new_temp
) != 0) {
193 // If ICP_set () failed, read this thermostat's minimum
194 // and maximum so we can initialize the BadTemp exception.
195 CCS::Thermostat::BtData btd
;
198 &btd
.min_permitted
, sizeof (btd
.min_permitted
)
202 &btd
.max_permitted
, sizeof (btd
.max_permitted
)
204 btd
.requested
= new_temp
;
205 btd
.error_msg
= CORBA::string_dup (
206 new_temp
> btd
.max_permitted
? "Too hot" : "Too cold"
208 throw CCS::Thermostat::BadTemp (btd
);
218 const char * location
,
219 CCS::TempType nominal_temp
220 ) : Thermometer_impl (anum
, location
)
222 // Base Thermometer_impl constructor does most of the
223 // work, so we need only set the nominal temperature here.
224 set_nominal_temp (nominal_temp
);
227 // IDL get_nominal operation.
230 Thermostat_impl::get_nominal ()
232 return get_nominal_temp ();
235 // IDL set_nominal operation.
239 set_nominal (CCS::TempType new_temp
)
241 return set_nominal_temp (new_temp
);
244 //----------------------------------------------------------------
246 // Helper function for thermometers and thermostats to
247 // add themselves to the m_assets map.
251 add_impl (CCS::AssetType anum
, Thermometer_impl
* tip
)
253 m_assets
[anum
] = tip
;
256 // Helper function for thermometers and thermostats to
257 // remove themselves from the m_assets map.
261 remove_impl (CCS::AssetType anum
)
263 m_assets
.erase (anum
);
266 // IDL list operation.
268 CCS::Controller::ThermometerSeq
*
269 Controller_impl::list ()
271 // Create a new thermometer sequence. Because we know
272 // the number of elements we will put onto the sequence,
273 // we use the maximum constructor.
274 CCS::Controller::ThermometerSeq_var listv
275 = new CCS::Controller::ThermometerSeq (m_assets
.size ());
276 listv
->length (m_assets
.size ());
278 // Loop over the m_assets map and create a
279 // reference for each device.
280 CORBA::ULong count
= 0;
281 AssetMap::iterator i
;
282 for (i
= m_assets
.begin (); i
!= m_assets
.end (); i
++)
283 listv
[count
++] = i
->second
->_this ();
284 return listv
._retn ();
287 // IDL change operation.
292 const CCS::Controller::ThermostatSeq
& tlist
,
296 CCS::Controller::EChange ec
; // Just in case we need it
298 // We cannot add a delta value to a thermostat's temperature
299 // directly, so for each thermostat, we read the nominal
300 // temperature, add the delta value to it, and write
302 for (CORBA::ULong i
= 0; i
< tlist
.length (); i
++) {
303 if (CORBA::is_nil (tlist
[i
]))
304 continue; // Skip nil references
306 // Read nominal temp and update it.
307 CCS::TempType tnom
= tlist
[i
]->get_nominal ();
310 tlist
[i
]->set_nominal (tnom
);
312 catch (const CCS::Thermostat::BadTemp
& bt
) {
313 // If the update failed because the temperature
314 // is out of range, we add the thermostat's info
315 // to the errors sequence.
316 CORBA::ULong len
= ec
.errors
.length ();
317 ec
.errors
.length (len
+ 1);
318 ec
.errors
[len
].tmstat_ref
= tlist
[i
];
319 ec
.errors
[len
].info
= bt
.details
;
323 // If we encountered errors in the above loop,
324 // we will have added elements to the errors sequence.
325 if (ec
.errors
.length () != 0)
329 // IDL find operation
333 find (CCS::Controller::SearchSeq
& slist
)
335 // Loop over input list and look up each device.
336 CORBA::ULong listlen
= slist
.length ();
337 for (CORBA::ULong i
= 0; i
< listlen
; i
++) {
338 AssetMap::iterator where
; // Iterator for asset map
339 int num_found
= 0; // Num matched per iteration
341 // Assume we will not find a matching device.
342 slist
[i
].device
= CCS::Thermometer::_nil ();
344 // Work out whether we are searching by asset,
345 // model, or location.
346 CCS::Controller::SearchCriterion sc
= slist
[i
].key
._d ();
347 if (sc
== CCS::Controller::ASSET
) {
348 // Search for matching asset number.
349 where
= m_assets
.find (slist
[i
].key
.asset_num ());
350 if (where
!= m_assets
.end ())
351 slist
[i
].device
= where
->second
->_this ();
353 // Search for model or location string.
354 const char * search_str
;
355 if (sc
== CCS::Controller::LOCATION
)
356 search_str
= slist
[i
].key
.loc ();
358 search_str
= slist
[i
].key
.model_desc ();
360 // Find first matching device (if any).
361 where
= std::find_if (
362 m_assets
.begin (), m_assets
.end (),
363 StrFinder (sc
, search_str
)
366 // While there are matches...
367 while (where
!= m_assets
.end ()) {
368 if (num_found
== 0) {
369 // First match overwrites reference
371 slist
[i
].device
= where
->second
->_this ();
373 // Each further match appends a new
374 // element to the search sequence.
375 CORBA::ULong len
= slist
.length ();
376 slist
.length (len
+ 1);
377 slist
[len
].key
= slist
[i
].key
;
378 slist
[len
].device
= where
->second
->_this ();
382 // Find next matching device with this key.
383 where
= std::find_if (
384 ++where
, m_assets
.end (),
385 StrFinder (sc
, search_str
)
390 std::cerr
<< "end" << std::endl
;
393 //----------------------------------------------------------------
396 ACE_TMAIN(int argc
, ACE_TCHAR
*argv
[])
400 CORBA::ORB_var orb
= CORBA::ORB_init (argc
, argv
);
402 // Get reference to Root POA.
403 CORBA::Object_var obj
404 = orb
->resolve_initial_references ("RootPOA");
405 PortableServer::POA_var poa
406 = PortableServer::POA::_narrow (obj
.in ());
408 // Activate POA manager
409 PortableServer::POAManager_var mgr
410 = poa
->the_POAManager ();
413 // Create a controller and set static m_ctrl member
414 // for thermostats and thermometers.
415 Controller_impl ctrl_servant
;
416 Thermometer_impl::m_ctrl
= &ctrl_servant
;
418 // Write controller stringified reference to stdout
419 CCS::Controller_var ctrl
= ctrl_servant
._this ();
420 CORBA::String_var str
= orb
->object_to_string (ctrl
.in ());
421 std::cout
<< str
.in () << std::endl
<< std::endl
;
423 // Create a few devices. (Thermometers have odd asset
424 // numbers, thermostats have even asset numbers.)
425 Thermometer_impl
thermo1 (2029, "Deep Thought");
426 Thermometer_impl
thermo2 (8053, "HAL");
427 Thermometer_impl
thermo3 (1027, "ENIAC");
429 Thermostat_impl
tmstat1 (3032, "Colossus", 68);
430 Thermostat_impl
tmstat2 (4026, "ENIAC", 60);
431 Thermostat_impl
tmstat3 (4088, "ENIAC", 50);
432 Thermostat_impl
tmstat4 (8042, "HAL", 40);
437 catch (const CORBA::Exception
& e
) {
438 std::cerr
<< "Uncaught CORBA exception: "
444 assert (0); // Unexpected exception, dump core