Wednesday, February 6, 2008

CASE Tool out of synch with your actual datamodel

It is possible that your CASE Tool representation of your datamodel might not accurately reflect the actual datamodel you have in your database. This happened to me recently when I discovered that some CASE work I had done in my own development environment had touched more objects than I was working with when I did a CASE Archive. When I loaded the CASE archive into the production database I had not noticed that it also updated some other objects with an older version of the CASE definition.

This was not a problem until someone tried to apply changes for the "unknowingly-touched" CASE object and it introduced some confusion into the production environment. Well, we resolved the issue but then had the question... How do we ensure that the CASE Tool accurately represents the state of the datamodel?

The answer to that question: "Reverse Engineer"

Here are some tips that will help you to reverse engineer a CASE model.
  • read the Smallworld Case Tutorial help "Reverse engineering from the Gis dataset"
  • an important thing to note is that you need to do the reverse engineer action into an empty CASE partition. Use a procedure such as create_database() to create new "empty" case.ds and case_dd.ds files and then update your Case SOC to point to these new .ds files
  • you should also temporarily keep your "old" case.ds and case_dd.ds files. Do this by creating a new SOC (:old_case) that has a :case dataset that points to these old ds files.
  • when you perform the reverse engineer action you will see that the graphics for relationships and drafting_* objects are not visible in the new CASE. You will also see that the CASE objects are not grouped together the way you had them in the original CASE tool. That is because the Gis dataset does not keep information about CASE graphics in its data dictionary.
  • I use a script like the following one to "recover" some of my description geometries from the "old" CASE tool into the new recently-reverse-engineered CASE tool. (Be sure that you have a handle to both the old and new CASE tools for this).

_local new_case_v << gis_program_manager.cached_dataset(:case)
_local old_case_v << gis_program_manager.cached_dataset(:old_case)

_local old_drafting_coll, new_drafting_coll , geometries , properties , new_rec

write("creating CASE drafting_* objects...")
_for drafting_table_name _over {:drafting_lines,:drafting_areas,:drafting_points,:drafting_texts}.fast_elements()
_loop
old_drafting_coll << old_case_v.collections[drafting_table_name]
new_drafting_coll << new_case_v.collections[drafting_table_name]

_for old_rec _over old_drafting_coll.fast_elements()
_loop
properties << property_list.new()

new_rec << new_drafting_coll.insert(old_rec)

_for a_geom _over old_rec.geometries().fast_elements()
_loop
properties[a_geom.app_type] << a_geom
_endloop

_if properties.empty?
_then
_continue
_endif

record_transaction.new_update(new_rec,properties).run()
_endloop
_endloop

_local new_case_coll << new_case_v.collections[:sw_gis!case_object]
_local old_case_coll << old_case_v.collections[:sw_gis!case_object]

write("updating CASE Object geometries...")
_for new_co _over new_case_coll.fast_elements()
_loop
_if (old_co << old_case_coll.select(predicate.eq(:name,new_co.name)).an_element()) _is _unset
_then
show("skipping ",new_co.name)
_continue
_endif
show(old_co,new_co)

record_transaction.new_update(new_co,property_list.new_with(:outline,old_co.outline,
:position,old_co.position)).run()
_endloop

_local new_case_coll << new_case_v.collections[:sw_gis!case_relationship]
_local old_case_coll << old_case_v.collections[:sw_gis!case_relationship]

write("redrawing CASE relationship geometries...")
_for new_co _over new_case_coll.fast_elements()
_loop
_if (old_co << old_case_coll.select(predicate.eq(:object_info,new_co.object_info)).an_element()) _is _unset
_then
show("skipping ",new_co.object_info)
_continue
_endif

record_transaction.new_update(new_co,property_list.new_with(:centreline,old_co.centreline,
:end1,old_co.end1,
:end2,old_co.end2,
:label,old_co.label)).run()
_endloop

No comments: