/* ck_cov.aml /* /* PURPOSE: Checks that a cover meets BCE standards. If used with the /* FIX option, it will attempt to rectify easily fixable problems /* /* On return, variable .ck_cov_stat indicates the degree of the /* most severe error encountered: SEVERE, ERROR, WARNING, or null /* if no problems were found. /* /* Output to the screen has some unavoidableextra dreck from /* some of the Arc commands; but if output is directed to a /* watch file, the watch file will be free of the extra /* dreck. /* /* If there is no watch file and the FIX option is given, /* this will create a watch file, ck_cov*.log /* /* Requires helper files ck_cov.pl and ck_cov_fix.aml, /* as well as getsys.* /* /* 08-may-1997 tglover Created /* 16-may-1997 tglover Added "FIXable" notes to messages /* 17-jul-1997 tglover Added check for universe poly labeleld; /* disabled polygon build in FIX /* 21-jul-1997 tglover Added check for unpopulated TAG/FCODEs /* 22-jul-1997 tglover Added check for all FCODEs recognized /* 24-jul-1997 tglover Modified projection check -- since arc /* sets its &desc variables differently /* on different boxes despite running the /* same version of arc! /* 05-aug-1997 tglover Bug fix related to FCODE lookups /* 05-dec-1997 bmackenz Bug fix related to FCODE lookups /* 05-apr-2001 bmackenz Changed message on missing _TAG field, and changed /* the return value from ERROR to WARNING &args fullcov fixuparg /* must be run from arc &if %:PROGRAM% ne ARC &then &do &sv .ck_cov_stat = ERROR &return &error %AML$FILE% must be run in Arc &end &severity &error &routine BAILOUT &sv messages_sav = [show &messages] &if [show &echo] ne &ON &then &messages &off &info &sv fullscreen_sav = [show &fullscreen] &fullscreen &nopaging /* user must pass in the name of a cover &if not [variable fullcov] or [null %fullcov%] &then &do &sv .ck_cov_stat = ERROR &call USAGE &end &if not [variable fixuparg] or [null %fixuparg%] &then &sv fixuparg = NOFIX &sv fixuparg = [upcase %fixuparg%] &if %fixuparg% eq FIX &then &sv fixup = .true. &else &if %fixuparg% eq NOFIX &then &sv fixup = .false. &else &do &sv .ck_cov_stat = ERROR &call USAGE &end /* Is there a watch file? If not, make one (if fixing) &if %fixup% and [show &watch] eq &OFF &then &do &sv new_watch_file = .TRUE. &sv watfile = [scratchname -prefix [subst %AML$FILE% .aml] -suffix .log -file] &ty NOTICE: Output for cover %fullcov% going into file %watfile% &watch %watfile% &ty Checking cover %fullcov% with FIX option &end /* does the cover exist? &if not [exists %fullcov% -cover] &then &do &sv .ck_cov_stat = ERROR &call CLEANUP &return &error Cover %fullcov% does not exist &end /* describe the cover - sets numerous DSC$* and PRJ$* vars &describe %fullcov% /* Assume for now that there are no errors &sv .ck_cov_stat = '' /* What is the temporary text file for us to use? &sv tmpfile = [scratchname -prefix xxck_cov -suffix .lst -file] /* What is the helper script (perl) for ck_cov? &sv pl_helper = [subst %aml$fullfile% .aml .pl] /* perl helper script /* What is the aml helper script to fix things? (eg: ck_cov_fix.aml) &sv fix_helper = [subst %aml$fullfile% .aml _fix.aml] /* if fixing, do we own the cover, the workspace & the info directory? &if %fixup% &then &do &sys echo %DSC$FULL_COVER% > %tmpfile% /* ck_cov.pl will test access, return an ownership error msg (or null) &r getsys [quote %pl_helper% ck_fix_access %tmpfile%] &if %.getsys_status% ne 0 &then &do &call BAILOUT &end &else &if not [null %.getsys_stdout%] &then &do /* access privs are not right to alter the cover &sv msg = %.getsys_stdout% &call stop_error &end &end /* check out the cover's name &call CK_NAME /* check out the cover's projection &call CK_PROJECTION /* make sure the topology is clean &call CK_TOPO_CLEAN /* make sure spatial indexes &call CK_TOPO_INDEXED /* check topology INFO files &call CK_TOPO_INFO /* check for _TAG items &call CK_TAGS /* check out the meta file &call CK_META /* clean up & exit &call CLEANUP &return /*---------------------------- /* checks for existence & definition of fcode at all appropriate /* levels of topology. &routine CK_TOPO_INFO &if %dsc$points% > 0 &then &do &sv file = PAT &sv topology = POINT/POLY &call CK_TOPO_ONE_INFO &end &if %dsc$arcs% > 0 &then &do &sv file = AAT &sv topology = ARC &call CK_TOPO_ONE_INFO &end &if %dsc$regionsubclasses% > 0 &then &do &do subclass &list %dsc$regionnames% &sv file = PAT%subclass% &call CK_TOPO_ONE_INFO &end &end &if %dsc$routesystems% > 0 &then &do &do subclass &list %dsc$routenames% &sv file = RAT%subclass% &call CK_TOPO_ONE_INFO &end &end &return &routine CK_TOPO_ONE_INFO /* on entry, %file% is set /* If info file doesn't exist &if not [exists %fullcov%.%file% -info] &then &do &sv msg = [quote not built for %topology% topology (maybe FIXable)] &call severe &if %fixup% &then &do &r %fix_helper% [quote build %topology% topology] build_topo %file% &end &else &return /* nothing more to check in this routine &end /* Check FCODE &if [iteminfo %fullcov%.%file% -info FCODE -exists] &then &do /* Look at the definition &sv fdef = [iteminfo %fullcov%.%file% -info FCODE] &if "%fdef%" ne "10,10,C,0" &then &do &sv msg = [quote FCODE misdefined in .%file%] &call severe &end /* Check if FCODE is indexed &if not [iteminfo %fullcov%.%file% -info FCODE -indexed] &then &do &sv msg = [quote FCODE not indexed in .%file% (FIXable)] &call warning &if %fixup% &then &do &r %fix_helper% [quote index FCODE in .%file%] index_item %file% FCODE &end &end /* Is the FCODE fully populated? &sv item = FCODE &call ck_item_pop /* Check to see if the FCODEs are recognized - what compare to? &call fcode_lut &end &else &do /* No FCODE &sv msg = [quote FCODE missing from .%file% (FIXable)] &call error &if %fixup% &then &do &r %fix_helper% [quote add FCODE to .%file% and index it] add_fcode %file% /* Check whether it is populated.. we know it isn't, because it was /* just created. But, this will generate an error message that it /* isn't. &sv item = FCODE &call ck_item_pop &end &end /* check how AREA is defined (if it exists & there is poly topo) &if %dsc$qtopology% and [iteminfo %fullcov%.%file% -info area -exists] &then &do &sv areabits = [iteminfo %fullcov%.%file% -info area] &if [extract 2 %areabits%] <> 16 &then &do /* width not right &sv msg = [quote has AREA in .%file% width != 16 (FIXable)] &call warning &if %fixup% &then &do &r %fix_helper% [quote fix width of AREA in .%file%] area_width %file% &end &end &end &return /*---------------------------- &routine CK_NAME /* is its name less than or equal to 8 chrs? &if [length %dsc$cover%] > 8 &then &do &sv msg = 'has name longer then 8 characters' &call warning &end /* scale designator - do we recognize it? &sv scale_chr = [quote [locase [substr %dsc$cover% 1 1 ]]] &if not %scale_chr% in {'d', 'i', 'b', 'm', 's', 'q', 'h', 'l', 'f', 't', 'x', 'v', 'w', 'a'} &then &do &sv msg = 'has unrecognized scale designator' &call warning &end /* anything that starts with 'xx' is a bad name since 'xx' is what /* arc starts all its temporary files with &sv s = [quote [locase [substr %dsc$cover% 1 2]]] &if %s% = xx &then &do &sv msg = 'has a very risky name: do not start covers with ''xx''' &call severe &end /* 'core' is always a bad name &if [quote [locase %DSC$COVER%]] eq 'core' &then &do &sv msg = 'has a very risky name: never name anything ''core''' &call severe &end &return /*------------------------------- &routine CK_META /* does a meta file exist? &if not [exists %fullcov%.META -info] &then &do &sv msg = 'has no .META file' &call error &return &end /* meta file must have KEY and VALUE &if not [iteminfo %fullcov%.META -info KEY -exists] or ~ not [iteminfo %fullcov%.META -info VALUE -exists] &then &do &sv msg = '.META is missing KEY or VALUE column' &call severe &return &end /* check out the meta file for required KEY values &call list_on LIST %fullcov%.META KEY &call list_off &r getsys [quote %pl_helper% ck_meta %tmpfile%] &if %.getsys_status% ne 0 &then &do &call BAILOUT &end &else &if not [null %.getsys_stdout%] &then &do /* &sv msg = 'missing required .META KEY values' &sv msg = %.getsys_stdout% &call error &end &return /*--------------------------------- &routine CK_PROJECTION /* check projection & datum &sv msg = /* break this up into three groups since as one /* big expression has 'too many elements' for arc &if [quote %PRJ$XSHIFT%] ne '0' or ~ [quote %PRJ$YSHIFT%] ne '0' or ~ [quote %PRJ$FE%] ne '1000000' or ~ [quote %PRJ$FN%] ne '0' &then &sv msg = 'has non-standard projection shift/offset values' /* note - arc sometimes reports '0***', sometimes '0.000' under identical versions (7.04) &if ( [quote %PRJ$SP1%] ne '50 00 00*****' and [quote %PRJ$SP1%] ne '50 00 00.0000' ) or ~ ( [quote %PRJ$SP2%] ne '58 30 00*****' and [quote %PRJ$SP2%] ne '58 30 00.0000' ) or ~ ( [quote %PRJ$CM%] ne '-126 00 00*****' and [quote %PRJ$CM%] ne '-126 00 00.0000' ) or ~ ( [quote %PRJ$LATORIG%] ne '45 00 00*****' and [quote %PRJ$LATORIG%] ne '45 00 00.0000' ) or ~ [quote %PRJ$LONGORIG%] ne '' &then &sv msg = 'has non-standard projection parameters' &if [quote %PRJ$NAME%] ne 'ALBERS' or ~ ( [quote %PRJ$DATUM%] ne 'NAD83 CNT' and [quote %PRJ$DATUM%] ne 'NAD83' ) or ~ [quote %PRJ$UNITS%] ne 'METERS' or ~ [quote %PRJ$SPHEROID%] ne 'GRS1980' &then &sv msg = 'has non-standard units/projection data' &if not [null %msg%] &then &do &call severe &end /* precision &if [quote %DSC$PRECISION%] ne 'SINGLE' &then &do &sv msg = 'is not single precision' &call warning &end &return /*--------------------------------- /* Prints an ERROR message and stops the program /* on input, the message is in var msg &routine stop_error &call severe /* stop the program &call CLEANUP &return &warning /* Terminate the program /* Prints a SEVERE ERROR message but keeps going /* on input, the message is in var msg &routine severe &ty SEVERE ERROR %fullcov% [unquote %msg%] &sv .ck_cov_stat = SEVERE &return /* Prints an ERROR message but keeps going /* on input, the message is in var msg &routine error &ty ERROR %fullcov% [unquote %msg%] /* Set error level only if at a lower level now &if [null %.ck_cov_stat%] or %.ck_cov_stat% eq WARNING &then &sv .ck_cov_stat = ERROR &return /* Prints a WARNING message and keeps going /* on input, the message is in var msg &routine warning &ty WARNING %fullcov% [unquote %msg%] &if [null %.ck_cov_stat%] &then &sv .ck_cov_stat = WARNING &return /* Prints a friendly notice and keeps going /* on input, the message is in var msg /* This does not affect ck_cov_stat, since these are non-standards issues &routine notice &ty NOTE %fullcov% [unquote %msg%] &return /*------------------------------------ &routine USAGE &ty Usage: &run [subst [locase %AML$FILE%] .aml] {NOFIX|FIX} &call CLEANUP &severity &error &fail &return &error /*------------------------------------ &routine CLEANUP /* cleans up for anyone who wants to exit &if [variable new_watch_file] &then &watch &off &if [variable messages_sav] &then &messages %messages_sav% &if [variable fullscreen_sav] &then &fullscreen %fullscreen_sav% &if [variable tmpfile] &then &sys rm -f %tmpfile% 2> /dev/null &severity &error &fail &return /*------------------------------------ &routine BAILOUT /* something went wrong &ty Problem running %aml$fullfile% %fullcov% &call CLEANUP &return &error /*------------------------------ /* /* Turn listing to the temp file on/off. This is /* important because otherwise, all kinds of junk ends /* up in the watch file (ie, all the LIST stuff. /* Call list_on before LIST commands, then list_off imm after. &routine LIST_ON &sv watch_file = [show &watch] &if [quote %watch_file%] ne '&OFF' &then &sv watch_file = %watch_file% &append &watch &off LISTOUTPUT %tmpfile% INIT &return &routine LIST_OFF LISTOUTPUT SCREEN /* closes list file &watch %watch_file% &return /*------------------------------ /* /* Turn listing to the temp file on/off for watchfile. This is /* important because the entire script may be going to a watch /* file in order to see the error messages. This allows that to /* happen without filling it with output of diagnostic commands /* like nodeerrors /* Call watch_on before commands, then watch_off imm after. &routine WATCH_ON &sv watch_file = [show &watch] &if [quote %watch_file%] ne '&OFF' &then &sv watch_file = %watch_file% &append &watch &off &watch %tmpfile% &return &routine WATCH_OFF &watch &off &watch %watch_file% &return /*------------------------------ /* checks for _TAG in the appropriate info table(s) &routine CK_TAGS /* assumes, on entry, that topo_list is set (??) /* Look in each appropriate info table (the highest topo level) /* PAT if points or polys but no regions &if %DSC$POINTS% > 0 and %DSC$REGIONSUBCLASSES% = 0 &then &do &sv info_ext = PAT &call ck_4_tag &end /* ARCS if arcs but no polys or routes &if %DSC$ARCS% > 0 and %DSC$POLYGONS% = 0 and %DSC$ROUTESYSTEMS% = 0 &then &do &sv info_ext = AAT &call ck_4_tag &end /* regions? check them all &if %DSC$REGIONSUBCLASSES% > 0 &then &do &do subclass &list %DSC$REGIONNAMES% &sv info_ext = PAT%subclass% &call ck_4_tag &end &end /* routes? check them all &if %DSC$ROUTESYSTEMS% > 0 &then &do &do subclass &list %DSC$ROUTENAMES% &sv info_ext = RAT%subclass% &call ck_4_tag &end &end &return &routine CK_4_TAG /* on entry, info_ext is set (to PAT, AAT, RATSUBCLASS, etc) /* assume not found until we find it &sv got_tag = .false. &if [exists %fullcov%.%info_ext% -INFO] &then &do /* get list of info items &do item &list [listitem %fullcov%.%info_ext% -INFO -ALL] /* does this item look like _TAG ? &if %item% lk '*_TAG' &then &do /* get the first part of it &sv start = [subst %item% _TAG] /* does the start match the beg of the cover name? &if [index [upcase %dsc$cover%] %start%] = 1 &then &do /* it matches; a good tag name &sv got_tag = .true. /* It should be indexed &if not [iteminfo %fullcov%.%info_ext% -info %item% -indexed] &then &do &sv msg = [quote %item% not indexed in .%info_ext% (FIXable)] &call warning /* perhaps fix it up &if %fixup% &then &do &r %fix_helper% [quote index %item% in .%info_ext%] ~ index_item %info_ext% %item% &end &end /* check to see if fully populated &sv file = %info_ext% &call ck_item_pop &end &end &end &end /* was it found? If not, an error &if not %got_tag% &then &do &sv msg = [quote missing *_TAG column in .%info_ext% - should exist if features have a unique identifier] &call warning &end &return /*------------------------------ &routine CK_TOPO_INDEXED /* check for spatial indexes in the cover &if %DSC$POINTS% > 0 &then &do /* either points or polygons &if %DSC$QTOPOLOGY% &then &do /* polygons &sv topo = POLYGONS &call ck_4_index &end &else &do &sv topo = POINTS &call ck_4_index &end &end /* regions? &if %DSC$REGIONSUBCLASSES% > 0 &then &do &sv topo = REGIONS &call ck_4_index &end /* arcs? &if %DSC$ARCS% > 0 &then &do &sv topo = ARCS &call ck_4_index &end &return &routine CK_4_INDEX /* checks for one index. %topo% is 'POLYGONS', 'POINTS', etc -- as used in /* DSC$INDEX_* variables /* check non-region topo first, so messages are a little less odd-looking &if %topo% ne REGIONS &then &do &if not [value DSC$INDEX_%topo%] &then &do &sv msg = [quote %topo% not spatially indexed (FIXable)] &call warning &if %fixup% &then &do &r %fix_helper% 'create a spatial index' index_spatial &end &end &end &else &do /* this has region topo &do x = 1 &to %DSC$REGIONSUBCLASSES% &if not [extract %x% %DSC$INDEX_REGIONS%] &then &do &sv subclass = [extract %x% %DSC$REGIONNAMES%] &sv msg = [quote REGION.%subclass% not spatially indexed (FIXable)] &call warning &if %fixup% &then &do &r %fix_helper% 'create a spatial index' index_spatial &end &end &end &end &return /*------------------------------ &routine CK_TOPO_CLEAN /* Check polygons &if %dsc$polygons% > 0 or %dsc$topology_polygons% > 0 &then &do &if %dsc$topology_polygons% ne 2 &then &do &sv msg = 'has polygon topology missing or preliminary (maybe FIXable)' &call severe &if %fixup% &then &do &r %fix_helper% 'build polygon topology' build_topo PAT &end &end &else &do /* Do nodeerrors and labelerrors &call watch_on LABELERRORS %fullcov% NODEERRORS %fullcov% DANGLE &call watch_off /* check for general label errors &r getsys [quote %pl_helper% ck_polys %tmpfile%] &if %.getsys_status% ne 0 &then &do &call BAILOUT &end &else &if not [null %.getsys_stdout%] &then &do &sv msg = 'shows errors from NODEERRORS or LABELERRORS command' &call severe &end /* check for polygon 1 (universe) having a label &r getsys [quote %pl_helper% ck_universe_label %tmpfile%] &if %.getsys_status% ne 0 &then &do &call BAILOUT &end &else &if not [null %.getsys_stdout%] &then &do &sv msg = 'has a label in its universe polygon' &call severe &end &end &end /* check regions &if %dsc$regionsubclasses% > 0 &then &do &do i = 1 &to %dsc$regionsubclasses% &if [extract %i% %dsc$topology_regions%] ne 2 &then &do &sv subclass = [extract %i% %dsc$regionnames%] &sv msg = [quote has region topo missing or prelim, subclass %subclass% (maybe FIXable)] &call severe &if %fixup% &then &do &r %fix_helper% 'build region topology' build_topo PAT%subclass% &end &end &end /* call REGIONERRORS &call watch_on REGIONERRORS %fullcov% &call watch_off &r getsys [quote %pl_helper% ck_regions %tmpfile%] &if %.getsys_status% ne 0 &then &do &call BAILOUT &end &else &if not [null %.getsys_stdout%] &then &do &sv msg = 'shows errors from REGIONERRORS command' &call severe &end &end &return /*------------------------------ /* checks to see if the given item is populated /* (except of course for the universe poly if there is one) /* on entry, /* %item% is the item name (eg, FCODE) /* %fullcov% and %file% are the cover and info file extension /* on exit /* a message will have been given if applicable /* &routine CK_ITEM_POP &call list_on LIST %fullcov%.%file% %item% &call list_off &r getsys [quote %pl_helper% ck_item_pop %tmpfile% ~ %file% %item% %dsc$topology_polygons%] &if %.getsys_status% ne 0 &then &do &call BAILOUT &end &else &if not [null %.getsys_stdout%] &then &do &sv msg = %.getsys_stdout% &call notice &end &return /*----------------------------------------- &routine FCODE_LUT /* check for fcodes in bce{lin|mrk|shd}.lut /* on entry: /* fullcover /* file /* what bce{xxx}.lut shall we look in? &sv infobit = [upcase [substr %file% 1 3]] &if %infobit% = PAT &then &do &if %dsc$topology_polygons% > 0 &then &sv class = SHD &else &sv class = MRK &end &else &if %infobit% = AAT &then &sv class = LIN &else &do &return &end &sv dict_info = $ARCWHSE/BCE%class%.LUT /* find frequencies of fcode in cover's info file &sv test_tmp = [scratchname -info] PULLITEMS %fullcov%.%file% %test_tmp% FCODE END &sv test_sum = [scratchname -info] FREQUENCY %test_tmp% %test_sum% FCODE END END /* Now set up a relate from one to the other &severity &error &ignore RELATE ADD comp %dict_info% INFO FCODE FCODE LINEAR RO ~ &severity &error &routine BAILOUT /* Create a cursor of those that are non-blank & with no match &severity &error &ignore &message &off &all LIST %test_sum% FCODE comp//FCODE CURSOR fcodecur REMOVE &severity &error &routine BAILOUT CURSOR fcodecur DECLARE %test_sum% INFO RO FCODE ne comp//FCODE CURSOR fcodecur OPEN &do &while %:fcodecur.aml$next% &if not [null %:fcodecur.fcode%] and %:fcodecur.frequency% > 0 &then &do &sv msg = FCODE "%:fcodecur.fcode%" (%:fcodecur.frequency%x) in .%file% not in %dict_info% &call notice &end CURSOR fcodecur NEXT &end &message &off &info CURSOR fcodecur CLOSE CURSOR fcodecur REMOVE &if [exist %test_tmp% -info] &then &sv junk = [delete %test_tmp% -info] &if [exist %test_sum% -info] &then &sv junk = [delete %test_sum% -info] &return /*------------------------------------ &routine CLEANUP /* cleans up for anyone who wants to exit &if [variable new_watch_file] &then &watch &off &if [variable messages_sav] &then &messages %messages_sav% &if [variable fullscreen_sav] &then &fullscreen %fullscreen_sav% &do var &list test_tmp test_sum /* delete the info file if it exists &if [variable %var%] &then &do &if [exist [value %var%] -info] &then &do &sv junk = [delete [value %var%] -info] &end &end &end &severity &error &fail &return /*------------------------------------ &routine BAILOUT /* something went wrong &ty Problem running %aml$fullfile% &call CLEANUP &return &error /*------------------------------