<%BANNER%>

Extracting semantics from legacy sources using reverse engineering of Java code with the help of visitor patterns

University of Florida Institutional Repository
xml version 1.0 encoding UTF-8
REPORT xmlns http:www.fcla.edudlsmddaitss xmlns:xsi http:www.w3.org2001XMLSchema-instance xsi:schemaLocation http:www.fcla.edudlsmddaitssdaitssReport.xsd
INGEST IEID E20110109_AAAAZA INGEST_TIME 2011-01-10T00:52:39Z PACKAGE UFE0001210_00001
AGREEMENT_INFO ACCOUNT UF PROJECT UFDC
FILES
FILE SIZE 31697 DFID F20110109_AACYKD ORIGIN DEPOSITOR PATH topsakal_o_Page_090.QC.jpg GLOBAL false PRESERVATION BIT MESSAGE_DIGEST ALGORITHM MD5
954f13d250da98ab2bf8e35c83b02ae2
SHA-1
e115b416b31886e056280aec4ae354a1b70023da
83892 F20110109_AACYJP topsakal_o_Page_023.jpg
99c2d3b5b5d4fde4ebcc64952639d59a
801e40a354372c97801c5823ca7766ba5ae4c20c
106412 F20110109_AACYKE topsakal_o_Page_035.jp2
3d6fee4b4fec3d6e8ca7a97f6a7cc9ba
729b8f29738be3a09f543b5e693add669b0136c5
18048 F20110109_AACYJQ topsakal_o_Page_104.QC.jpg
c98eb70b4083e92795983acea88c84af
755ca222474f72aa655349e1b95660d47c33b5bb
90581 F20110109_AACYKF topsakal_o_Page_096.jp2
fe7d5aede22c09c169060fa6245fd85b
ffc6a63bd8e044138f62ceb000fb3acf8a49e7fe
108655 F20110109_AACYJR topsakal_o_Page_033.jp2
69cb8ac0b6d2e9d3b3fec29484816506
cc8a01e883746fbf323cc7dd9c10adf4514cafc7
1712 F20110109_AACYKG topsakal_o_Page_051.txt
26bf8a619337d521a0fb7f1c0bc5de03
6d7b77f432a48b5842a01cbf88cdfaac7ccdd29e
1861 F20110109_AACYJS topsakal_o_Page_032.txt
60c39d05ffb7e6d2656d85b14a1c89a9
7683d274c8b3d1283f765f43f279d9467e980a4f
5826 F20110109_AACYKH topsakal_o_Page_109thm.jpg
10f62d0ac6188e566c470c935c4ca93e
9c3fc86e2ebed777a6fd7ec7baad17b7dc8aa27e
26346 F20110109_AACYJT topsakal_o_Page_021.QC.jpg
c0b253ee5c2a4bc0261dda44c794f77c
1fd8924a3071d697b6251e1b679bd3f901b36b80
5443 F20110109_AACYKI topsakal_o_Page_005thm.jpg
468c843c6f2b99d25e5e6a1c0ae20afe
2752a6b9cd1136b33c09eabfae46c28719386e0b
91211 F20110109_AACYJU topsakal_o_Page_032.jpg
f104c98adeec6ba840fd2cc6c01c56f6
f50233b6a078f37a3cbb70b15d4f8731841114a2
425 F20110109_AACYKJ topsakal_o_Page_108.txt
10f9ea0ba25639a405b008c9fa6b0d0b
707b95bd4bd9ebe3c97cf0557e7f28e6e813dbb2
25188 F20110109_AACYJV topsakal_o_Page_083.QC.jpg
88d7a76d0c20c6b948f25f18368fdd13
ba10c9aacea98e0edf4578291dc500982e88f42a
4748 F20110109_AACYKK topsakal_o_Page_113thm.jpg
4fcdf20e3a279d9fd8cae7f50370797e
8045bca574e7b616bedc525dbda59841d2772cb1
99554 F20110109_AACYJW topsakal_o_Page_048.jpg
876010c084f5e5c1aa97f38ea4a7f85b
176362b058fa5ff3a78804f6875951b12da1f03e
7401 F20110109_AACYKL topsakal_o_Page_128thm.jpg
0477390a06f56ee61007c1fa3f719df1
3d04e3319939dad88cda16552298d4cd77bc25d7
2358 F20110109_AACYJX topsakal_o_Page_003.QC.jpg
8213f6df3cb43d1e6c60ce0b27bc89b9
4a9db1160e37cb355f5c17b56187a8a1ea9628ec
1053954 F20110109_AACYLA topsakal_o_Page_055.tif
9121d06bc24112d6c1d7805685263707
107b6188db1065ebfcdb6cb5518557a76db5ba37
F20110109_AACYKM topsakal_o_Page_088.tif
69c37a4ca311d93333bfe9c439fce7e5
47a0cd9c6c5ef6d0173423524b87873ce2a98997
1939 F20110109_AACYJY topsakal_o_Page_087.txt
17c4ab4e5ea79fd2e9e890ce3e272560
c1290431418c2c980dfc1cb35f619201d4db6c28
29336 F20110109_AACYLB topsakal_o_Page_085.QC.jpg
f2fa97e186616b61e083b3b9ea26d281
12fe7d04b8da1596e6d32571aab0b3b616f2ffb3
54505 F20110109_AACYKN topsakal_o_Page_126.pro
dcf04a9f23c5f2d01f39c802a045fa55
e4c3697b6098e41d76ecac025ced3168732049a9
29453 F20110109_AACYJZ topsakal_o_Page_043.QC.jpg
3300be0321d7cda31b459f46ca533a94
5468349076ba548ae0a7ef6674b831aafd70dea1
26078 F20110109_AACYLC topsakal_o_Page_119.QC.jpg
d5aa28ffa39c8f8889bbfa6a13a8854a
648284410c7db051a4657e996406e1609ce1b144
47518 F20110109_AACYKO topsakal_o_Page_031.pro
1fc22a3c1ef58085ee2bffe7c3f2ce40
7973faf4140c0584db55e04b26c78d169bd16b9c
74529 F20110109_AACYLD topsakal_o_Page_109.jpg
c0b09746dad4997b57e0640c6e8faea7
f60e5c39a26f97b1643bd7fdd88d7c185974dfa7
99317 F20110109_AACYKP topsakal_o_Page_046.jpg
986a5d2748618f5759fc5b4ad8568bbc
819068ad0423bd811a808379973fb21aa2d14824
1051977 F20110109_AACYKQ topsakal_o_Page_059.jp2
d86561347a0557a0e75b2314b5c8fcfe
3d9f34ebb63f5b3bdd96ea2d4e854d72bf35e9b4
82706 F20110109_AACYLE topsakal_o_Page_014.jpg
a9882e0c5571c0f1006540af8f8fa82a
e54d540ea022343fa812b198e38048321da9a008
314396 F20110109_AACYKR topsakal_o_Page_011.jp2
2fbeb8ff82f3ac554e4fa0a430e49477
08757cac19969dd167aac1c9bb83f2f931238eb2
6827 F20110109_AACYLF topsakal_o_Page_007thm.jpg
8c7ad0a00138acecf118e54e24c8b96a
7f9cb3a43e8e9a8243c4ffe0d158253eb0639812
112268 F20110109_AACYKS topsakal_o_Page_128.jp2
60b03383543089789f78a2e6c4ecfc7d
db6a8ecb33bc091483b4bc873ae6442cca126ff9
97638 F20110109_AACYLG topsakal_o_Page_037.jp2
24933c3acc957eb273679d27fb3d3245
41ea90549c8ad1d50ebfa1d52d0518db6a302a6e
32088 F20110109_AACYKT topsakal_o_Page_027.QC.jpg
84518c84eb93dadf5297fc8988023e0d
ab476347890d056bfb5c8e9dfe7fcd2c73d97f2f
F20110109_AACYLH topsakal_o_Page_017.tif
a63a74ade7fad8606ad3c50c13179ddd
df6b5ed530100ec935aff228ce74ede9aef0d51b
861 F20110109_AACYLI topsakal_o_Page_040.txt
6f83bb0ac515bfc5a341c2a3435bf144
9f3942a0485d5e480f672d254c65e50920d76551
1998 F20110109_AACYKU topsakal_o_Page_101.txt
649236ed81a1c8088b4effb62190cf7f
cc63d03e227964425a1828b11be59ac53a2b5582
1865 F20110109_AACYLJ topsakal_o_Page_038.txt
4b988e0cea88c6fd9170c167eec233ea
017003d4288ece31d7803c697634d2c64e7e3d57
71194 F20110109_AACYKV topsakal_o_Page_106.jp2
7cb99a96ac6136cc092ee03933842167
d0a5acc31de7097e5c06f5d3e43adc0084934e1f
102042 F20110109_AACYLK topsakal_o_Page_085.jpg
8099eaa676e4dc64aa18c339a591763a
863b18ced9521825cf6ee92d7d0d72b0918de44c
91560 F20110109_AACYKW topsakal_o_Page_101.jp2
62dff061a3b1ec2850374bda1f8c6e4d
973b3babb6b42d246197cbded9962c4bf397a169
F20110109_AACYMA topsakal_o_Page_107.tif
0d8e37c5919e4da00f42aa5b1e08c2eb
1f6a2919c10ea18074b23f7037921815504ed0ea
24252 F20110109_AACYLL topsakal_o_Page_114.QC.jpg
295f98e42c5a0e3308742b0e8e69590b
519c17b5bec9ee0d3dbd2db2c7b36224477ed7b1
38893 F20110109_AACYKX topsakal_o_Page_116.jpg
dd75a1ad6a726cc7b1d2a6fb2b24e0f4
3c5b6588669071eea3f12a38405e8e32c275bd41
39964 F20110109_AACYMB topsakal_o_Page_004.pro
1efdfb3031d85cee0e874e32525948c3
bfd1ac66513561fa1ce8d4c2501eaa620a8cb3f9
104882 F20110109_AACYLM topsakal_o_Page_092.jpg
750e4a0792d8e4c6c0b70947b1dc99da
d02e4e349f09ecc436a1f4bcc02725f58f3e272e
96218 F20110109_AACYKY topsakal_o_Page_077.jp2
71e61b390e222793d414cdfd326117b8
7223b623e0d3c2f9bae954474d7b18ac6aac14fd
6764 F20110109_AACYMC topsakal_o_Page_072thm.jpg
ba23c98bb13df4068c4df3d138fe969a
af49e6c44280bac1622bc8ad5c545d819ca34c7f
44890 F20110109_AACYLN topsakal_o_Page_117.pro
07d2e704154deb0db19f74dc7cedd4ba
de0dcdf21f193bcddcc0e18ad1e799129ce77a54
61738 F20110109_AACYKZ topsakal_o_Page_130.jpg
fd49062b724f2a7490df9a46d483a2a8
0ec6ea790c9f1edc98e982c502db703f6601f1a2
F20110109_AACYMD topsakal_o_Page_014.tif
d0c63b6f954a0fd8c7b19f85bfb4808f
b8e56255023c0cdbd9b0d2c00de596096118c390
667162 F20110109_AACYLO topsakal_o_Page_105.jp2
af36d8026bb9ce5db77dc544dde7e773
58ac2311077f0b0f5003e70a8ac2f1e4089612a5
39822 F20110109_AACYME topsakal_o_Page_014.pro
1feb1d814a185ad2fbc7cd989e323832
f6e48d035bc1b1a939ebac567d4de1e847ce355c
F20110109_AACYLP topsakal_o_Page_099.tif
7657d4b932bef6bdb4a47a5b534ecdc0
65ec9ba7c2b4f239405d8c3b99700a63068e5d40
25148 F20110109_AACYLQ topsakal_o_Page_060.pro
3e83554bea592442f4a3446c5a9a0cf0
da44a99eefe23edc44e822a5737803339a75cdf5
25271604 F20110109_AACYMF topsakal_o_Page_011.tif
8da197244674879a92b7a45417e9aeaa
7aa941880b70b87774df170b6b4da57f8ecda4d8
3388 F20110109_AACYLR topsakal_o_Page_066.txt
be2c08ca1f2e63149c44e1f0488ed5cf
1bc4ed47b42121ca60d6a3342722767c08d04d4c
66169 F20110109_AACYMG topsakal_o_Page_113.jp2
dde8a3e12adc1b21f59ca29fc9f94537
e0b735c79a6f9f8d2d96542cf3b8240a96ff27b5
47782 F20110109_AACYLS topsakal_o_Page_030.pro
7f88e93a9327fcb6f424da9d3682d2bc
094976a31598b3bb081dc1978c55356eaa42570a
70565 F20110109_AACYMH topsakal_o_Page_106.jpg
9ea46bcddbc787a9f154de0ec4c3a21b
844b023e8cc1967bd166428a0bc1d9741b68f858
F20110109_AACYLT topsakal_o_Page_060.tif
0540ee76748ceed17a13117a8d44c51d
362609f48110534456563c603b58e0a525f64ed5
2061 F20110109_AACYMI topsakal_o_Page_033.txt
66fcab7090da623f41f47ebd212006f8
fa4b37621157381b86372c3e0e654a24da38793c
737 F20110109_AACYLU topsakal_o_Page_129.txt
9afee116071ef7dcb19671b7d5fd3a0b
dc58c71d2217c6d47d260bfde57a002e06453c1e
2039 F20110109_AACYMJ topsakal_o_Page_094.txt
c731d2e0daaf3953b4e4d82f882baf5d
9167adb8c84853fa427a810455327b24cbea1244
40002 F20110109_AACYLV topsakal_o_Page_022.pro
83b936aed79a9c0771ddda05ecb09ec1
0e24e683587b411e62cb472c3284e9240ed21375
F20110109_AACYMK topsakal_o_Page_119.tif
90254fdcb906222fd4c64eeb9ee64131
dc7c9749eb614a81b9f092703b0d940ea0e31226
26628 F20110109_AACYLW topsakal_o_Page_001.jp2
57ac27de1f638a4aa85b8339cc0e1088
08dc92b2f82d46e448f481d94707acc767ea8892
62951 F20110109_AACYML topsakal_o_Page_104.jp2
f9359bb665c14b45cbf28516e99a967d
e26c1251b76d6a0e0bce94bcd6dfb972501ac784
3538 F20110109_AACYLX topsakal_o_Page_020.pro
d0ef779ccc69336e74380b507655c484
298b9cc29445c27750f58670d7f8c3564fd9a14e
27707 F20110109_AACYNA topsakal_o_Page_130.pro
ed02d6d255066de62c9750663a7258c9
d48ddf441b160fe017b96ff6334791e60c3401ea
5990 F20110109_AACYMM topsakal_o_Page_118thm.jpg
7745be49bdc7383d729383580b82f1e7
400524a453a51949e994fda60078b710444e7c53
1639 F20110109_AACYLY topsakal_o_Page_022.txt
36361b37293bc414baec4e00e2b505f3
8069c42ce2d01c4bbcba6550a9159dfe5dc4cff3
464 F20110109_AACYNB topsakal_o_Page_001.txt
7cedd5681db86cb669554f899fe7eee2
07d5f7e24ed5893adbdeea2e71d47ed772931467
1951 F20110109_AACYMN topsakal_o_Page_041.txt
86941d7505a017f34863297158c169d1
97f3dcbdf7745fe17397523249375dae7dd750e2
2126 F20110109_AACYLZ topsakal_o_Page_025.txt
593d69fdb17a8842044bb6e341f32d16
dc193f02154e6ba2d14a7d880b58e72b2adfa034
2552 F20110109_AACYNC topsakal_o_Page_015.txt
ac1668d7ea82f446fc8437f74c741423
a8a92a6e3947a88cc867e7ccc8759770ca709678
1629 F20110109_AACYMO topsakal_o_Page_004.txt
62e72adb92486ed77a2ff7a94026c163
4f75ab760c798a3081c199ebbd2a6d907d94a134
19748 F20110109_AACYND topsakal_o_Page_130.QC.jpg
30af0de462f8486a586b186db4e2bf78
15fc9db0122c1e004ad91cca360cadb17995d0fb
F20110109_AACYMP topsakal_o_Page_093.tif
2148712c3e416817d788263f0b1dc992
89df9b9bad461c37ef7359788b15adc437374e7b
49756 F20110109_AACYNE topsakal_o_Page_048.pro
4f79c5e810a9cee3cd1a6cb99662bfab
840a3e425c9d432eecf35f61a268314a2fec93f3
38224 F20110109_AACYMQ topsakal_o_Page_103.pro
88c40bfd22267c27e99434528a7778c4
6de054985bf8613af877696363a88794633dd9cf
92203 F20110109_AACYNF topsakal_o_Page_117.jpg
b62d9122997f484a29813208b0a3c643
73b3eb76cee589e5290ea39eb3f9244be08881c0
28385 F20110109_AACYMR topsakal_o_Page_080.QC.jpg
7a4c997d92ab90b7e2d2fb70b06aa931
c338523ee7c60b98ad0de141d3472fa44fa49d2e
31308 F20110109_AACYMS topsakal_o_Page_038.QC.jpg
93c7dbf25512b93c1309447f34d99c4c
59a108a8271adf796e530d928e3d45b900abc5fe
42277 F20110109_AACYNG topsakal_o_Page_077.pro
8b5d2944a62041cf2e19f514a1c5485c
0794fef0bb23ed6a800426c4111f8273215174a4
53095 F20110109_AACYMT topsakal_o_Page_090.pro
87652477156a322031cb6b45e432e301
6bfd8ddd468396f54c4a8e5b3605f838d45023c1
104368 F20110109_AACYNH topsakal_o_Page_087.jp2
6ae5b5379f2c31895abf9f8755a861e0
ad5d1cced61d194cdc5a359dcf07bf17efdf1493
30695 F20110109_AACYMU topsakal_o_Page_068.QC.jpg
b2226caa90de9c7e666ba8e4bb40451e
d543c2300a154f984afb823dedf0a50b045bfa0c
F20110109_AACYNI topsakal_o_Page_023.tif
55651806c430619a91512aa6542ce456
e3f58f651b952e89384021e910c490fbb9ccb66b
102588 F20110109_AACYMV topsakal_o_Page_026.jp2
988e2224e2ae11d82d5943997aeefbd2
75184cec086667ff4f418414d9c4752fd8fe9eb3
81544 F20110109_AACYNJ topsakal_o_Page_098.jp2
a0029dbef39ba936948e310df05232f3
7fa4120fe18fe9ec085273a1078985cd4650c443
1023224 F20110109_AACYMW topsakal_o_Page_030.jp2
5c6d8f2cf7d70dffe6b7e56197c1c3b8
4f9480e69393adfc1916d9f6fb2c0f1287eddd39
F20110109_AACYNK topsakal_o_Page_037.tif
cf33cceddcddadc0fd0a981d4aefba9b
28c5fae9a0100e94090c98ea2db2474b668c143a
F20110109_AACYMX topsakal_o_Page_026.tif
5f10ef636935fa86a1e63c0e9b5d0e3b
e4f3f09f891e5af1597ed0c2e06275344278d97c
788747 F20110109_AACYOA topsakal_o_Page_075.jp2
1bf06d96fa658fe5892bd4c661b26602
0cb26134197fb74bb270dd04951742c95d5e050b
48913 F20110109_AACYNL topsakal_o_Page_112.jpg
f80a97c6e3a2aef8e9980cab6867c57d
d0f9893d01dcb155f715227e679b2f8af3cb0da2
1973 F20110109_AACYMY topsakal_o_Page_121.txt
af4757c35c536504aef296226fb4f2f3
a91baf99f4efb8a970980a3932c2d2306e41515b
7060 F20110109_AACYOB topsakal_o_Page_004thm.jpg
95e2464f9ef9d3d921adde127c17ba84
2bce5f1b57ca555dd817d0bbd508051ae12b71a8
32660 F20110109_AACYNM topsakal_o_Page_092.QC.jpg
0208d0cf8ffdc29ea610791c9cc96095
c8018b19105ac4f1081c2eec2ffa96878c296b9a
7853 F20110109_AACYMZ topsakal_o_Page_066thm.jpg
41ebedd678167b2020fb3ed02a440c21
203da6671aaed30d227fc7562d66166bf654db69
28418 F20110109_AACYOC topsakal_o_Page_023.QC.jpg
bcf6083a28eafabccf7afcaf3696a7b3
859944488791ac3a8432a365dd9141cc60b8ec0d
8184 F20110109_AACYNN topsakal_o_Page_041thm.jpg
c738181e12ab85614c6fad9ce303f54c
81311c65153c783800bceab747b40c6bd3ed7b9e
2009 F20110109_AACYOD topsakal_o_Page_016.txt
7fdb7dcdc3b5854aac5b574e291b425a
c62105fd378b6fd4d3cb52ce944e0706855b7e6b
2424 F20110109_AACYNO topsakal_o_Page_070.txt
63b46f1f7c67ef2800891d1c48037f9e
4127223f794b90a097f6dbc35a9329d0fdf2e367
97181 F20110109_AACYOE topsakal_o_Page_026.jpg
9625891d74ce237bc252390bc5479bab
f2888dd04ab7d064ff1d1fb7e2ea8ff5bee65df2
32421 F20110109_AACYNP topsakal_o_Page_035.QC.jpg
c4fb591d3d78360a2d205ad6478a730e
548f39e4fb953eaf1bf1f57847c29090efa28c5c
7498 F20110109_AACYOF topsakal_o_Page_091thm.jpg
7b6fde210106773a564efe74ee572e35
ed2f415d36b58e85c90d9f1655f640e15d83cc2f
120267 F20110109_AACYNQ topsakal_o_Page_070.jp2
9f964b39f07d1d71f77277c41f5b300d
f9d0fbfbfec7690501c1408166db8ea15a7c582f
67235 F20110109_AACYOG topsakal_o_Page_102.jpg
cca92b88dbbc93c3ecbfda0c7959d5a3
e26f0dd7411cc593b2148057e4001697cee451c5
5925 F20110109_AACYNR topsakal_o_Page_011.QC.jpg
b3839c4cbfd7623700f0b37fca7a01b3
d85ba3a056f4ead258afe04f7169b0c7bf864a7e
F20110109_AACYNS topsakal_o_Page_096.tif
d8bac0c6d79272b2a83b1566d7cc8487
a2e797ab94763b18ac351b23f371d05284b7e369
F20110109_AACYOH topsakal_o_Page_082.tif
7b13712ea6949fbe6630a8a62ac36926
586527359a35d9beeae9ec784f875f14ca38caa8
1984 F20110109_AACYNT topsakal_o_Page_119.txt
67962919d295d88ab3f2f033343b0ba5
4701c835886265f5bd69733d4ad5e032b0b1b50c
F20110109_AACYOI topsakal_o_Page_117.tif
0f8c95f2141d4cb05e1c90d8a83461b7
442d9c55a2f636ea61152b5e125a600e024f9d38
F20110109_AACYNU topsakal_o_Page_001.tif
4a6df41b328885c83d520d0b00d0ec93
4a04a3cff0f6c7b81f5399ec326017dfbbac1714
2191 F20110109_AACYOJ topsakal_o_Page_092.txt
81edb61f6ef1ff5b6632bf061bc6750f
6e1e288e236f3ca7d7449f6919419699dfc2b90b
114732 F20110109_AACYNV topsakal_o_Page_058.jp2
738aedb8d5d58db6113a91d12e5c700b
0208c58f26bf9e3120189d030912e86836897407
5449 F20110109_AACYOK topsakal_o_Page_034thm.jpg
9979fe1e1cca45de59c11985ccbae4a7
9f5372449a06367daf5a6aaa786670fe7b2e65a0
8423998 F20110109_AACYNW topsakal_o_Page_068.tif
ef77fdf4b44cac5ca2d4e92c427953bf
54aadd54f8d23f2a808c1e56631f0204da7e53a8
85195 F20110109_AACYPA topsakal_o_Page_004.jpg
7cbd555cab02a75f832d649b58e37cbe
2dc845529c9678180ab1e1a921f3b87f64246c54
28261 F20110109_AACYOL topsakal_o_Page_096.QC.jpg
2f825bd09d7378aaafe5c2ccbace2252
6c90ee839de3272fce487d5f3b274af3c4a153ff
8595 F20110109_AACYNX topsakal_o_Page_084thm.jpg
933ddc0e5ecee6ba353cb14b2e1dd2b8
b46b7e82f0284ef5d72694d8a4b0f12b5be51740
93701 F20110109_AACYPB topsakal_o_Page_086.jpg
415e758e1fa8ae8399141bd5ede61645
ce6f9062b503c77804d59e61ce253c5c13b5b602
887643 F20110109_AACYOM topsakal_o_Page_064.jp2
c8cbd8b6db44f62f2ec8bf05654ebbb0
6e0aa66cad59b3bdd12766e86afac090f8bbb33f
44613 F20110109_AACYNY topsakal_o_Page_050.pro
b9051d086feebf8a853eac89d005d132
b67b12bea0607e95642267b4c5fa4181d4a87324
F20110109_AACYPC topsakal_o_Page_126.tif
8f6d4ef74bbbeda65622bbfe75603d06
2067aa2efb3b6ee5ff7b8a7337595e7957f98d1b
1853 F20110109_AACYON topsakal_o_Page_110.txt
4cc56a392e65b9f73dbe18ea899dc186
a26415d0363e66b45683f3dfaa3593a733d9647e
2407 F20110109_AACYNZ topsakal_o_Page_090.txt
a7fbaa7c3f1c0977c2edcfc14c475255
d76f2b9d2efeeb566f0ea6750b9eb5d6abb0cfcd
F20110109_AACYPD topsakal_o_Page_024.tif
7df4496486eb9e01db2aed6dc3b70b2d
f2b314309164b71833661a2fbe7b3f4b1c51e2b0
48171 F20110109_AACYOO topsakal_o_Page_085.pro
3775ec7f2af5cbb63fe96d6c68340ab2
57460d214dec4d1ccde0c67aeb69a6046f7ae417
88752 F20110109_AACYPE topsakal_o_Page_054.jp2
014827ee5e54429b63d6390e2a85a74b
52b2e51776ddd98cf91123d04534d5fefd18edf0
F20110109_AACYOP topsakal_o_Page_058.tif
dd7c6ac05ad96c6da437f46b2edfde03
ff5f5d43a5c01d20773d691b6802694795f57ba1
F20110109_AACYPF topsakal_o_Page_009.tif
305e3e71fb1a92e12b6a92d67b87fe39
ed584db23282ff6c1b40ff5f45b121aa32214533
7596 F20110109_AACYOQ topsakal_o_Page_065thm.jpg
c7651619694dd8299ac3ec3b4ad0a90e
9afac28eaf54a8d8dd046ca747e2b365e6950a95
90895 F20110109_AACYPG topsakal_o_Page_036.jpg
59f0964fbc09d7618f179f45e378a169
1eb75bc40347f1824b0c99ad71a344b6d904b3d8
30097 F20110109_AACYOR topsakal_o_Page_050.QC.jpg
d42b4e71f2d79aa5aa92ff0475914862
5d18ec23d665a3993a3320773cf43393bb9c8882
84315 F20110109_AACYPH topsakal_o_Page_079.jpg
fb45bc96e7c7d0d99dbe3c3b37791eee
ad7a0f5a160c937e192bd965e5ee0de96c6ba54a
41467 F20110109_AACYOS topsakal_o_Page_051.pro
b5da8ebd5cac827d0ad281960a213f83
748bf44e75274da3f569e9d4338db8055778c53a
31338 F20110109_AACYOT topsakal_o_Page_056.jpg
b7d1d1a6fd12002df872ac87b300d4f8
da6a8829aae95fd0e26d6540bd755039ee36062e
111069 F20110109_AACYPI topsakal_o_Page_025.jp2
6eb2e4315d6dcb9f0adb50219511a8f0
9395e44b75897d62bee34015e1cd7af5a78e8b22
64612 F20110109_AACYOU topsakal_o_Page_034.jpg
fb5ff8d4284970a2c0378c5951668094
912280f6e8a6347d6a03926174a178ffbbab9247
87743 F20110109_AACYPJ topsakal_o_Page_118.jpg
5bef3ec1266d0e9494f83d2742f888d8
1ecc2f0c96dba1735a716eae63088c67754e8452
33638 F20110109_AACYOV topsakal_o_Page_082.QC.jpg
985d6871a00c9743bc36c7437cc29c39
9ee4d25c85f7ae5c050366983936afdb1073e789
6677 F20110109_AACYPK topsakal_o_Page_120thm.jpg
c19604a6737bb7702565219a80e5585a
0ef4e36f1e98537df37eadcaeb5fe34ded2c3de1
24798 F20110109_AACYOW topsakal_o_Page_052.QC.jpg
eb257cfd69902422c028286c4787ac4b
ad959b0622ea6413f54f52b57947180a48e59d5e
F20110109_AACYPL topsakal_o_Page_077.tif
4f05d96a9e0ffec6eb770548289ad41e
43a16e86375e84c26556826849973f4b5c3ca0fd
27373 F20110109_AACYOX topsakal_o_Page_107.pro
8e7bf641b38a6cbce28e158df77f83f5
981451566505a6001cdaf17acc932f529eec96cf
1751 F20110109_AACYQA topsakal_o_Page_069.txt
a2542855080093f49bb023322096bf7f
5adfc015bab8d9ef69cf83463c63df248c4e1d99
F20110109_AACYPM topsakal_o_Page_112.tif
a6844d56eeb696e8bed973e49348c74d
263b992117a97886b8896c594a209cbdeec6c13e
38525 F20110109_AACYOY topsakal_o_Page_068.pro
2f980a0175748045ea1ef729555f5b55
9ff97097748c034736a414c3f61c9c5213a53e8f
21244 F20110109_AACYQB topsakal_o_Page_034.QC.jpg
ffc454c9fe7d7034aa60403e16e2d012
e3d501a52238922b5725353734f781582d400945
29929 F20110109_AACYPN topsakal_o_Page_069.QC.jpg
9391014edcde6fa3646a6acc4a7453a7
03290b1548a9eaa2150b6ed018cfecdd7245dffa
88633 F20110109_AACYOZ topsakal_o_Page_022.jp2
a6472e5ddefb877a54c8238e84181ee7
6e8a53f2cd1ab80850b2fd8528851cbd7ffe3c15
48185 F20110109_AACYQC topsakal_o_Page_024.pro
a04408d9df3d81bd892d46f11fb9906d
6e86429bf9820d4363801c86665e5e80e90a1f3c
106436 F20110109_AACYPO topsakal_o_Page_090.jpg
25a26cbe7149d239d15aed82ba3b2843
bbd3c53465112e75862a204286f93f9c37239754
88299 F20110109_AACYQD topsakal_o_Page_053.jp2
187298a3637fe401cd8ed7f20b3f7352
65d9e109e8fdff9b8a2b4a030df67aca482fe3e1
8018 F20110109_AACYPP topsakal_o_Page_047thm.jpg
fbffbb10c3aa03e14c77c45f99221e75
9d7f9625a1aa87bfe25af76642c4672138217f48
57046 F20110109_AACYQE topsakal_o_Page_070.pro
c0ee21b79d98b4c72ef86b8935e03e24
8e9a34a9923817f20685745a931d39b59063e3d6
19273 F20110109_AACYPQ topsakal_o_Page_116.pro
3d385218995e81c52c6ab201ca4cf481
ba5723403dbd0f31a7536ca4d7a82972e81ddcf5
35179 F20110109_AACYQF topsakal_o_Page_055.pro
a68cbd790a50e8ea068b44e72eb0faf2
11446d7097bc26a7a6c9c1125fdb57a2551ea405
27781 F20110109_AACYQG topsakal_o_Page_079.QC.jpg
5293ce2f63862f8fbfae25100f830a61
7e09e5fdcaba2c75083eac57e6e5f55143c990be
7745 F20110109_AACYPR topsakal_o_Page_032thm.jpg
26a3b89130342c9cf80c84a79cbfb803
a86feff83dd04d566fb9ffce22034b757e669f4f
69703 F20110109_AACYQH topsakal_o_Page_102.jp2
51f3cf27eb10ed3011daafc1752c164c
53738250f1d15f60acd06f15cc55e2f994ece93d
70241 F20110109_AACYPS topsakal_o_Page_028.jpg
0f2f008773dc218dabb9b8da204ec695
9ec005679a06bf62007bc631322bc59a0b0fe82c
7589 F20110109_AACYQI topsakal_o_Page_003.jp2
ee251c50e0c969ed8e65facc51a6034c
255a6174a44ad5b80ac9650f2c240486538ebabd
37650 F20110109_AACYPT topsakal_o_Page_045.pro
e93195b1162651c62e86dbb2df4df453
bc669aabc6dc9419ca7d317d604edb287c600fed
73411 F20110109_AACYPU topsakal_o_Page_073.jpg
eeb1c40c8526d21fda388ffc1466e889
45065e7f80092eab553f7f4d46a76256ab8e8cfb
F20110109_AACYQJ topsakal_o_Page_033.tif
e5efb93451bb3622d17062bb75481246
90b40103c9141d5d320b2bf57893d0c0873425dc
742 F20110109_AACYPV topsakal_o_Page_097.txt
c43bb081d6022952420697dab1323547
176f9bf515908b1feb5f4b85622e8f5dca4603e6
29655 F20110109_AACYQK topsakal_o_Page_036.QC.jpg
79df13412f7c35cbdfcd78ce663bf83e
7d643a671a6f9154e488f909f6a16e89107e7c41
25716 F20110109_AACYPW topsakal_o_Page_014.QC.jpg
624c4bad00c469e62ad3e4770b89efa3
f24e713399adb1d31a1e61606c9449e38af697dd
2344 F20110109_AACYRA topsakal_o_Page_039.txt
2b47c53a8a2e48b382330a899652f976
48de154391866045a7ba1fd57b26ff3da1da2bdb
1394 F20110109_AACYQL topsakal_o_Page_060.txt
80c15c4f51ec3c9c7d9b21de581663ba
f73065a44eaba2f0295201fbf5f71a468bf147b0
104208 F20110109_AACYPX topsakal_o_Page_018.jpg
07eb332bee95f682ba021841559a041b
8ba8fa9dc11ad6d2cb608d3b7d9fcceb62b26974
7767 F20110109_AACYRB topsakal_o_Page_071thm.jpg
b2cdbd5556ac9bd5ec8fea3b6ab6cf82
6468e5c4372a5433eb9420bffe526e5a161f9047
83202 F20110109_AACYQM topsakal_o_Page_111.jp2
bb7907f21d8588b9e7310de2802568e9
ca5d46463360b813d9372644dbae9a76ae6e9490
7925 F20110109_AACYPY topsakal_o_Page_025thm.jpg
7aca7ee2e86545b6416803d1d0524a76
98b4228544b65b89d1a746ae82b6b52b2cb29dc6
7444 F20110109_AACYRC topsakal_o_Page_122thm.jpg
e7f99c7edb9c1d6dbe74501774054f89
35545dd5eef956b0b6a24e6fe32e0e1cf3caf980
6575 F20110109_AACYQN topsakal_o_Page_098thm.jpg
8d70846aa94fb50b759470456f963798
7c3d3b41839d91b879b21ae585f22ac1312644d6
30279 F20110109_AACYPZ topsakal_o_Page_126.QC.jpg
e022cea8be8fd283b2a8d471dc44ce28
a7933c08a4d56cca616d863a8abbb806b9759275
F20110109_AACYRD topsakal_o_Page_061.tif
e1cd0ef997d1ff6311cc598338e7d09c
9d8f6552a17022c4b16661c76f203753e76e451c
122939 F20110109_AACYQO topsakal_o_Page_065.jp2
47e7a70340e1af646b8e0499d86ccd32
393599a55875ef26333082124d4261102e04c279
2487 F20110109_AACYRE topsakal_o_Page_099thm.jpg
750958ffdea3ab6d6d75026d168b226d
2a5fcf07ac2fb04d77e52aaeeba9bd65387e3c80
26443 F20110109_AACYQP topsakal_o_Page_044.QC.jpg
6e6f8877998d9df4f000af9528a4eea3
5a73ad92bfbde70a82c0891d29ef252bb1f1ee1f
71610 F20110109_AACYRF topsakal_o_Page_066.pro
6d0705ac892ac815998999306f0b9b07
0f2e8f68455548c09195c3a831fa470403329bbf
F20110109_AACYQQ topsakal_o_Page_109.tif
29461f15c411779fb5abf9dcb6b49c48
1603b2c239a2ac0f206e38f03061c2cc0b7cbb39
112565 F20110109_AACYRG topsakal_o_Page_039.jpg
f7e75f0ac50af39e19ffe550a16aa1ee
46bb609682e42daafdb508f8a6c517fb80cb3acc
19338 F20110109_AACYQR topsakal_o_Page_011.jpg
adcbe17e2b2e90e247aec832615cc301
96a91359fff2f1daf1bdb15618dcee8ed6805e7b
24711 F20110109_AACYRH topsakal_o_Page_108.jp2
39aa349dba8af69167726515119139ef
700330e2d40c1242943f0e83581da9aa12618567
30441 F20110109_AACYQS topsakal_o_Page_025.QC.jpg
6f84d49034ed4570f40f59ad2c6a145d
3549ba71b3a21fb2d5b19c24bc6e443876a90dff
44887 F20110109_AACYRI topsakal_o_Page_086.pro
c0ec5a85485b21cdbbfe496c2a5f9c04
ab5248025f6da6a4f102a0ee592d2b00b8e12e2a
F20110109_AACYQT topsakal_o_Page_070.tif
3bf947105b6b86ad529d591a8d626c1d
451ce565f2b57c882c0d9b55a6d7613164e4acae
96737 F20110109_AACYRJ topsakal_o_Page_027.jpg
e558e19e364269065f73d4cd444e7547
4984bac94083d4a29a5fa14de1bd8f519b7c6bb7
84801 F20110109_AACYQU topsakal_o_Page_076.jpg
04d7641d412dee516e85ad4676929649
87c296f5cf04899003e3ec34fb3c91290d42c682
3817 F20110109_AACYQV topsakal_o_Page_112thm.jpg
eec0990d3901c2817ca56ad42a7a0e1d
0d48f02d096e1b2455beb3d6ca3faac26987784d
31891 F20110109_AACYRK topsakal_o_Page_127.jp2
54f7f0469e9dd5e2159d9ff0af88b820
39fb518f89e238c237cb9999252cbd7af4090e61
8262 F20110109_AACYQW topsakal_o_Page_016thm.jpg
55f9a3129853c9863d0982c461776b3c
8cfb42033b96d0a746f8e2106ca41fa47c7a075b
92190 F20110109_AACYRL topsakal_o_Page_024.jpg
c437ec77380389f9332c505aa14b27e6
9875a33d0d8d75c195b6a424fb293e4922271063
40734 F20110109_AACYQX topsakal_o_Page_028.pro
3451b5f573005c1e5345bd787b1256d0
76ca68224aab9e43a6285338c3b023a1afe4803a
8151 F20110109_AACYSA topsakal_o_Page_015thm.jpg
9bc8f0ab6f99967882a178cf3fdf3ad9
cf4e543d7f49abb1dc9865c6904ec2b3d6fdb14f
616 F20110109_AACYRM topsakal_o_Page_099.txt
32c804072a9b61fc84b4a133d8bcecfc
2295b0c842b29ad3086777d05fd6d9185f7aa634
631 F20110109_AACYQY topsakal_o_Page_002thm.jpg
83b49b4117c47a50d81f9411a4ba43f2
2437c9c3b2bf2d628c3fe2cea128e9c8c7c82760
41175 F20110109_AACYSB topsakal_o_Page_116.jp2
e4c2f6ef7e589bc493446318ddc9192e
32ad7486ab9b9e815c0557e950ca9a49504ea7dc
137 F20110109_AACYRN topsakal_o_Page_003.txt
65914d702991c32dc5e295d0afbf6025
d15418879534ee6e95a8b91406eb9390f910a370
115353 F20110109_AACYQZ topsakal_o_Page_018.jp2
cf9487da83f03197b9c10fc864052573
1b55e598667a6322319aa95620c756c7ac36688c
F20110109_AACYSC topsakal_o_Page_051.tif
ed480fe7e123c9f8f160cb228317281f
4378618b460304c079ae5866b01e93aef67f628b
2075 F20110109_AACYRO topsakal_o_Page_111.txt
e1bedbab7ad51ff89dc3bb33e6b16b89
bc7e8c73632517418aba38820c6a032f009978e7
7809 F20110109_AACYSD topsakal_o_Page_027thm.jpg
af85f6350e2477e76a64ec86896146b1
45fdcf76384bc1c6302d7b380008ad5851b5c348
7079 F20110109_AACYRP topsakal_o_Page_023thm.jpg
007f9c680fb00d8fc68d887b726b56f8
1407e507bb9a8e50aa4226fe9eaa2cf50016ccd9
48013 F20110109_AACYSE topsakal_o_Page_017.pro
fd7637093064a40bfa6f9d789029c241
757d26aea8feb8f4a913fe14e7d5fb45450e887f
2275 F20110109_AACYRQ topsakal_o_Page_001thm.jpg
7eebc3c51cbabb8bab32c6bead7aceba
72ac4a5c9b75b71103b6d5e70d82f481add57d8d
23100 F20110109_AACYSF topsakal_o_Page_109.QC.jpg
3b42c4785180850980a73c133a61ee32
f02cfbc0f5a525094d23ebb4cfbe8f70a8023aad
44665 F20110109_AACYRR topsakal_o_Page_013.jpg
a5b85c008e01c130b35ab17636039678
3a62e2cc922b67371b4925036f1f2322cf49da24
112367 F20110109_AACYSG topsakal_o_Page_126.jp2
8088e371c4fda9e27564a79d441727da
ae52283eb41ae6b2435e134920edbbd120bbb997
F20110109_AACYRS topsakal_o_Page_031.tif
159b67490176737e658c104aee23cdb6
10459daf7963690ae3cd26f33efc88fb5c42cb86
1634 F20110109_AACYSH topsakal_o_Page_002.QC.jpg
e4b014880240b60a4243c79e7c59f597
ca36fed80b04b90ef507fbb9e092793b6edb801b
7684 F20110109_AACYRT topsakal_o_Page_078thm.jpg
c74c12ede2e247ff683a89e4831d739c
8fd53bf49e3509291cc93a4e73dff63dfea0274d
10176 F20110109_AACYSI topsakal_o_Page_108.pro
b6b9b22fa96af58344f3c78b2db95dbc
1d8020f226792a14d50407f0d81ea0b2169e084c
57935 F20110109_AACYRU topsakal_o_Page_064.pro
5be39ff701b4d9cbc34c3ecd16319880
7b06a8bc053e713fa4808bab7993a3855f73f1ed
1797 F20110109_AACYSJ topsakal_o_Page_037.txt
1ea342b4583c91ab238ee389d48908c2
7517ae20eb95a55581fb0f0ac5ac478369e29dad
18666 F20110109_AACYRV topsakal_o_Page_040.pro
88ed98ccd64b700f5d9df481d5c16e66
09771bff5bd2be0bdb2b4f5f71d9e87816ea6089
1904 F20110109_AACYSK topsakal_o_Page_024.txt
170dcedb4547c497edb9f25433bc0720
8da958d7eab528ab442200d40dfdaacee31e3cf8
121281 F20110109_AACYRW topsakal_o_Page_015.jpg
d84b0c2d0abaff7afba594126a9cc5a3
617ffb79055645f92151727e08b801282a5813a2
F20110109_AACYRX topsakal_o_Page_049.tif
def6341221efa8bb9c83449640100626
b6cdc5bd5a236fca264598d2611c0e22c4deeb88
42178 F20110109_AACYTA topsakal_o_Page_080.pro
924fe04ca335262efd2bd87cb53e3543
0281533d18247a3dc5958803c914453c622f4d3d
F20110109_AACYSL topsakal_o_Page_074.tif
318fcc091d67b5213b61f56df801d3cf
e6e59f3edb721b286c5333cb74180ff12f593ee1
784959 F20110109_AACYRY topsakal_o_Page_034.jp2
8c21130b4f0e3e6787b8c466b746d10c
57b3fb10e1e14843e293391dfb715c64ecca6622
47088 F20110109_AACYTB topsakal_o_Page_087.pro
217d6491b60bf756bd8645fb0bd098be
ac30e05c9811f7ce5cdd9710ceecd0f1d1ca853a
7321 F20110109_AACYSM topsakal_o_Page_080thm.jpg
f3958e6a7042ab1c623714ca799a6461
c8a489b05416815d25a3174e56ad91dafc7559ed
76110 F20110109_AACYRZ topsakal_o_Page_057.jpg
dff747e7a4db6a2ca85b1754f5c1b3b5
7f2951dd8e4249d06c4a7af82376fc14d92476fd
6921 F20110109_AACYTC topsakal_o_Page_121thm.jpg
13577faaefb25b6098f3629e929c9ead
ebf963642e1026f045ac2a6cf017849ef495f6b3
30359 F20110109_AACYSN topsakal_o_Page_031.QC.jpg
a8f6d3a8e4a32b50b831144adb7ad15e
fcd73267256753286c597a539ed242a095933a9a
7729 F20110109_AACYTD topsakal_o_Page_092thm.jpg
a77a9116094cb1eb58103e4e5e2ce161
4698ca1ff4846aae1225c13214ceecbc3d1fbe04
9540 F20110109_AACYSO topsakal_o_Page_020.jpg
131c6f5a1cc9d47068db707730c970ca
8e5b4eb1eff6f0b6417116fd78d49a0386676e8d
829 F20110109_AACYTE topsakal_o_Page_013.txt
32ec5a9ebaae565bcd3979db8e260189
5e5160efd07db8b68f66b37490b511a4b70fe655
1788 F20110109_AACYSP topsakal_o_Page_114.txt
884e40d1a76efe8efb4d7038d0d2373a
ae26087611161c128b6f9a8379575bce5b4a02f2
329 F20110109_AACYTF topsakal_o_Page_011.txt
c3a8a4c40e96eafce2fa94b97a3a3933
6c7bea291b0ac63d3550a14fc0ca15c9f6f773f3
7587 F20110109_AACYSQ topsakal_o_Page_024thm.jpg
f1dabc563e6f5544b24458efb290f0d9
a59cff4d7c4cb500ad2fa0aa7bf4aa3db2737ba5
80112 F20110109_AACYTG topsakal_o_Page_044.jpg
2a119a8f463a20c6c0057e33dafe0c91
5e7b461b802b8c355c96edc509c0ad8af3d095a7
23404 F20110109_AACYSR topsakal_o_Page_005.QC.jpg
68cd9bc256aa076d41551fc7bd7ac4a6
ccf94adede9e2b001b28cf4c1e1306d8926c396a
6897 F20110109_AACYTH topsakal_o_Page_003.jpg
3f0d28bb07931c7c0b4a8d377d6591cd
cde65cff9dfa6eb14e14ed349fce1d702834cf91
98309 F20110109_AACYSS topsakal_o_Page_120.jpg
1735f592e72ee80940140af8d7d32483
4424b8077e65fbd67927f942d47f792f83a1a2e8
35448 F20110109_AACYTI topsakal_o_Page_058.QC.jpg
45a4dd363beb098bec72aae645907350
6b4250573e4746c21900ee410262c32ca40c6497
7526 F20110109_AACYST topsakal_o_Page_085thm.jpg
9008b67bc779327f195fe01835ab6dc7
c38f83059b2327fa485aba85d6f1c6ede13d1522
60289 F20110109_AACYTJ topsakal_o_Page_107.jp2
92f9259f2c40b60f3c6c403cce11d246
b158eb56b402bdc0de865d650f327c885cd760f0
F20110109_AACYSU topsakal_o_Page_110.tif
5f5632ad298bf18a84e8ebb629d9b33c
cf084d4f341062f284dfc4bae1c76d529b368438
32267 F20110109_AACYTK topsakal_o_Page_039.QC.jpg
5a07688e057a47067add8d37a49a04ad
0d7df8b5c0cf2ae9e0aa4072d756cf1600eccb6d
83278 F20110109_AACYSV topsakal_o_Page_042.jpg
3bb449728ccdaf3bbf4276a8689db7e4
a739f5a45d9c4e7f8df7a1ea73c6776c85efc876
41760 F20110109_AACYTL topsakal_o_Page_096.pro
75c41c17fd36053d1475664728d854af
ad99af8f872e43c70bc62cd614fc65874737c6af
84538 F20110109_AACYSW topsakal_o_Page_103.jp2
d13b73a6ed45f13567e0796addab4a0f
7ccb224ebbeddf9ad4c9be383731e097d5d4327b
F20110109_AACYUA topsakal_o_Page_121.tif
f061303dba27d4d8776f69de4d49e7ee
a3775cc49076a8274c66bb123c374eae3d2b5f18
869 F20110109_AACYSX topsakal_o_Page_049.txt
9dc22c5602d26d46eab38381ba1a31ff
ae181aa6416196c9cfccc88661d94c02d66a824d
105374 F20110109_AACYUB topsakal_o_Page_017.jp2
cebf1f90da05b98f6aa8622acd638604
c814716b964df0d8d8765ca764e9af2439bf1910
1893 F20110109_AACYTM topsakal_o_Page_031.txt
e48884fcdc27bf72ec70131da7bde3e0
4902e7adb686ff22576b9a446c0b8db67675f251
26669 F20110109_AACYSY topsakal_o_Page_051.QC.jpg
59dce36ea8084715c8b723a5ff38beb4
60c88c6f67268aef42fe10f334eafc7734cc0f55
65377 F20110109_AACYUC topsakal_o_Page_110.jpg
a7234083500d21f9676d4d231431f789
04139dd2214ed5c88bbdc4c8ca9238848941d808
48519 F20110109_AACYTN topsakal_o_Page_063.pro
ac0873cea921956cde291b053eb39945
a54b8b24898d4f913c9406922e07399d6c3e66ab
41315 F20110109_AACYSZ topsakal_o_Page_079.pro
9552d294a5c29b98df6646d9dc7bb08f
18d35314bd51e0422be87d0c328e6e7aedbd417b
10415 F20110109_AACYUD topsakal_o_Page_056.QC.jpg
d4a105071ae329d240ca9d9eabcf567f
6ea34fda727647088f3716f498208d9d498d2e11
785744 F20110109_AACYTO topsakal_o_Page_049.jp2
915558750f173e7b6bef45bbf07a0199
140c9d8752e840d6a4fa4b6022a0c2d8a2ed53e7
F20110109_AACYUE topsakal_o_Page_104.tif
2cbe29578d5c8aaf69a0d4f53b5953d7
68156aadb477e062eecf79c68a60e6cd63d4b9e1
98468 F20110109_AACYTP topsakal_o_Page_019.jpg
88fc59cb28de3cbe03402749ad751b3e
e7561d25e6af951ff2e9bf99c928cc2c3f486004
48039 F20110109_AACYUF topsakal_o_Page_088.pro
d7373d26fc176295e3cb4a0e2f8354de
831d43b09d40408e69241fe40c569ccbe0d411f4
6706 F20110109_AACYTQ topsakal_o_Page_022thm.jpg
0c1ab3ffda8ba95ec92b0055e1a68461
001d9f1c21b6be3e066e305ebd563dd848f5bba6
1576 F20110109_AACYUG topsakal_o_Page_103.txt
2ef08084e10875de485de26023070648
f376962009d96504251725b6059189516cef771d
27695 F20110109_AACYTR topsakal_o_Page_125.QC.jpg
323d2978407bd4b5c455833ecd5f95a8
92f733134e112e706ad95a3dcc2be849f39b7b34
88657 F20110109_AACZAA topsakal_o_Page_083.jp2
89ae4e949f9b85336ac61fc3ed6a4d96
3e2cd6b945b1cad50b9ea098c8b45f8280c72c1f
F20110109_AACYUH topsakal_o_Page_064.tif
9bbf3588fed2207d5807354e60b07ab6
ca034491d306a16875fc3df876a05241fe606447
8042 F20110109_AACYTS topsakal_o_Page_048thm.jpg
90364d17b9ca504fdca048fef6a698a9
e233ff576bfbbd500182f32a891b1b764d90d3e0
111102 F20110109_AACZAB topsakal_o_Page_084.jp2
0fc39ec1811db0b24881807ff390f45f
3ff7e8e46e73442717f56583f5e3975d22a00d4a
F20110109_AACYUI topsakal_o_Page_097.tif
6a88d6e48904f3ba27ee74b18991b596
ca74db44f3e7af6847559ce6ff607520ec395709
1746 F20110109_AACYTT topsakal_o_Page_057.txt
95c3033aa5ed237469ad6f8898156983
d4bdf2da2e44c2ab5adeec07529cfecec3bd2c64
98760 F20110109_AACZAC topsakal_o_Page_086.jp2
ffec0456f74ef7f155d079a54b2b5498
2fd61b90d2eb8352b779ae4133ec5f2ececdb6c6
6919 F20110109_AACYUJ topsakal_o_Page_021thm.jpg
66cfc9ea8790e93d740a9236d62186de
7196fdb9ef8a2d7aab1513328f5ea2570a3b36b8
6505 F20110109_AACYTU topsakal_o_Page_083thm.jpg
7b89e604877be2b36dc7b75cf2423da0
151e1a4ea3799ee5761caeab8597d3ebe3946d33
110500 F20110109_AACZAD topsakal_o_Page_090.jp2
6a7b3898bef0b9639ca9c0c741909aa8
a04c895dc38263d2805a66b8a09231358efdb5d1
2000 F20110109_AACYUK topsakal_o_Page_082.txt
ca50d97df7033a360fe8ef35a0670ba3
9c9035df935d4d3c9ef366e9ab97e0363c6e3ff3
28037 F20110109_AACYTV topsakal_o_Page_007.QC.jpg
a883a481d2e24b730afbb462b43e2c6a
50eb1c1bcc19abbe5a4421646b0a4e8748484174
113329 F20110109_AACZAE topsakal_o_Page_092.jp2
024ef6deac42ce616295b27d07d0aa37
383f67b04f70d93a5809f507f707768eb22a2c79
27670 F20110109_AACYUL topsakal_o_Page_001.jpg
9761e7fdd190ed4cfb250b44cdec116b
b34cb190502440befcb6cafa2df8d02e14f529f8
1823 F20110109_AACYTW topsakal_o_Page_036.txt
39d396dec5868b503e201915984b3239
1adb0379a1412917c6de457158f29429cfb03630
111440 F20110109_AACZAF topsakal_o_Page_094.jp2
3fd2cbc3a7d4675d95bdcfd5157034ff
fabfb94772043a895277d5b8484e24f92c76d0f7
2174 F20110109_AACYUM topsakal_o_Page_120.txt
62c0e47ce67b59461467c7deb4c1c51f
69b69bb5ac50dbb935bce75139f77bf56355ea7a
2170 F20110109_AACYTX topsakal_o_Page_109.txt
6d1683ba0d87648e6d73a2afb572bd80
1f4dfc97f3f4a6fe067b968908e1bbacdf2753fe
70750 F20110109_AACZAG topsakal_o_Page_095.jp2
dc6e6d3863717a675d6f2d164d8607e8
96217ef4c85841c3cebd33274065194bf6349ceb
10825 F20110109_AACYVA topsakal_o_Page_020.jp2
0938249d0b4dc8e895383320d20ee94d
5341b88525276825af85ec64d45b5459ca64cb72
10648 F20110109_AACYTY topsakal_o_Page_009.QC.jpg
7fa9b6f8a7cae7cd577d377da19e5e75
387f7d37d51403f2d86fc8dae729e313e554f2e5
69464 F20110109_AACZAH topsakal_o_Page_110.jp2
c107d9ce48819b128bb97c6329605251
db4ddf3c8fdf47d0c171a240c3624e2a2e645033
1936 F20110109_AACYVB topsakal_o_Page_088.txt
6f7bf3080257645d08acaa8a90131a9f
f086e0d6d3c757a19f0a3815d3a9647a15da9bf0
1327 F20110109_AACYUN topsakal_o_Page_105.txt
436df51de38be78e9a82a2ebe99df1f8
b5b96a5fc23871d3d075c29881ab8b62785d96be
F20110109_AACYTZ topsakal_o_Page_089.tif
c1aacde9ea505f70dcb504c201502009
f3a7393c9ac6e3a21e4b646744a5206174f90368
85435 F20110109_AACZAI topsakal_o_Page_114.jp2
bc36817fa518d528343a81ebaffbb920
72726338b2b30fbcedb53dbd6f4e77045b494e7b
2983 F20110109_AACYVC topsakal_o_Page_126.txt
4bc906d0ee891666ed66dfecf604d7a5
53a1b8be7d06ffa1a42ec811ada613e061a3d2c9
101253 F20110109_AACZAJ topsakal_o_Page_115.jp2
dbc936da7f8da55b9fe4396c1a3da586
5dddbc349bad18f46e8273f7278ba526212d94a6
6674 F20110109_AACYVD topsakal_o_Page_064thm.jpg
3678a043c8dbf7e0b42bd41b22c852e5
27b06b3ed8212f1d6a04005ba42ce5e3ccdf599f
31486 F20110109_AACYUO topsakal_o_Page_047.QC.jpg
39d4472a9f8290c400d4f29ae1245d69
bca3d0bf353c5e555e1213f399c85efe07bf073e
97018 F20110109_AACZAK topsakal_o_Page_117.jp2
ee4032bc0f79eba14ecf0d14e920978c
4e9dffdf390059c2d83731df17fa985b4865ec85
49740 F20110109_AACYVE topsakal_o_Page_016.pro
1e71264bcdc3a841870fe7642536f350
763e398de17b14208316d695aaef8675aa44dba0
1560 F20110109_AACYUP topsakal_o_Page_068.txt
6f8e8689af645040e930ef8f66523d86
223c06fbbbf5e369cfcb118cd34aff77b2f46e8a
90601 F20110109_AACZAL topsakal_o_Page_118.jp2
34cb2630eb71494ddb2a858746ff5cc4
418b50ff11db3fe609f614f053d09f367a2bae1c
106121 F20110109_AACYVF topsakal_o_Page_048.jp2
75e74abf2980e069a26f95ec5ab9afff
c44103aa556040259e6b89f83f368a7683f87229
1645 F20110109_AACYUQ topsakal_o_Page_073.txt
7aa1205505c8b8b2339a7d7f8670e020
f7af24525eb10546fc63bfc0cb5d3774003b007a
F20110109_AACZBA topsakal_o_Page_015.tif
8d58b5604674d04a17c0d4c917a1ec93
104252bffd75058e9df9dca8e1e7fe8dd760a7d6
95400 F20110109_AACZAM topsakal_o_Page_119.jp2
ceb951c1d05aba4c4256c65f92468af9
55b0478c46fffa70bed10989a64976404ea43787
46887 F20110109_AACYVG topsakal_o_Page_026.pro
1715b671145c80e87116ca122e0aac39
86dcf7394dbd8269d38fc936f69454cccc529dde
74999 F20110109_AACYUR topsakal_o_Page_045.jpg
3ae487f7341a1ee69f93fd998a51c631
242a7fdf853ad91cb01a2c7c59f9ffc059ba1ec1
F20110109_AACZBB topsakal_o_Page_016.tif
be04f0ff152cf93d3b0afda1e32b473b
156788aa31ec929f2b9996d1d222b64c603aeab2
98002 F20110109_AACZAN topsakal_o_Page_120.jp2
11a6d3f124490586f21a61d3ea786d4a
325731f6199d404b411d0f60ff59b6d4634c0490
86320 F20110109_AACYVH topsakal_o_Page_096.jpg
d99a15419e7b321a9c4b9a50dda9bd24
ff3e1c7c00443c8c2df9d62acdcfbe6eaf526363
61750 F20110109_AACYUS topsakal_o_Page_104.jpg
7ff36e64a4e83a4e9f700885eeaebc47
fe0423c3e5e8eab791df972ded633666abe7eb24
F20110109_AACZBC topsakal_o_Page_018.tif
1c1acc4e00e4a4bc33466151bd1eda13
2dcc7aa3762f2a2e641b43b2db2f8a00645d265c
113162 F20110109_AACZAO topsakal_o_Page_122.jp2
7875d00ec0dbbf3ca0fbd7e224acfe4e
f7b3855e531355863d1d71f423abfcda6f9e4ca9
65175 F20110109_AACYVI topsakal_o_Page_105.jpg
5f1099b8de003ac76cdcfa4447eb46cf
3cdfac3025e186f0a4b229927d70f3ae224283f0
96135 F20110109_AACYUT topsakal_o_Page_081.jpg
a4639b0d0706a2f88cc6076d9f024f3c
a1d1f5d133fad29d80ec174f97c3b010561a414c
F20110109_AACZBD topsakal_o_Page_020.tif
a62344d96ed8daa1d0e80cd7c8ed9c97
cd543f3e4404383e08db504a252be2a682e3f7d7
104136 F20110109_AACZAP topsakal_o_Page_124.jp2
da834a2b635059ccc986a33bf4bbe9a1
a211e008b0327184333fce21a1077231a4f66610
30550 F20110109_AACYVJ topsakal_o_Page_018.QC.jpg
c1d79358a5f38553c48f42aac98cdf0d
55319dc40496ea6eb7be978fd6c89df888993df1
54479 F20110109_AACYUU topsakal_o_Page_112.jp2
36b4b2cc2c7bd8399ff902a319105d3b
d62853f848d053af9ff24c01beea9736d77977d2
F20110109_AACZBE topsakal_o_Page_025.tif
3bdd92566529354779a8996281ed14a5
e614131ebc001336474f6f6b572f767ce28121b2
94341 F20110109_AACZAQ topsakal_o_Page_125.jp2
c51c98d0154b1bfbe2d06e4b96f8c48b
48fa6afbceb9daac1bc4eb90e2682cb31faceb7f
F20110109_AACYVK topsakal_o_Page_125.tif
9ba4f710d9cc89155373cff1f9da2c5a
eba5368fbda8f0a348645c64cdc718a327c4f25e
4544 F20110109_AACYUV topsakal_o_Page_104thm.jpg
5fe5e821d118ff0583e32319bbc8dda3
4d520dca41981c43eb76552e803f2af5038a88f6
F20110109_AACZBF topsakal_o_Page_027.tif
10e8be1252c381b84f8955f9747a3623
fd41cf88f23426105fd56e149f11a3bd6ecfac11
38108 F20110109_AACZAR topsakal_o_Page_129.jp2
225b098c28637298837bbf0c33fddf8f
10371b9e869217ba7cccc989de8c451684a3e700
26453 F20110109_AACYVL topsakal_o_Page_072.QC.jpg
b9070abb40f1f04eda47ad1466993cdd
ba53b30d14637e3394420176164b6fa5d21e18d0
6622 F20110109_AACYUW topsakal_o_Page_010thm.jpg
118d60db502c4baa0facb84a1a84f78e
edb259a86540e86db11ebe07ea84897115004c08
F20110109_AACZBG topsakal_o_Page_028.tif
7315dca026f858c7d906eebec0b677bf
4a2dedfe684874c7c79d37afcae6bacc7e8b28e7
6343 F20110109_AACYWA topsakal_o_Page_075thm.jpg
40b69fa199185f0197163e1c18a6224b
263b770bdb32d49d9f0249ebc02f47340a67a8ab
64780 F20110109_AACZAS topsakal_o_Page_130.jp2
c1472b58fb487013282ced88b873a7dd
22f629496328754c345ef1d85fcdb1978c37f655
45835 F20110109_AACYVM topsakal_o_Page_067.pro
0ad1b3252eae6be04395002249247662
47284ba4d7d28c5990e8f871e9312aabb19cb64f
81915 F20110109_AACYUX topsakal_o_Page_052.jp2
546f4763c26efb4754f4a8d1cd29feb0
3626150b203f561df6c14989bd0278fede765a22
F20110109_AACZBH topsakal_o_Page_032.tif
5fa3a7e54ea8634999b77930e03f6953
06a55a78fe4b7df7c6088c5517b2fcb2a131eab1
1916 F20110109_AACYWB topsakal_o_Page_080.txt
284febae41ca79efc202531b2fd75915
e9872a7d250ce4ac586ec7e179caf35b353b9645
F20110109_AACZAT topsakal_o_Page_003.tif
ea4a3fc680d914797b1e0aeef23f9aa0
b529f2a86c3d52ae09478342609b4ee2e9ee65fc
5361 F20110109_AACYVN topsakal_o_Page_095thm.jpg
4ec87893918b07652f3898d4a0709806
bd6a58e6e70135740f8af4d0460076ea6c6d09a7
F20110109_AACYUY topsakal_o_Page_090.tif
507c0eebb062b5d988bcfb8755ea610f
b3c242786790d7902511eb59ae06fbcb6c9279f6
F20110109_AACZBI topsakal_o_Page_034.tif
091f1b5057a52e40628c884ffe9c2350
231b72a850adb94df6ec434f7579a39191cc6392
F20110109_AACYWC topsakal_o_Page_022.tif
a0778a570eef87d87266efc695dd7afd
aa7b23e0c63a262294454a7e2801d07a53727daf
F20110109_AACZAU topsakal_o_Page_004.tif
857536c31d2c7f187064e6d02efd254a
74eea92dd21c7807ab4f27dc07cf86e405d3abaa
28351 F20110109_AACYUZ topsakal_o_Page_115.QC.jpg
1b75650d8373d7ae8b0474680acce52c
ce7d77f352dbd58425d2f1a687ba7ddb5aa68530
F20110109_AACZBJ topsakal_o_Page_035.tif
526a80016c4529f7b1ed90afc90b33d1
88ea173e54ec924e24c4a2ed34f0f8d667704536
3312 F20110109_AACYWD topsakal_o_Page_005.txt
9d6d833e65ebe5e494283c6de26f8e54
f06b1bafde38fcb172e173332f56236dd18ab860
F20110109_AACZAV topsakal_o_Page_006.tif
75a61d684a3e759b509056d54e8c2958
7d5ea9661181b26aa4adb7019c3b2cdd910ca856
37741 F20110109_AACYVO topsakal_o_Page_098.pro
bd8d05acae60def30891e73947f2c2b1
2f90f8094453edf530206ce310ca22dd08765a3f
F20110109_AACZBK topsakal_o_Page_036.tif
6efcb7c5606997f99309c228f4ba1122
375000cb5b1c83ddaae20b7ef90782ce40ba0596
37164 F20110109_AACYWE topsakal_o_Page_009.jpg
9ea427171e543859ff1d9aaf535d454f
94e72f2bc3d9326c20b7276808cce5719c14c9d3
F20110109_AACZAW topsakal_o_Page_008.tif
0d609f1042fcab3977e6dfa8a700ce19
68cf2cab3f6a0bc0163a03a74e2410a7a3553184
103705 F20110109_AACYVP topsakal_o_Page_027.jp2
183d7aaeb14e1923bbff56584d4f8bbf
ade72b58d6535f7c082594b736a4f96260413c70
F20110109_AACZBL topsakal_o_Page_038.tif
d655ddc0ab72a56ec6e0ae486bfb375d
8481eee9ba97bbf56a72dec05b77dfc46fec5a6c
43878 F20110109_AACYWF topsakal_o_Page_069.pro
9a3b2f428d5d5aa7376f085d5f046126
23a13d96dc72ec6bdf360ec7020255fa251351a1
F20110109_AACZAX topsakal_o_Page_010.tif
8c54c3eb599e305beba2de7e31814b2f
dee37b86e55eb21d5ae954d62219bbe846e1a28c
2134 F20110109_AACYVQ topsakal_o_Page_061.txt
17308f8cb91d71a5ffb3296d6a22dc3e
6e95d9a48431455d52759dd8733a96a768332eb2
98597 F20110109_AACYWG topsakal_o_Page_074.jpg
029692f0b02d2b9d340b42c8ea76dda3
64313ff26bdf470223abaa237859e94dd05ceaed
29893 F20110109_AACYVR topsakal_o_Page_032.QC.jpg
f24c7b226544a89b298ac5fc3afe60e0
e52b25ed5fe88273dd4dcade8b28cf51d1a1c519
F20110109_AACZCA topsakal_o_Page_072.tif
9e412224d84f857d87252343b14e28a9
d9a1b3ceac2293e6d96eddf4e4273bff41034109
F20110109_AACZBM topsakal_o_Page_039.tif
e0d213d6267da41528629c63be347b97
2dacb74f9118fd31b227fa57993247ddca5c3c16
92107 F20110109_AACYWH topsakal_o_Page_077.jpg
cef4c3c305c2839df8772b290633d000
4ce8bfe58c97ffea1c71cd911ea5a4f04f5b0688
F20110109_AACZAY topsakal_o_Page_012.tif
0565925aa1d1c6d5800bd7ada736744b
b39361cccdc7be63f1f0e8ec2004bb428300d122
100788 F20110109_AACYVS topsakal_o_Page_024.jp2
f0fba544d5f6f235e7a9dcb27ee72a22
3d43968d0c97423990f079bfbd98853b7cf66553
F20110109_AACZCB topsakal_o_Page_073.tif
ee5905c68f2f5c5b8ab55dc062bbc574
add34140a75bdacca11a1daaee15f3b15e545751
F20110109_AACZBN topsakal_o_Page_040.tif
10b74e126b3a50a17d287ef634cee79c
511ccdf2142f3b0a49337847a7b71cbd7b92da6b
30219 F20110109_AACYWI topsakal_o_Page_102.pro
d311c2870e541e96030540f7c50daec4
34c29a639bee0a801de154350ba654b3732c5728
F20110109_AACZAZ topsakal_o_Page_013.tif
51324f0cf0029476b8abbd3776b3a9e1
4aa1530db45a675b5fa82e850685ac574dfd956d
115788 F20110109_AACYVT topsakal_o_Page_065.jpg
340996b5adee88d84ef74885d31bbf99
22f7ce37a5913e87bdfe3dc15111e199fba46dfe
F20110109_AACZCC topsakal_o_Page_075.tif
4ec9e3ba6ad73da532b7621e094b4f72
98317d27b357fd7c98ebbd3434981a3687d58db7
F20110109_AACZBO topsakal_o_Page_042.tif
643426737db62cbef3ba0f481d2e4b9e
73b51da80990752f38c4525a3b7e291a8e896fc6
7722 F20110109_AACYWJ topsakal_o_Page_090thm.jpg
3e35b56fb27fad47295804ea4efb0dee
3ec73a0b11f62d5f5d55befe90e2e314711dfa4b
2015 F20110109_AACYVU topsakal_o_Page_093.txt
6557bfcaf23c4ddca67b71d285435447
0a0a2137a3c3d5eccacfda38612d60ccc0877a8a
F20110109_AACZCD topsakal_o_Page_078.tif
41328a51c143f1a49e30e1650fe79873
8870257baf94d9c44c43b7cfdd75a8d9a30ac668
F20110109_AACZBP topsakal_o_Page_046.tif
ba5986d5e1df499c158fb65a4fea289a
030111f7405f1a449bf1a5ecfa607f81d15ca377
21149 F20110109_AACYWK topsakal_o_Page_095.QC.jpg
30bb9d7c4ee247e12cfe79ef5dca9502
3687eba7b87bf9ffaf82950f8294185409c3797d
2109 F20110109_AACYVV topsakal_o_Page_019.txt
e753fe3ea0eb0a2c9e0448b520a9097c
e8ef9ad1b6a01b92054f0410439f69fb7961f883
F20110109_AACZCE topsakal_o_Page_080.tif
0cf368f9eae46162fcdbf0121602ea53
5a7c0dac44c60b6503b6c89d586a70526af11269
F20110109_AACZBQ topsakal_o_Page_047.tif
66f4445e7bb629eecc0cb89124a3b616
75e944c3ed09c1bb7c7b6a703697f4411a3c2a7a
742845 F20110109_AACYWL topsakal_o_Page_073.jp2
a6f9c1e47e8d1384062e43144d9b402e
bc24fbf70a09974ef0be16842f4e8833423cb8e6
50516 F20110109_AACYVW topsakal_o_Page_082.pro
40902aef6281371a04cd97e977776b19
79aa0766eb98b24a1b01bbe1f25fcee2e1d20fd1
F20110109_AACZCF topsakal_o_Page_083.tif
26c582275c2dab15695f071de546a9d3
f862bd3f14be7078d5ae73c555ab2d6187664bed
F20110109_AACZBR topsakal_o_Page_052.tif
984b825cca9558fa4956702a9681e89e
179aabe2bc21d826baa380a1b820309aaba43481
151831 F20110109_AACYWM UFE0001210_00001.mets FULL
5d49a7a9e4efc10e8717ea65cc91ca57
b9967c1f0ac6294b9f565225d0cd96af9a11e280
104025 F20110109_AACYVX topsakal_o_Page_047.jp2
a1cf4371a2247f5c3f584af1a4c65a92
19cbcf8d67390c2fe7868685df22941921aa1776
F20110109_AACZCG topsakal_o_Page_084.tif
2218fd0dc919f73ebf9f4419b5f53535
9b3aaddc710babeb962c1fe3e26511a73bd210c8
94609 F20110109_AACYXA topsakal_o_Page_043.jpg
9cdef4fd9b4a92045fe899a15969ef48
99da0eb8b99a1a14323ae87a9c035dfdfcfca332
F20110109_AACZBS topsakal_o_Page_053.tif
b4f1cc9bc5be243ab7fb397584fc7b72
a7eb3429958efb419ed1353f8024e7a2de8f8e9e
F20110109_AACYVY topsakal_o_Page_103.tif
5ec99e4ae1210b2a8575f13b2ad61ae4
26db66890788890779b11b246df3dbe80dc280d2
F20110109_AACZCH topsakal_o_Page_085.tif
a8a599b10435aad4a62dace9934bfe98
49f839325d4e11a9aedc689d195a4d048062add5
78481 F20110109_AACYXB topsakal_o_Page_049.jpg
401761a793a458012e5fd55395dfe3ab
4bac62a939afe4dd836f43872b7e1d6069675258
F20110109_AACZBT topsakal_o_Page_054.tif
df2d711796b48c91295d00afdeef7e38
c7f38d66cae2145a4ddbac919831a0d49b0a0b0a
104344 F20110109_AACYVZ topsakal_o_Page_074.jp2
db395e044f1917c351b075b3a423b2dc
55dcd912a972751ce6814001896a16ee8a782125
F20110109_AACZCI topsakal_o_Page_092.tif
ee7ee39c3a88235fd5a7ad91489bb5b5
0de22f979339ffa8eb88da549ad44f193c42947d
76053 F20110109_AACYXC topsakal_o_Page_052.jpg
d22200c53620ebfe9d96ff3766f1c1a2
68eb0a3514810a16d94a7d0f623cdb80d2ba9d72
F20110109_AACZBU topsakal_o_Page_056.tif
81c7966fa4b572611e088fe9dd9d965d
453d29375402c97956d67804bfbb0d80791e4ee3
F20110109_AACZCJ topsakal_o_Page_094.tif
de9a472de6a9f7164c364dcb55d914da
1757d2bf64ffdd60731769b0759cfa01d0e294b0
83280 F20110109_AACYXD topsakal_o_Page_053.jpg
84d4f0fe910cae7177a66045eb3943ce
7ee747227d94122e2f6c96a1f5370f229172beac
F20110109_AACZBV topsakal_o_Page_062.tif
34f8e319288b1cbf17aa03e4aaa698f3
df4d4c5cd29d42909d8ddce9eaa2c25cef87e967
141704 F20110109_AACYWP topsakal_o_Page_006.jpg
64f32ab38429e7d2d72dab5c05e33031
bf1a58146ee6382c41793e113889576f16c56fe3
F20110109_AACZCK topsakal_o_Page_098.tif
5a9753a704f21c62f0ca676d0217116d
64eccba2d53e8a6775ad6c3ad97c80e99ee4b84e
81392 F20110109_AACYXE topsakal_o_Page_054.jpg
4248eec0f8dd447a38bb0f6b07eb89eb
b888a75dfbb69f93d78945131120cb87507a2941
F20110109_AACZBW topsakal_o_Page_063.tif
9bb92e8cd1ad86b650212afe2161fb95
c22d009bd015bf30db5d8e8ddb96b7e7cf43d2d9
82121 F20110109_AACYWQ topsakal_o_Page_012.jpg
39c059b0f7b0677aadd30e7032e88a3c
7f7844438bbb43ff075dea37e8cbb9114421bf6f
F20110109_AACZCL topsakal_o_Page_101.tif
018cb69eba0de42a6db403c2d34cd173
9c7ac14aabc669db92d0d34fc3d8060948702613
72285 F20110109_AACYXF topsakal_o_Page_055.jpg
30ff1ced00dca6b7c99bf1ace8037eb6
5770d3d326c9d91128a3e2772e18004fe37d4768
F20110109_AACZBX topsakal_o_Page_065.tif
b16d5736d5f71882d4b8664d4f5620dd
ab8a02f942bc38648b2d10a53c273a895a4eea55
102134 F20110109_AACYWR topsakal_o_Page_016.jpg
2abf7f78f54f33ce921fdd6b96ebaed5
a493db9c965f23177ccb8ef08a0a4cbded2f3462
73873 F20110109_AACZDA topsakal_o_Page_007.pro
368050e4e35e04f20a8e5ee0e94861e8
0f8c3c91351b7753092f3d7f6a79be079b174fa2
F20110109_AACZCM topsakal_o_Page_105.tif
84cdd436e696e6cb546ba8b0bb3fdf7e
079a08c939188586218f20830b42a94ee690eb2f
88551 F20110109_AACYXG topsakal_o_Page_059.jpg
30b98a8f8bbc5c2a4e186b670e53a1cb
d226a75fa60882255fb19408764817995d510a5b
F20110109_AACZBY topsakal_o_Page_067.tif
44fc968774f128910ee1d2885a8251c4
5cb213a1fdb3c49a2153325eb6d01c54a16f2e82
97165 F20110109_AACYWS topsakal_o_Page_017.jpg
b563db9253bc776ff23e21a52f266fff
27c5e89edae7083b31cdc3cd97ea281dd0575abc
56496 F20110109_AACZDB topsakal_o_Page_008.pro
2068d1c788e7b5efef8186af6db76ee0
2063694bdbf48c6da88b876b9601c254c8a158df
F20110109_AACZCN topsakal_o_Page_106.tif
764c21faa4214e4c848f2ecfa19088ce
1f19b8717574cb85233e44385ff0dfb5d0b949eb
107809 F20110109_AACYXH topsakal_o_Page_061.jpg
e7bf518b9e12d7d2d2ba5421be6cda66
6c58c06f6c7ab249f49355c4fb30551f385efe92
81763 F20110109_AACYWT topsakal_o_Page_021.jpg
236cf1edb5f52e8e60917d8a823441fa
baf587260c9b2926e5f846f45f3e1e8613d637f2
24096 F20110109_AACZDC topsakal_o_Page_009.pro
59b3a08a88be12a56bb0497d45f73a02
6c95ea9a2264f2f2f3d497111a6b0ae9dbd6ab1d
F20110109_AACZCO topsakal_o_Page_111.tif
d6011e8b3aab095d0ce728559ebafbea
a04aea6e7c7d993f40a69e94b65d05a57e46c67c
97900 F20110109_AACYXI topsakal_o_Page_063.jpg
4d62540aa457eff09dd9fa3b1cd3c040
0f4ca3dfef90cf895dbe6db94a4aa4ccd454bd28
F20110109_AACZBZ topsakal_o_Page_071.tif
03355bb5d239bfce3bc3bde2ab2a0999
edaed117797f3b211dabec1c4aada896c7014f2f
82926 F20110109_AACYWU topsakal_o_Page_022.jpg
0383f1a8c72c1f55bb8664f7ae731321
a4f5a0a3d300d7c1d51ecb59934c7a9b5cf1286c
56599 F20110109_AACZDD topsakal_o_Page_010.pro
80a609cb2aefc6d2428368e0188d61b9
44a09f0963c681dc1f4b1b8eb7e92e6c4f00280c
F20110109_AACZCP topsakal_o_Page_113.tif
3cdc7aead9fbb9d05d381833bd62a988
593580c5898474d076f91c4cf7a54e3671fb2d82
108999 F20110109_AACYXJ topsakal_o_Page_066.jpg
30c99721ea56318bc2e69f6061057005
af4d81c351c288d35995645db4bf2a3616921f48
103791 F20110109_AACYWV topsakal_o_Page_025.jpg
b8f33abe886cb0a4df3a66254688de88
5eb947449deb95b548683b899a56819b3b08591d
8203 F20110109_AACZDE topsakal_o_Page_011.pro
d191c008860600f525d8e76c7e344caa
089aceaaa8ad5ce49c5dbfd771ee3e1067280823
F20110109_AACZCQ topsakal_o_Page_114.tif
0eb2258e7d31a332478690cdb05d2b27
73360b255419c793154adf5f954bf5af7fdbf4a6
92903 F20110109_AACYXK topsakal_o_Page_067.jpg
bb9c3cce1bbe34c5b32ff310951708d8
e236d2bcf92f9f6efb1aabc3d4435e6450baa543
94558 F20110109_AACYWW topsakal_o_Page_030.jpg
6fc80c3d964c5d71e1445bf45bc7d57c
8c495d48c5e43229b1f90a717a6ee5fe4bc0fe35
20523 F20110109_AACZDF topsakal_o_Page_013.pro
5a678525733c530b4d5f8e8722046e1d
e5fd99c3a626a9af9866d1202632a774511f92a2
F20110109_AACZCR topsakal_o_Page_115.tif
4d5b2a164addb11133eca37782228475
35526616dce517d66cfa03f7a48c331b22ebb53d
89141 F20110109_AACYXL topsakal_o_Page_068.jpg
da856367daddc6fdf96df60f12a62acd
f28062836749139733f022a27724d477e472678a
95071 F20110109_AACYWX topsakal_o_Page_031.jpg
1c39148ae4aab991cba40cf990dd00fb
ee2246b372a2c9d0608f5f9dd2f3c2d940b183ab
61988 F20110109_AACZDG topsakal_o_Page_015.pro
de61479525fbb60b312c1f9315c83a10
00dd2448777b5e9a7acac046973ffe757fb53353
87697 F20110109_AACYYA topsakal_o_Page_100.jpg
3c11f7852b4590e8e4eaaad61019ca20
402199fef33d8d408695def5ae0ccc848956e505
F20110109_AACZCS topsakal_o_Page_116.tif
ebd3a61a3406a351f76651f295beee8d
0ce84488b9d04a0d3ff1abef9f37cfb89eef9fff
90560 F20110109_AACYXM topsakal_o_Page_069.jpg
8ee1cc977580c766a2981bebccc619b5
ff94af64c80fe053a4e8e357837b752176d6fdd1
93774 F20110109_AACYWY topsakal_o_Page_038.jpg
d981e5a650c115e1657876e7aae69d6a
2ec01bc3b7d1498b29ee97065a652b171c316dff
55317 F20110109_AACZDH topsakal_o_Page_018.pro
b92e79fbf2dcbd04e6fa1224c61b8caf
3afb7ac1176704eacdf77047d1178ce6a80112c4
86990 F20110109_AACYYB topsakal_o_Page_101.jpg
282733b389b6f65bb64c8c102694b6bd
4c31aaddcfd5b272541a3e71fde25740194a4436
F20110109_AACZCT topsakal_o_Page_118.tif
1b0d01706784167b062ce6d44ce1eb9e
164601e2c31c244df07f6b98f64bd6246ce5b638
119399 F20110109_AACYXN topsakal_o_Page_070.jpg
2c761fe0e71be7b904205e9df5c27f7a
18e1c160453339a0e67e7ea60230120d6a94e8f9
74466 F20110109_AACYWZ topsakal_o_Page_040.jpg
e4be9a39852ffb95f75c7f0f8dc180b2
c4dccd2a861bfb362351924d718f6881b8ef4a42
51017 F20110109_AACZDI topsakal_o_Page_019.pro
cfd3c39296ecb2d58ae47777b1122491
93cb257da23bb675c0444367b05392515918a101
82872 F20110109_AACYYC topsakal_o_Page_103.jpg
1795a2fb0799c8fbe180813d34b2e99d
37f8c80760b6f4d96d7f179c22eb3fe4bbb8bdc0
F20110109_AACZCU topsakal_o_Page_123.tif
6bd0d9492ae7bf06c5d6a2fcd38379ba
ff3f01a7bfe6d888c4557ac85e8e2ce7e8c543ee
97157 F20110109_AACYXO topsakal_o_Page_071.jpg
4f15b9cefb03aa989ae6e843b6d382e6
d7ad744d85497798bfd8347b1fb9feb092082c5c
52997 F20110109_AACZDJ topsakal_o_Page_025.pro
7d8af9512d8ac9b91b8ef570bb24b4eb
ef8e1a64727ad4ea3597bed0340758f7986b97bb
25002 F20110109_AACYYD topsakal_o_Page_108.jpg
04ef09335fabf796a95179688beaf544
47320a86b6afc187dff0a469dcecb5bee222aca8
F20110109_AACZCV topsakal_o_Page_127.tif
e4d81c16806c36294ab2029a90de20f0
681340e5f6e7aa24879f2b517bb65b2053889661
79838 F20110109_AACYXP topsakal_o_Page_072.jpg
933f92e2521c88aeba3d7d5f3fc1d954
58505f022b1f6db0e87d74f6d100ef14d3ac664a
48195 F20110109_AACZDK topsakal_o_Page_027.pro
b515ce07603b4043dd840c0d16d2869d
7b2fb31bd9d9bad41b85f64060404c38b7995ccb
76493 F20110109_AACYYE topsakal_o_Page_111.jpg
0e4b1da94695708c071e6b4d4a693a22
58dc808fe91d7c45c7beb4aa010cf9b076fe0969
F20110109_AACZCW topsakal_o_Page_129.tif
118e504ac7cb2fff860afb00b9d2035a
f8c3eed9d75fcc00af0e3dced483875e655a43f3
46170 F20110109_AACZDL topsakal_o_Page_029.pro
ef126dcefc8b2f80572fe2dd391aeec9
5ccfcac869e23a78f065ece0c8595e7b6316ed17
80205 F20110109_AACYYF topsakal_o_Page_114.jpg
eb88aff90f7c17f55f43bdf3198181bc
0d6ef32f2c5372f6a13d14375581dc5b45cea0a9
1203 F20110109_AACZCX topsakal_o_Page_002.pro
f4450d58ebeb80319d6350b77f7c9cc8
9e40aceb1c558ae4c253f76e07d25ef369a3946a
78520 F20110109_AACYXQ topsakal_o_Page_075.jpg
b9e304990003eb8cc6f3e4b0739ee946
93f1623cde5dca7ed72e805cb7fe308656be3d41
45489 F20110109_AACZDM topsakal_o_Page_032.pro
cca08f31e0fb61749ce6a577edfe8d16
ba8c54c369c6fe00d5a9092664c87b4b5449726b
94345 F20110109_AACYYG topsakal_o_Page_115.jpg
8e8adf80a5205ce613b4f0ee49061866
342d3da9c0d32dbab6f6942d2051df935aa7af3e
79208 F20110109_AACZCY topsakal_o_Page_005.pro
830f1f1b24b7e962226b970c519946fb
80fc2c7f1ffdbc3e398f4dfc03aef2adb9c7c7ce
101467 F20110109_AACYXR topsakal_o_Page_082.jpg
11308e4d9b575d3cb848e21db318fd15
1c3aea721a7d54545730ca784ea17a1c7bb84e2f
51402 F20110109_AACZEA topsakal_o_Page_084.pro
afff2b1da9f425be723b272cfb27a357
6f0bc72ec736ee418fe682fcde6380d917b21064
26059 F20110109_AACZDN topsakal_o_Page_034.pro
eb7889010101645e7c5c2b3405ffab20
cb354e21cf467d69f8eb333f75855cd5243710b5
98765 F20110109_AACYYH topsakal_o_Page_121.jpg
f2b45fda3be511905bcfb584355b4184
92b0e487e4cd911c945c18d7dbbab7a092ed277b
100260 F20110109_AACZCZ topsakal_o_Page_006.pro
f83c6f9a52287c92ab16d1cde6013297
65a76c4bfcff93f0194eeb55650040a8949b7b53
104822 F20110109_AACYXS topsakal_o_Page_084.jpg
4df516d1841ded4d6a61a09942035d3b
79b3c8264d2f28269edf1972bd957ad1fed4ed70
45475 F20110109_AACZEB topsakal_o_Page_089.pro
d5fee0f020d415410a385ceb9c5b03e4
578a3b9ab9f09b5fc82d1228e44c082f7432310c
48347 F20110109_AACZDO topsakal_o_Page_035.pro
cc05812d5160b8bb1f9596967a43b05c
25303c7d8fc3bffbed54a604b415b33c8a89b30a
98609 F20110109_AACYYI topsakal_o_Page_123.jpg
616331b9bd318bcc0ef09ea9dbc8b1a4
558d5acc336672c4ecafeb864a6cf296f19ffa45
98968 F20110109_AACYXT topsakal_o_Page_088.jpg
b95493616f01b7fd09fd56adb2f3e88c
a4ed1b6d17b4c15c385c18925b90ce3abcabe329
51835 F20110109_AACZEC topsakal_o_Page_094.pro
28629f9cf392e4d933b43f2cab053174
322061efc2d8ff79f16233063a35613c40720389
46456 F20110109_AACZDP topsakal_o_Page_038.pro
46ebf8d6aec5a1415e1b51cf719551ad
0a6e3f6218d77b348fd5c0731af5df89d5e803d4
102835 F20110109_AACYYJ topsakal_o_Page_124.jpg
13b59603540d857dd4dc5b0107fa32e6
04ae9cbd941e44e9fc06e6cf43d50eb48a4b4d7f
78480 F20110109_AACYXU topsakal_o_Page_089.jpg
376c23b59a30c2766a01d35313d4053a
6d7985652840c37612fb947fd2658841be84b1f1
31581 F20110109_AACZED topsakal_o_Page_095.pro
1acceb196166d09b7766e7e3a1c0b2be
ddc27323fdc4c33ec5767fd45170fbc834a12f8a
57728 F20110109_AACZDQ topsakal_o_Page_039.pro
4cf204e53a072a43dd0c76919427402f
16f26b5d269741bc4ed4f64a63d5878142677a79
112117 F20110109_AACYYK topsakal_o_Page_126.jpg
044a471951cc2346b5a418765185d700
412766394be66e38cd25b0ccae7333cd69bdd2d2
95694 F20110109_AACYXV topsakal_o_Page_091.jpg
004897c2055894bfbf7cf011f97e606d
781bd737f6099e4be9b186dd3d65270d3be83269
12440 F20110109_AACZEE topsakal_o_Page_099.pro
b9e4047ba7fe6d70694adb42b1057af9
4056f9f3e507093225f19c045a4131d49f7ae8fd
49306 F20110109_AACZDR topsakal_o_Page_041.pro
d511ff9719d54c365bebb1bf0f552967
564dc5d72964e773fc3e19c5ee3445eb265b6a99
112012 F20110109_AACYYL topsakal_o_Page_128.jpg
2615e0dca33c3c82aa0c040846cc12a7
9561cbcb716635655c49e4a927f6a6ff5cb6b578
102438 F20110109_AACYXW topsakal_o_Page_094.jpg
7a3ee32d21d15171133c3feb2ad00b6e
dae9bc541edb7286104c4fbbcbda218c2c7a0ffa
40288 F20110109_AACZEF topsakal_o_Page_100.pro
304cd6c1242c928a9713803c34f70f31
8e20aa9ae9869aededa1bd83ff7923e5348bb908
98417 F20110109_AACYZA topsakal_o_Page_032.jp2
2a0d7b657c4b604fbc3c01958de8808a
c07970e544c68df17a587f07bb7d5e1deee5b8a2
38899 F20110109_AACZDS topsakal_o_Page_044.pro
3d6bce140a81e593efb4c76d71fd6bb2
20f1885d4109927cc32ee84368d01c6a3a7eca38
38837 F20110109_AACYYM topsakal_o_Page_129.jpg
31cb0b3e520711548c81e4fdf38c1140
e61fc36b0b364a1092734513e52d215f5c8bcc7d
64801 F20110109_AACYXX topsakal_o_Page_095.jpg
d3353ebfdedbfe75d0c3a8eea93d072c
9f5b5daebd1c367a88506f6de76bfd2759e733a7
30211 F20110109_AACZEG topsakal_o_Page_105.pro
64a38b02973e02ca9b6a603fd2de2d97
e6a2cccaee63159c1bdc61cfcfb72392513d2994
101159 F20110109_AACYZB topsakal_o_Page_038.jp2
0d16a85123403308ab27f3d2534131a5
63f1b2e7a9be0ba4a6f8875ba7eb2d4db5e990c1
49687 F20110109_AACZDT topsakal_o_Page_046.pro
cd70a56bb3fd97707cb14ec6cc63d4c8
ea3c11a219c3d7d4eea6e48a9dc6a21452930ccb
1051986 F20110109_AACYYN topsakal_o_Page_006.jp2
5934fe833b4e1c0332a975eabc54267c
fa89ef4d359b8d1662280e2767ed2e5ff61eb1d9
44495 F20110109_AACYXY topsakal_o_Page_097.jpg
b0260ac53ba5d7d410abd45ef750b144
b6afa0ec7b5de09b85d05c54ae97d67dd50f47da
31749 F20110109_AACZEH topsakal_o_Page_106.pro
3e18d3b6330551319d58879571887242
c023b42518cf208eba4080d6c45770475ff3ba07
120533 F20110109_AACYZC topsakal_o_Page_039.jp2
c685e7ad2f1fe0a1d3c02f694d90acbe
d0792060e203b70c51ce09e505333d9130a61db8
47809 F20110109_AACZDU topsakal_o_Page_047.pro
86aeb5ffcdb531d81c9977afc5145b2b
8c996a4abc772ca5a8b1a6e5c6bd0b8968e00d7f
1051978 F20110109_AACYYO topsakal_o_Page_007.jp2
db01909d0e2db9615952fcf0f05ccedb
0880a20cb799c4ad8454d5b65702c13adccbe679
79147 F20110109_AACYXZ topsakal_o_Page_098.jpg
30192e7221a0c7de77bc6f63ed67e2c3
f591be6493dbbe4cd2a07c565be5e8b60ec78564
39918 F20110109_AACZEI topsakal_o_Page_110.pro
52b7e5baff115bb586554b4ec8a0a65e
7a29ff41f91b41e5984d41b0b4efc8801c2134fa
739905 F20110109_AACYZD topsakal_o_Page_040.jp2
b226cf106da23dc3ae07b8a77a479036
f8157fd6af6cea064700dc09ff27f1764b190727
13770 F20110109_AACZDV topsakal_o_Page_056.pro
b04027ff800118e07f7fea9bddcce9fe
2e0ba940c34975f12f0d05ef52814234b82bdcec
1051960 F20110109_AACYYP topsakal_o_Page_008.jp2
6bcd43ceff4bb9600312da3a626df785
48574c95f38e4ad6b178653e7f8fb796b4bc9661
45867 F20110109_AACZEJ topsakal_o_Page_111.pro
bc111e2bb650c564e05c970946bcf976
e606c3576f64708492569f6cd535f65f2433717c
853211 F20110109_AACYZE topsakal_o_Page_044.jp2
48ba91551c4f6ee30c0509d4139a42f4
c31a265610f2aaef91d75377a7b00a78aec48337
59930 F20110109_AACZDW topsakal_o_Page_065.pro
4c40a6b38bb1acfb0e98c52057e8bacf
eb5fa04c70169768bb0a12f000f5e1c1aeb422bf
650028 F20110109_AACYYQ topsakal_o_Page_009.jp2
bb699e03e840769bfc71f196588db39a
d3cc2ad9fcb4d91469000f0a211a7172bc80d36c
29399 F20110109_AACZEK topsakal_o_Page_112.pro
0d5a06a7e85f2cad821d807557fb9863
4ee7381b13a653c7775840a56cd80d98403ffd2f
798513 F20110109_AACYZF topsakal_o_Page_045.jp2
a50645f893b34902e616bbf97bf81eca
954156534462eece8320b0d55e08d19caeeb2473
47569 F20110109_AACZDX topsakal_o_Page_074.pro
49c57974888c8fa7a8b2109526b075ff
a0a1afda44b9c0fa0b59f382a97bf8cfb0686041
36067 F20110109_AACZEL topsakal_o_Page_113.pro
4b4ea9294b411b504ed44acde58febb2
5a029a9e625aaf40f72a079fbc17f4f660df04ea
1051968 F20110109_AACYZG topsakal_o_Page_046.jp2
e067b3482132ae7395f6da47f2128cf6
e4cab3efea2b09a1fcf171fcca25f17a0d4dfa4f
41220 F20110109_AACZDY topsakal_o_Page_076.pro
a6923ebd64917259914897c42c3d5724
c090dafceef4ffd46ba8b95ee792da99fa412848
F20110109_AACYYR topsakal_o_Page_010.jp2
fde1ffdb59c44842ec93802c1fc38cc7
fac8a7ae4ed0fc569cbfea418158c56230cfe2a5
941 F20110109_AACZFA topsakal_o_Page_009.txt
dfdd599b3f54937b73df5f4412391c95
03ac87dd61df1035f9290a2d912db5c05d155baf
49094 F20110109_AACZEM topsakal_o_Page_115.pro
88d6cde788241bab4ba7c2a2a81250de
2afc53c7be355c4614fe8e5c4c3d1475026bb50f
977272 F20110109_AACYZH topsakal_o_Page_050.jp2
f2efe9f198044a5648d0ad0688348a10
e2a42e4ac7478a47d8586d1c693269f8ba02a470
41162 F20110109_AACZDZ topsakal_o_Page_083.pro
06c86a72097e3c865e2023a1b1cc8fce
55b7d913595ad3dc42ff9acba521c4512d75796a
85540 F20110109_AACYYS topsakal_o_Page_012.jp2
2c7a14c479f75cc3ee11b9d756b4d845
459fb6139e2b4f79000b828efc5d0ab942506588
2248 F20110109_AACZFB topsakal_o_Page_010.txt
1448b27a2a4d7a821567a5b256c26cc5
aca7577d7d3471581b29b547518eb49590a4649b
42477 F20110109_AACZEN topsakal_o_Page_118.pro
9fde1543f971f486d4d1b2c471c60c1b
99391a62bf265b7b91046d0a44fa03719fae2bc8
90578 F20110109_AACYZI topsakal_o_Page_051.jp2
cfef1b570b48bf3ff63329722bb59568
ae4a3e3a3865c5ee612c244c07e837fe17e5dcbf
88173 F20110109_AACYYT topsakal_o_Page_014.jp2
84b2e7c8ac118e9857eccfc8ab5dab19
f62594b38132b7cc75c745462d5e3f4a1917b2dc
8313 F20110109_AACYCA topsakal_o_Page_001.QC.jpg
35d61b123442dbabad106e12b2991be1
23157d05ad16c47060b2212705559848e94f12bc
1713 F20110109_AACZFC topsakal_o_Page_012.txt
a67402c61545b6f6a7bb48dc3400a827
dd7e76e9b346045fc9db0d24dfbde492c7b8a785
45136 F20110109_AACZEO topsakal_o_Page_119.pro
cb8a2f0d7eb0f24b737ad811211bc993
96f94c655dd6bd0d91952dd3f3530208268d6293
78513 F20110109_AACYZJ topsakal_o_Page_055.jp2
69d154c7ce6f21a3d31e10350f795759
af32c7f161bcb6575ce6da9a7194ca55b540c393
127484 F20110109_AACYYU topsakal_o_Page_015.jp2
584c38dd9c9a320df8ee2e616c3e1afa
a562d73baedc742d46b237115f1dd22a4c6f4eb7
F20110109_AACYCB topsakal_o_Page_029.tif
0d79441e64a8832a86918b5e0b476100
856a90d5677b1ebb7ec0b451b1e6c54c6328665e
1925 F20110109_AACZFD topsakal_o_Page_017.txt
bee6c70dd65a123ee360166151c3c0b1
ffff980a6eae0bd5de8073e7d836f91ea1833fa9
49056 F20110109_AACZEP topsakal_o_Page_120.pro
41d54949f1429924e579006549dfff5c
1a48549f248a152a74e029fc0a38a61102ae97e3
34318 F20110109_AACYZK topsakal_o_Page_056.jp2
6e29b026821ad104e9d54a4f0c62b060
eb7711b98bff3f28e4cc9e6ded06a31ab2a7137e
109750 F20110109_AACYYV topsakal_o_Page_016.jp2
86b3a1cd4bc6dae7fe338856b57be2e1
8681a9193a928f8fba8fea13e59701d6bfc5787a
40237 F20110109_AACYCC topsakal_o_Page_023.pro
f5fd3e32ec101fca27954e166b3c16ce
d9057dafb58d7314ca6155026552d72910a8b608
2330 F20110109_AACZFE topsakal_o_Page_018.txt
0cb421ec198e09c170ef9021583fa78f
1d34c55fd66d60f3293f1d9fb42e023f00a7fae4
54833 F20110109_AACZEQ topsakal_o_Page_122.pro
52372b87ebeb314f1b6defd3ef04231f
ac0ccbffcb52c762ee46d77a8cde75fab6cd3934
817547 F20110109_AACYZL topsakal_o_Page_057.jp2
0a39798fd63b288603357f8ae84f0497
81612ade9690fe3f5f2bee04917daa470879b43e
108086 F20110109_AACYYW topsakal_o_Page_019.jp2
189f689058e9e92b17ed3fe7b2ba402d
6e196f4c9cc1700ad0756462c44d9789fba707cf
102004 F20110109_AACYCD topsakal_o_Page_041.jpg
23d5addae0e73b32f561ce8e9df34e0d
1e3fa89db441469a373fd1f26031b509fc6ee4ef
1923 F20110109_AACZFF topsakal_o_Page_027.txt
eee8fbfa096b4bf64571404b15f5aa31
6b1fb78d353cc939cac84e6cb855839bba310487
47096 F20110109_AACZER topsakal_o_Page_123.pro
765ecde97a226524b181795c2f51f15d
a364f94f0bc11bc1a0bd2ffe2e910325a273153c
88746 F20110109_AACYYX topsakal_o_Page_021.jp2
6e454d1f1000d0798cada7abb97e22cd
139c6f7e72927e7299e8c0843480229d587897a4
104860 F20110109_AACYCE topsakal_o_Page_058.jpg
8a78a64cc7900770e9abfdc98c42c20b
9abba590b7bb41bf9c2863e8f8fc30b74004ad5d
1969 F20110109_AACZFG topsakal_o_Page_029.txt
fe7ade917af344c1fe4d2153b0d0805a
3657851faedfb59c7989f9a1920060636977255a
50660 F20110109_AACZES topsakal_o_Page_124.pro
4b4b46d0e1430e285ae046f41d6df176
513c757d4f9b644635ee5e3538f13ea56905ccf0
1051976 F20110109_AACYZM topsakal_o_Page_060.jp2
616a8412a31eea525ec0d81de56d4310
48589bcf21393ced64fbd52cc6b688029dbd8a50
996216 F20110109_AACYYY topsakal_o_Page_029.jp2
1294054f878f3a860face295bf8f7f78
5bfbbcaf9c331b5434522ca743a7c950703b9cd1
27755 F20110109_AACYCF topsakal_o_Page_104.pro
740ece56ddc16e12885583bc94bcc07e
4487bc3c91686c7db64303c397de39ff02762ca1
1110 F20110109_AACZFH topsakal_o_Page_034.txt
5cb8670c6a349ee9571afeac1d14f278
0e0c1539b2d9e8c3447e8d95913e229f6f5ad2dd
1982 F20110109_AACYBR topsakal_o_Page_062.txt
1264c288a4e6c2149d4934623b0588f4
d9839ac23dc0ea2f8bdb92f0e67b5fe018cc2088
43840 F20110109_AACZET topsakal_o_Page_125.pro
d408ea7fe4397b59056da56adb8a80be
e520249ae06ad7938b87ac267cc92d283cfc6042
115965 F20110109_AACYZN topsakal_o_Page_061.jp2
40c7f50ec89ab13bb84e7980ecbfeff4
21ee24b7952499287b946dc71eef9340fcf5daef
100935 F20110109_AACYYZ topsakal_o_Page_031.jp2
21e9b52858abaa9c2a4f8acf655d49ae
3a102980f51d32b4fc8e076a27ac4c4ab98b73a7
34785 F20110109_AACYCG topsakal_o_Page_057.pro
83665ab8a928b41e445947723441a2d3
c8b2a9677c711d282031496c830f28cb6dade25d
1922 F20110109_AACZFI topsakal_o_Page_035.txt
038613d420a17d8e9efbda5f8ba20357
9a3ef051c0ff8151991e780eb43676842979929e
2466 F20110109_AACYBS topsakal_o_Page_028.txt
537dc2667313349fb9eee96a22eed08a
7418a42ab87b9dddc1303b59dfab8a80b53cae9f
14169 F20110109_AACZEU topsakal_o_Page_127.pro
5cc254e3daeebb9df4c856b963496a02
f681151cb17f5ffd63aaa5e963383b143842cbaa
974686 F20110109_AACYZO topsakal_o_Page_062.jp2
e8c0fd9308f46ee118b6e23ddf34705d
6cd4b7d60dbc6e46d1e37f12ad1477771b92d3ec
F20110109_AACYCH topsakal_o_Page_079.tif
16803518d19dfe4f08dfcdfc02695b5e
5c02b52ab1adc5a06f9d7ffef72218d981b23688
1801 F20110109_AACZFJ topsakal_o_Page_042.txt
b97194fb8d5b086fddf53997c7e83e76
b4a53df1f00bae80bc0ec356e46c7dd4d6822e9c
34555 F20110109_AACYBT topsakal_o_Page_084.QC.jpg
05f75012bea05da95371f5c4af5fceb5
d6bfd62f328130562420d7116af801d98bd3944b
52444 F20110109_AACZEV topsakal_o_Page_128.pro
dad37097f1b0606bb5bda2ffa882ed25
63b4639ef208d526c70ab996c646959d84a513e7
106644 F20110109_AACYZP topsakal_o_Page_063.jp2
bcc1c8e4c23022bceda13bb2b65be17e
73ea117820fe2201567e3b2dc2300acb192babe3
37255 F20110109_AACYCI topsakal_o_Page_052.pro
e249342bf3774eea8fa35c4fae3daaf4
04de68bd333ec9bfe89e070e1c0b1fa5e53d8b54
F20110109_AACZFK topsakal_o_Page_043.txt
82517e5a3fa8c441e743cc544b65cce8
627369c5965b3588964bf76046fcb21af5b51684
104292 F20110109_AACYBU topsakal_o_Page_088.jp2
68462b699f122816074ea3db6f5c771f
d53c4545c8ea343e2626e3d4a24806e33e3c77ed
16741 F20110109_AACZEW topsakal_o_Page_129.pro
f8638cba24e754121b9ddd84de9edeb6
1930c65911c9beeea0ecc08aacf0d38942acd02a
99283 F20110109_AACYZQ topsakal_o_Page_067.jp2
3d2b51e0978e3763529d92036c99c9f1
98ce506aa163fef52a723a5cad518766d5268ad5
F20110109_AACYCJ topsakal_o_Page_005.tif
3d65b29c263c0fd3854e6f2bb65de19a
d5621a93740c4b9bb47095937bb32987cc49991b
F20110109_AACZFL topsakal_o_Page_045.txt
013f3da7a947bcb59c7840e67e591132
776706107568dccf3ede4948ba1926a67ef94e25
20278 F20110109_AACYBV topsakal_o_Page_049.pro
0eca918be99054c49bd0b0edcf6730e8
544ad940d682e4bf18309aaa83f1d5d1862273fb
113 F20110109_AACZEX topsakal_o_Page_002.txt
28c9b2d08b4166ad72391e31cd4e9a3b
896e040fbd200c5722899e63df8021c6589ac67b
921760 F20110109_AACYZR topsakal_o_Page_068.jp2
fad46d84ebef583430943c48aece369c
0b27516cce0627730fbaeaf998484897ce6a73d8
1575 F20110109_AACZGA topsakal_o_Page_075.txt
debf5ebcaa90fc2d0203becb8983b744
6316a071cf99683a279b881dc3a35413aec9511c
F20110109_AACYCK topsakal_o_Page_095.tif
174ad202678c92d93ed083475d0dfcbd
34bd8c31c05175b26ea7f7534edd0388603f1dea
2045 F20110109_AACZFM topsakal_o_Page_046.txt
8cfa833f47db5d77eebb7b5c5c1fc0bb
5cb567a890fc96cb6e8716da69d5d024f6890806
F20110109_AACYBW topsakal_o_Page_043.tif
7c8ad20947d3441c809c49af45bc4a61
6f39c094bc90c9bc90a02485279330c8d14ed81f
4087 F20110109_AACZEY topsakal_o_Page_006.txt
6dc54be0ccce569d75002d7025003eff
1b3106da7b7deed10cbf32c19820ef8b26ad180b
F20110109_AACZGB topsakal_o_Page_076.txt
9e0c52e6c543d479662e75fde91801d0
432be926ac8a4b6d0733c8c9156a49f4bdff8a0c
108365 F20110109_AACYCL topsakal_o_Page_041.jp2
7f9761afd6bc8ab11753bd322693e6f2
82ceea8ebeb5cc20313056d79b537a6871398f25
1907 F20110109_AACZFN topsakal_o_Page_047.txt
4d3c994ee710f077e6995c879f2b8031
3c9316c1ad8411484c52fc7282ca5ce9c01ddf99
1807 F20110109_AACYBX topsakal_o_Page_086.txt
30f69d088a4cf4ee9a9735e60ba3b33a
40bde11a8e984beba41233b579b8cec2be7886f7
2951 F20110109_AACZEZ topsakal_o_Page_007.txt
36f90066b4211e685dad28589c1d8fc9
13489801f6e862384919d1c4704d19f74d944be8
96943 F20110109_AACYZS topsakal_o_Page_069.jp2
0b54fdebe0ed21527b8a047e948d9a28
3d7877a14d82f885068c3b4551365cba1d9e501a
1683 F20110109_AACZGC topsakal_o_Page_077.txt
30fa62bf31dad006d0b7af7b9dd27115
7f9b6a760219cedd3952c82bc41ecea239a81c99
94583 F20110109_AACYCM topsakal_o_Page_010.jpg
befb90b8e4b2c52bcee72430b9f0f974
cc811624104a5ec8ed3b6076c69acaeaa9988e17
1851 F20110109_AACZFO topsakal_o_Page_050.txt
3207471214d11b5bb822dab4a4ea9b4f
e24ec1e8a8d5eb8b3945e25142c839f1d1bb93a9
52424 F20110109_AACYBY topsakal_o_Page_033.pro
dfe9bb1bbfd88bc408e1925baba24e2e
e93fb2335152a9e2c20a69c1981af7237e915e8b
1035006 F20110109_AACYZT topsakal_o_Page_071.jp2
f3961becbb8a8480683ee606e2fbedf5
a0a98946a731837672436ed166d861495f2880fb
35926 F20110109_AACYDA topsakal_o_Page_061.QC.jpg
5daca1581a5bacf5d96d39c45c888e35
513f291e1b2059c3f4b3eacb6b164794ebb9dd4f
1883 F20110109_AACZGD topsakal_o_Page_078.txt
13dae90e1426e5ad4171306777083ec5
f746b672dd3f343288965cafd4fcd227ab4372fd
28631 F20110109_AACYCN topsakal_o_Page_077.QC.jpg
cc2a8c7e243eedc505be6c96b85168c3
c3734f309753b5cc3efc950fc563205b02cd0744
1691 F20110109_AACZFP topsakal_o_Page_053.txt
2309322ef1b2ddda4b3d0c52035c5228
21b2af39a9664d3bda7ca25b95d089255e6fbccb
183 F20110109_AACYBZ topsakal_o_Page_020.txt
705e3400c32b5c84e8c5ad27e9a86a4b
c20af836b0d372a1a507a485afd33a64db9d2b1c
822715 F20110109_AACYZU topsakal_o_Page_072.jp2
749a94a77237dff59a2130f478f23910
1f35928583f1c19346f803a0977bbfd3e808fac3
11452 F20110109_AACYDB topsakal_o_Page_129.QC.jpg
e4f424b1af56dbd9db95b0fa3b8e3cfd
9290b0a04f96d38a087ae1c9a8edad4fa9dd291b
1912 F20110109_AACZGE topsakal_o_Page_081.txt
75ccdf9e2a98cf2667c207a4be376adc
9e71b7dd7dded0963ac94099d621c1d412c6b9e0
27772 F20110109_AACYCO topsakal_o_Page_004.QC.jpg
05a184f573404d17d7901fdda7aaed36
8c4db879b7a4176081a404d54d1ae6c26543f8f0
1479 F20110109_AACZFQ topsakal_o_Page_055.txt
47f56f8aa5020e2eea16a6f3d25f33c6
6e68a1a5da7c7fcb3118994b02cf04d89fb6d8b2
91685 F20110109_AACYZV topsakal_o_Page_076.jp2
84534d6a9cf305d0866cd6d996c4a8ab
83f57a1bdf8371d83d3862c4dabb8c3040e00cc5
82013 F20110109_AACYDC topsakal_o_Page_064.jpg
c18bf1368de5919f2f4713aa90e19e68
d806bbec1698721f8570fbb0dd2305b4fb20f03c
1660 F20110109_AACZGF topsakal_o_Page_083.txt
d010605decba08e5726aba082598e52e
76edde2312df7d706aa45d700d1fc4fc65d06d2a
81794 F20110109_AACYCP topsakal_o_Page_051.jpg
0d20c9b1596af347f9a112b919c078ab
2bd628254ca4568bd59be58e27e6298a2c044599
606 F20110109_AACZFR topsakal_o_Page_056.txt
b465234fb1fb3e3cd3b0b40ba1bcab31
754d11868725d981e5e1d0b444517e3211d2a46e
987809 F20110109_AACYZW topsakal_o_Page_078.jp2
6f034732cc8a5187224d134675173345
eebd9f2e9b9b5ca4cd9598d1a58ef2a9200acdb5
84304 F20110109_AACYDD topsakal_o_Page_083.jpg
1af6ca10dd6cf9e0972033f08ee7c8c4
1f1bc0f0f841cb396524663eabe6993acfabae36
2467 F20110109_AACZGG topsakal_o_Page_089.txt
90c19f01ec2294bcc6945fded536acda
e5b7830efc36d4e28c67048d64b2d354fd1378c3
F20110109_AACYCQ topsakal_o_Page_100.tif
297c47522aea364e0f1acea28a99d84a
443b62729f9da7cceb7b7160ba504599ef99e21d
2090 F20110109_AACZFS topsakal_o_Page_058.txt
fe4f84b7e5f230cf237812983dfe3295
46868bf12d4b84960a125a393b837c0983cca44f
948359 F20110109_AACYZX topsakal_o_Page_080.jp2
f2a6bb8ccbda40cae8f6fa2e1ef9dda5
6ed020abe59b9925c70002e6ecb811aa55d4d2b4
1624 F20110109_AACYDE topsakal_o_Page_023.txt
fde7b568a6959536f78dc0b2145b46bb
4524b8eff40cfcd94bdc8dbb00daccbd33dc0ccb
1730 F20110109_AACZGH topsakal_o_Page_096.txt
c7a199208a848790219aa43ea30b227a
5a2fa7160b5f357a07959f85240a2894faf8397a
91102 F20110109_AACYCR topsakal_o_Page_037.jpg
e2d7925742639cd6dcb2d7314b2fd7d5
aba7fb591ef825498f205436b039b30595c393c5
3144 F20110109_AACZFT topsakal_o_Page_059.txt
d3c8926a4a45e32da7508c4382945f99
b0c9021920022685ddc89b5278c6fa6e8788046b
102715 F20110109_AACYZY topsakal_o_Page_081.jp2
b2763d50265e92ab26fb893de205e98c
2e95b690ac693b6941d71d22efcf9960473dcf81
7443 F20110109_AACYDF topsakal_o_Page_069thm.jpg
b4c368786a205da7689f42d05793f55f
55b9613e211c1f049c0b4b3f9f439dc9ba156f7b
1658 F20110109_AACZGI topsakal_o_Page_098.txt
ac70ef9beda14427d8fcd21ab6229f57
6fc4e2e3e2c56c1f3e853c610c8f0f7a3fe50549
90962 F20110109_AACYCS topsakal_o_Page_080.jpg
473765585835e2759ccb84122ff9ade7
0512e9ff1c945b504ab151ffe2d1f3577cfb9263
1970 F20110109_AACZFU topsakal_o_Page_063.txt
03854382d9bf6e2681702bf35a442c8e
6d27ea9a8a5aa092a9e3a9ba772c65497a925b38
108850 F20110109_AACYZZ topsakal_o_Page_082.jp2
50653b43a0cc333a4e34a81d8d62f874
c4f8b789a2d056b5b48bbae1e323fb5f31d089e6
1258 F20110109_AACYDG topsakal_o_Page_095.txt
d784d30d265b29d4e2bfd3c9c4423111
ef8f63be1ab4547011242a6c232f1fc176b40d54
1727 F20110109_AACZGJ topsakal_o_Page_100.txt
e35a713885d1a88162391ba7dcbf969f
d0372f4b77776f390eef6787d4a748f3893f06b9
30224 F20110109_AACYCT topsakal_o_Page_029.QC.jpg
0e218c3a3fc81a099399c894b5ba99b2
942237d21df9202218ea160b5ff030773bb6d6dd
2906 F20110109_AACZFV topsakal_o_Page_064.txt
28c3d1d3575f98d0671c2fcadace3bef
d0cb52686392a18aa98927212c89d44b9565dbe6
7653 F20110109_AACYDH topsakal_o_Page_063thm.jpg
9621fbacc470ee74509659a47a3ef13e
da7b3640ad54e9957e07fa60813affc375d3b129
1608 F20110109_AACZGK topsakal_o_Page_102.txt
51fc0cc68f055f084b682b5b150cdbd8
13d2998221e81c367d749d00da555e569a700c63
F20110109_AACYCU topsakal_o_Page_021.tif
4835811f61f6be96b94bf29722daff2e
26384d91a48b0b7587b7fee843436f185c1333fe
F20110109_AACZFW topsakal_o_Page_065.txt
b06fa40675c5619b88b93515ab4da306
1d57f80763d649423231645c32a063f98abbff00
8983 F20110109_AACYDI topsakal_o_Page_001.pro
134e32963fd9d6f25e568121f7dab233
31729b6eee484aa6415fc7383a6c5b1220767e54
1257 F20110109_AACZGL topsakal_o_Page_104.txt
0b2a972c65afacff78e1b3afba3ec0e2
ec914857d50fe0c0417ffef8387e4a71951a0531
1860 F20110109_AACZFX topsakal_o_Page_067.txt
fae06e74262e5a0a3cd18a364d7bc0ae
18bdf41a062deb6ce84b08fa5d5341791d60712d
1296 F20110109_AACYCV topsakal_o_Page_106.txt
ed29422430ce345c115744cf9a2b53e3
5439a5802ab06fa93c43193a4d0713fa90abfaa4
1622 F20110109_AACYDJ topsakal_o_Page_054.txt
a32b69fc1ae90631e727cef98f13a071
1379d1c92dcea323d3c974be6046e3b5896b5d57
6848 F20110109_AACZHA topsakal_o_Page_073thm.jpg
d7b7bb863a975006da2451d745250de7
5a5a92abc810ac155b3885d71796da90d7525122
1549 F20110109_AACZGM topsakal_o_Page_112.txt
efa008618cbed805eef2715c4b4c1282
aa4bed3249b38ec6b96dd3832d249f415e971e82
2103 F20110109_AACZFY topsakal_o_Page_071.txt
dc05310051af46b09e782f64dbdcaaac
63243feeb4acc0cffb083552cc41cde16ea7974b
F20110109_AACYCW topsakal_o_Page_076.tif
481a28d570a8aeb452c48c8461a0b6b9
bb5a489d3280aa33e0c6bdab8d360018d7e147d5
104953 F20110109_AACYDK topsakal_o_Page_093.jp2
d41efb6cf6b933c3ee40395b99fc5fc2
a201e6b58ccd9aabb947ce9162c5a7a409bb8d85
6667 F20110109_AACZHB topsakal_o_Page_052thm.jpg
2b52445393a8a2fd3fe8c954059359ab
57a66639c2795a6301d1f43be9b839d2c6bebc95
1562 F20110109_AACZGN topsakal_o_Page_113.txt
d16e6096a9d71b0f10f42307dcf4cafd
b0440f4447822ee3b65b8fb99a8b0eee7f7774ad
1736 F20110109_AACZFZ topsakal_o_Page_072.txt
7a4fc4ae08e1c4f2a73ade0b7fd46698
3a9a90b36f63c39d1528daf5a7e7139cccdc8d74
2884 F20110109_AACYCX topsakal_o_Page_009thm.jpg
4a09b167d1ca3f42b87e2379b61e3070
6505366a206a754df309508ace88040bcb3a0299
102099 F20110109_AACYDL topsakal_o_Page_033.jpg
15cd3e314961730fe5902da18243e87e
5827d5e8d2aca8759bfdea2e30dbdf2c161e6bd2
25352 F20110109_AACZHC topsakal_o_Page_075.QC.jpg
7eddf33fc28e5b00a93ffa22b729ee85
0c07263920b875e85d7da948ef368429f9063899
1929 F20110109_AACZGO topsakal_o_Page_115.txt
01c91c8371efbcb9d5d311de07dd46c3
8d72ead12b318ace7b6575a2ce143b18ff977b59
90561 F20110109_AACYCY topsakal_o_Page_100.jp2
9167e134dae6a5cb0d4de7ca631ab495
4bb750bf191a35f982606864f3cbb9a7a66d9794
F20110109_AACYEA topsakal_o_Page_066.jp2
d4fa23f3d9e381344f1003cbc3f96d9a
d4e4128b4ab815ee0c2884449e65570622f3f8ce
5198 F20110109_AACYDM topsakal_o_Page_130thm.jpg
e8320f8ea155e0b31558f64f38a504f3
fb4a7c8c3c002dbb8d87dcc0393c2e6b8f44a66e
3129 F20110109_AACZHD topsakal_o_Page_116thm.jpg
c6d046878b4a57e0dcd75b3f59837eab
27ac7227b241c16af9e2ca68ca94b8a2792d797b
773 F20110109_AACZGP topsakal_o_Page_116.txt
b6096cf8c158ca924b7d1cc66cf533e0
cd8c52a449186877f71eba6d714e03dd239b9e57
6289 F20110109_AACYCZ topsakal_o_Page_028thm.jpg
07f895876495745d97422912ceb97e9e
07c3b615d9d4e64ccfcd9d2f55d90d3bfdc16c64
F20110109_AACYEB topsakal_o_Page_124.tif
1f1323fe4fbcd52c55eaa07efe7b1620
841c608cf9a0ad96fea33e2c75ac8b94cfe6c87c
32811 F20110109_AACYDN topsakal_o_Page_048.QC.jpg
14b1de92686016415d2c95e131fe7608
a66f91f786ec6d5c7aa162ccab8a37ba615877e6
9495 F20110109_AACZHE topsakal_o_Page_127.QC.jpg
cee285c8531bf58b22a63f4591788834
02df6fa085afb64eda46325f298da08bd1aab305
2593 F20110109_AACZGQ topsakal_o_Page_122.txt
209bba8c19b4c802d71ae59b589cca55
4e226b1f1db84496cc6c871147cfea41e6fa08de
F20110109_AACYEC topsakal_o_Page_030.tif
c10dc15f9957f3a8cc6bab8ee8d7d117
fbc87fadf2be6bace0ef4c9e152c5e50c570b40f
7582 F20110109_AACYDO topsakal_o_Page_029thm.jpg
a8b1c90acdc4ca19a38703e2e9c0f687
c7f457c54d495d733c7b40c20473396d0cdc61a0
29607 F20110109_AACZHF topsakal_o_Page_081.QC.jpg
af7e75daa6b28a23793e6969d16cb319
979b4dc1ce620f058e29f48dd9a95843834a8282
2203 F20110109_AACZGR topsakal_o_Page_123.txt
6c8d30769b62f3510699504aad38f744
2d1ebf89ecc04776c33cfc6074dab6ac8c3337c9
101594 F20110109_AACYED topsakal_o_Page_005.jpg
bf1c9424a2d65e97d15b07e65c7174ac
dbc40cf4ae944fa7dbb6c0aae56bc29d7cb1ef8d
F20110109_AACYDP topsakal_o_Page_087.tif
893c3a7707daa894ccbc8d1087ec6126
d99dec54a9151b63c684bff5c78f916f7edf28a2
2882 F20110109_AACZHG topsakal_o_Page_129thm.jpg
6865c2e8fd40b9ee14da446bfde05248
8f8491fdf01656123644a78ab35ce2da6966f16e
2284 F20110109_AACZGS topsakal_o_Page_125.txt
a934df847589ca95262cf4c940c26bbc
bd6b0cc18d18dc833b1dad4df259ed74a4e901ad
F20110109_AACYEE topsakal_o_Page_120.tif
6ccdce2907ca927a7ad6340a5fec9dd7
db474b3a08ec21696c30e4ec3cec1cfcb1b53a91
35072 F20110109_AACYDQ topsakal_o_Page_075.pro
55c020ee83db93384c66edcbe9d1019f
7ebc2c7a69e8318da1c29d4daa9e662a7405918b
32760 F20110109_AACZHH topsakal_o_Page_006.QC.jpg
eab8631d3c9c70c8f0533632526b0af9
26821d0525a3b4691e912abd3388d609e3e779d5
1152 F20110109_AACZGT topsakal_o_Page_130.txt
b02d90819c82d6fec2a1a5666bdc1ac6
a3618554dc602300d9aaa5f646ccec1b17359b13
1745 F20110109_AACYEF topsakal_o_Page_079.txt
7de4e33d92f82c1b9fc6e211bd40449b
f5625f017fdcfc291dd5a81e1964a476db1c5e4b
89169 F20110109_AACYDR topsakal_o_Page_062.jpg
7c9340c1972a440a359fd22e2e3816d3
8a083b9e4473019154884d04db87b814c637db46
31870 F20110109_AACZHI topsakal_o_Page_093.QC.jpg
e6b3ef7d551e1149d478afde658c7124
df42634d6692aa498c5df5ff7482c40e7a1d2144
1299227 F20110109_AACZGU topsakal_o.pdf
54bf150051060ccc21711aa184cb1dd2
d5741d69d5f4c75f9f1e7e09df8b87136323e163
47356 F20110109_AACYEG topsakal_o_Page_121.pro
3372679066e0bc2971a97e3aff3914d1
13d69e4b5d4bcfa56a74b09132185cbbdbf987d3
7712 F20110109_AACYDS topsakal_o_Page_067thm.jpg
c042be2b8caf3528d39d50d682e5ee4d
153f6ad26f61bdab5d2563afb4bdf61f90ce841a
18114 F20110109_AACZHJ topsakal_o_Page_107.QC.jpg
bf9eb9a7ae8def2ec6500caf8c02af25
37a5e0a81d091d0ce2430bef0526a57f4cc96208
6176 F20110109_AACZGV topsakal_o_Page_055thm.jpg
397916b34c701d46198986bf7e0ed50c
90c46eb6133261d70000cdbe455ecc1c3797621b
F20110109_AACYEH topsakal_o_Page_130.tif
19bd1aad97bdcbb8268a42e7f4731e00
d9c2554da73aff50051cac1989209a41878de66e
F20110109_AACYDT topsakal_o_Page_108.tif
0b4f84a2249d50c254f02d87b909b2f1
39168ece63345dfdbdd9e17c5a86b593bfb1c83f
31783 F20110109_AACZHK topsakal_o_Page_033.QC.jpg
e2fd87f176230cd207eb3e396d2de49c
170e599d6195bf8177cfec979f6d375ceeed8b90
7955 F20110109_AACZGW topsakal_o_Page_074thm.jpg
339610c62b88f63623c49c8346478107
ee68a57ac3685a8d289c0df53484229c8306770e
5791 F20110109_AACYEI topsakal_o_Page_002.jp2
d5b3e97966d03987f7830d88b1dd3280
a18f42b40bcc9a7f623af26dccb0885b66dc8047
54306 F20110109_AACYDU topsakal_o_Page_061.pro
11a2d0bace3862ef03fea5616aa589dc
441aad35aceb8eab523e4017c195ec1058f46208
8528 F20110109_AACZHL topsakal_o_Page_058thm.jpg
8563204e43898d29be0675e1dc0b9c72
3d3c0068a0d656cb3d99bcffef45db67a080be71
8838 F20110109_AACZGX topsakal_o_Page_099.QC.jpg
f42fd14d1fa36b163ce71e3b87977288
a3f3bfc347e6ba32caf110bc59db1cf96a14219a
47558 F20110109_AACYEJ topsakal_o_Page_071.pro
386d5a8523ac85e5d37c8079a84a8f6a
7638f4fdccb6b8a15287cb94375ab070601c81d2
5710 F20110109_AACYDV topsakal_o_Page_103thm.jpg
ddf94c69e386fe2d70e2d74856e4323f
0fe106dd43456bfb7ee301fc547b8178d53217bd
6602 F20110109_AACZIA topsakal_o_Page_057thm.jpg
712a586762ee06550103ec4ecea6ee82
c3607f1db489f558ea30c28d89533477093f7ac4
7906 F20110109_AACZHM topsakal_o_Page_035thm.jpg
d014cac61d9b307334f062100ea181a0
99eed33824e27706841697f9ad6d7984f083e8ec
20163 F20110109_AACZGY topsakal_o_Page_102.QC.jpg
697acdb621adb298608c6c8ff79f8ad8
d70dd5491b6ee61537617215164fbb78c38d4689
41532 F20110109_AACYEK topsakal_o_Page_042.pro
d760f592cf128e758b79ebaa60932d81
b6f862d133cdaf593ebd25c3674bf99d97206253
24584 F20110109_AACYDW topsakal_o_Page_073.QC.jpg
ed4d8e484b424deb61a28307db0d1872
07febbc87673ba7ef8cbae9b6198660cac05b3b8
7564 F20110109_AACZIB topsakal_o_Page_126thm.jpg
638294f21b9cf509bc6f9f98bc5d7cf8
61909a7e810aa6e2ea48c8617345247c2e33f1a4
7363 F20110109_AACZHN topsakal_o_Page_087thm.jpg
7829a0ea9e85665bd809fe7211774f5f
37488d957e1cc6bdc002ee0287a06e825022723f
28506 F20110109_AACZGZ topsakal_o_Page_008.QC.jpg
c4b133594d2ee7a691ebc4f265df2f75
60263508d88d1740e31c7a79c9461bcf6401985d
4907 F20110109_AACYEL topsakal_o_Page_002.jpg
a6dde8e84790648e35c855c246460b20
4523c819ba40234c70848ccd04d757de4b156611
29367 F20110109_AACYDX topsakal_o_Page_099.jpg
01940f2fd4d07e2e2b612188f22d3bcd
1420994422f021801ce5fb458b9c7c4c7ceae594
7130 F20110109_AACZIC topsakal_o_Page_076thm.jpg
eb43ce3918ded3def48e9a77918c1eee
4858b1439debee292b239ea6963f0098f18125d7
7073 F20110109_AACZHO topsakal_o_Page_096thm.jpg
7050aa6d48cda0e3e7ecb9c50e775d69
9c6cbf0b004707eea465bb8545e084070cb16bfa
102529 F20110109_AACYFA topsakal_o_Page_085.jp2
c09a03d3eb3c0042b9afc2ae4b3b13cf
2be0f147650ac8e2bf83f673903898aba1333d7b
6152 F20110109_AACYEM topsakal_o_Page_105thm.jpg
35dc1dbe9afb34393f66b00e47afd977
25d9c7790387e19d0d4816cba9aa25bd5f28d003
24598 F20110109_AACYDY topsakal_o_Page_057.QC.jpg
ca7782d6e99c24576d8e11aff8b45dbc
9fa96279754198cbbf06ed3a9d399778d47b3b9d
6322 F20110109_AACZID topsakal_o_Page_100thm.jpg
92f1428b11e7cc0ef5b12df6669523e8
7e351ec854173e5659c91a23cd3285391c6026bd
5579 F20110109_AACZHP topsakal_o_Page_102thm.jpg
b812e840ba03707bd4eb8c1aa3a03fd0
37d94fd6b8a9dd8d0688bbf5d944f83c300e312d
27050 F20110109_AACYFB topsakal_o_Page_022.QC.jpg
dadb3fb689e7c25716fd450ee1bff2ce
920b54df266f10f62fea8bbceb7c8f3dee1da8a8
52147 F20110109_AACYEN topsakal_o_Page_058.pro
088db205b99f688e461f6eae3a64faf5
cf4c66dc66d9a553ae41ac635437a9fcbc5dec6a
112376 F20110109_AACYDZ topsakal_o_Page_007.jpg
f066b3e7db36604d63fade16da4b63c4
43e4724ea11cf339518a5116fb6ca1bc2979dbab
30803 F20110109_AACZIE topsakal_o_Page_060.QC.jpg
e83c2a9796053def66a336c651c1f700
123938c260ff44dffd664d22ca7084597e230f34
20684 F20110109_AACZHQ topsakal_o_Page_106.QC.jpg
c0223428d77625ced173804420fbfd6e
ffeb72d4efcb0a1b3615092e010b22de3b4dcfc8
26527 F20110109_AACYFC topsakal_o_Page_059.QC.jpg
4ae6790ee9bdb738da78607b2ee17cf3
6781ba56f4873f96a6d9128f993163e67ef08c33
23763 F20110109_AACYEO topsakal_o_Page_103.QC.jpg
d70e3c00dce7de9d32ae27ff4d555079
69fae03e8a14dc67017eeda803b23ebeee83f895
25456 F20110109_AACZIF topsakal_o_Page_045.QC.jpg
956cd79f9bc538ba0579897b7612aab1
c9a8b5942c602a66356e6ad9fe623aea53f07107
34152 F20110109_AACZHR topsakal_o_Page_041.QC.jpg
1bfe24c989e308f979dd8b6b2d55ee90
559f5461a16e2c5f5c441a720df2eb5ca89a7ffc
F20110109_AACYFD topsakal_o_Page_048.tif
a2a78e8be8b280f8a2de2c7f6532e89f
870ed266023756a92a45a5c42a3ce8aeb4c0bae2
8144 F20110109_AACYEP topsakal_o_Page_017thm.jpg
bc3a9e6ea5ec921a75f0f3cbfc9bf0c0
22f6a76cb21d6e7f0a3cb8fd0478312c1890a8a4
2915 F20110109_AACZIG topsakal_o_Page_056thm.jpg
a94b2fcb5ea96e056a4b58d9cf77662f
74da6f32e0371f050bd1ac3633d5bfb6defad15e
757 F20110109_AACZHS topsakal_o_Page_003thm.jpg
e44e1913223e467d08aceab3f0230a60
b216d11ef05cc01c3ba14590e59a7adfd43364c0
25711 F20110109_AACYFE topsakal_o_Page_049.QC.jpg
d0ddeed7202edc0ee431b5193cbd4ae3
eb496b0a75d8cb1c3813b3c9eebb72ef02f4236a
2087 F20110109_AACYEQ topsakal_o_Page_003.pro
60f6fa95c78706231d246d8c591a17dc
b5b521ae601564ad04be0cef7045699342748168
3602 F20110109_AACZIH topsakal_o_Page_020.QC.jpg
61639788ab65fd6caa57f16a2791c1b7
08162e0e50b52f463efbc8afa03aef27ed919fcb
8025 F20110109_AACZHT topsakal_o_Page_088thm.jpg
8e1bef7c62ae6375dc4f55411dda32f8
ffabbacd21eab19a282ac628790fb1d6d51b5548
34185 F20110109_AACYFF topsakal_o_Page_073.pro
906b219543bf940706a77e7ac047db54
4cc6c643032622335707f49e97b2a1b9264ee072
1839 F20110109_AACYER topsakal_o_Page_091.txt
56354a4c4dbde4ad74bf875f21c33f94
1d59a5dd1d3651735acd5b9df4d7162adae2ed66
14453 F20110109_AACZII topsakal_o_Page_013.QC.jpg
726bd02de3d47aa5e2cb64dfe6a27021
591a014e4a1395c43e4b82c1a01dd663f7d5bce0
7472 F20110109_AACZHU topsakal_o_Page_042thm.jpg
7953de3f241f6bac9db428d3aede5dfc
c0f2cd3ad35f27e8c5a0134d63b8bf044d17d14d
27402 F20110109_AACYFG topsakal_o_Page_010.QC.jpg
db6a76ccf389801d46feec20bd1b76e2
f6f68a5959f88dbe6b1c4f603541fcbb3e8d2240
77884 F20110109_AACYES topsakal_o_Page_089.jp2
aa25e8521c2043ebd721e179136cb29c
144791e28c117d6bec6c7d90fe98f30ed357d110
7150 F20110109_AACZIJ topsakal_o_Page_008thm.jpg
bf7ec7bcead6be16462d5fcaf03972eb
cf8ae3ce0ce2de8c3c8f643b4961893d4719f752
7107 F20110109_AACZHV topsakal_o_Page_030thm.jpg
15105782e8814e8ec21e60b2dfbb62e0
2de72c3d63220542e2cbd91b5959c2ed5434bee5
100234 F20110109_AACYFH topsakal_o_Page_091.jp2
bb109cbcff8de6e6ddd73fd349b65e26
ea905b69771526a100dfb520ebe61fa3d2a222c1
41566 F20110109_AACYET topsakal_o_Page_053.pro
3df009b8bd31b60cfba9ba1c0c934c9c
2dd531353ba48a4f0998bcc0db68afa3ee397e75
24836 F20110109_AACZIK topsakal_o_Page_101.QC.jpg
78b029ed82b5535d4b998830a43d150c
4ca719e9af66c93a2b2de4d77deeb14ae7037e50
26381 F20110109_AACZHW topsakal_o_Page_054.QC.jpg
4f00724cb0da62c8dabf82be2dd0004a
9e6ce786651140dee93a4fe419c068ee9546e828
97334 F20110109_AACYFI topsakal_o_Page_047.jpg
43e3c27941352a73a095ce645820fb78
ed9d46535cda6966e22b5c2ee6917087a969c251
108702 F20110109_AACYEU topsakal_o_Page_122.jpg
d2fdf8f20cf0c3816347b285b48f53a0
57688571725a0254b668f7e592b6056795183551
7189 F20110109_AACZJA topsakal_o_Page_062thm.jpg
9fc3e11ee5d8aed05c4517871083b31a
580524fe244d07ec7ca06db95f64bb3cc00b7304
29370 F20110109_AACZIL topsakal_o_Page_026.QC.jpg
bc42c06ecded7bd486ee4cb6d99fb2c7
dd98bf6ec395b99a78551853cdda1840dd379495
6750 F20110109_AACZHX topsakal_o_Page_040thm.jpg
cb554231121846dc0f098e2dc05eca50
36532a9bf9efef13a105a3a807b4fbdffe5a8ba8
18235 F20110109_AACYFJ topsakal_o_Page_097.pro
eb922eac67f1c7333641a853f0a52284
9b48060c9ef7aa3381a5cbad953c43c18289b829
79607 F20110109_AACYEV topsakal_o_Page_109.jp2
e4e25b7b9ce9aaac7cfedb8a08064c88
f20ee08f2396b485bfb32fcff686e5af4c13ec08
7763 F20110109_AACZIM topsakal_o_Page_019thm.jpg
9df5f1a9d8c50f172f07834aac07b1b8
32805f381b1b4b000554bf60e3c65165f922ea42
19610 F20110109_AACZHY topsakal_o_Page_113.QC.jpg
19c27d82fe6ac18dacf0c77de5995b08
6c926b869228e7fa57dae3d851965c3b87f16847
91649 F20110109_AACYFK topsakal_o_Page_050.jpg
3e06f4474d89b793967338962805b4d7
a972cb2e233d4abfa42d0415b4572b96e506c7d5
F20110109_AACYEW topsakal_o_Page_086.tif
fd7e3098658117286aee12cea1ddf166
745bdd413196c38a061eee4a87096854025f3a55
34299 F20110109_AACZJB topsakal_o_Page_015.QC.jpg
675f7c01feb59c6424f8dff0b8ecadae
f714777fe75bac37ed3d562e2b254c04f108708b
2810 F20110109_AACZIN topsakal_o_Page_127thm.jpg
ac2dd223e4686ec759e7c80e0e869af2
57f6156eae534a8d5f173ed9ba5dcabbb6ab7226
5954 F20110109_AACZHZ topsakal_o_Page_114thm.jpg
d90ebf077ac4b1a5e4742d0c2c8f4aef
37b7b3f36dde6c8e6dc996cdef649be9c8908a84
2059 F20110109_AACYFL topsakal_o_Page_084.txt
616cee2ca916ae04231dcf838c1812a6
364cbf73d7f5ee3f4bb4404183771fb3fce1d039
F20110109_AACYEX topsakal_o_Page_011thm.jpg
784126fd967190a68c4071b9099c2740
4e6bb09da6a861cb4789f88ed734ea469391d082
7899 F20110109_AACZJC topsakal_o_Page_018thm.jpg
2f16ee560e3b256f130887567728fc88
68f8b19dec745429dc590c6164d7b31eb64d5738
6666 F20110109_AACZIO topsakal_o_Page_119thm.jpg
f8f2ce72f6bd2a83b065200da37384b9
903e59c5f4819d09c7e0135377eb53877665ce08
2245 F20110109_AACYFM topsakal_o_Page_008.txt
0ac111715c58ea2dd1317df5e8cae88a
c17bd5508161575f65e98acf1e08bd6bd902768f
89422 F20110109_AACYEY topsakal_o_Page_023.jp2
9fb3a2b9d081aa908aa986a9d460df68
57e5035090582354242a5ebd1b50a520c329f819
1151 F20110109_AACYGA topsakal_o_Page_107.txt
9ad339ce8ac6d6561b47d22c47a2c47b
b93d50e1880968266b8b73819a71ab19e5053aaa
7158 F20110109_AACZJD topsakal_o_Page_037thm.jpg
67f393c5233424f7b898a5ce1a714596
bad54d90d744e913ff70329f75388c41ba0eef13
31350 F20110109_AACZIP topsakal_o_Page_019.QC.jpg
1144af146d66ce36abc095fa6f7b2725
cf92f5f7859fea3b575a1cd337e0d82601d8fd69
12322 F20110109_AACYFN topsakal_o_Page_116.QC.jpg
6d63a8d96314372e4855311c843dd45a
220f46f5df1aff88f6d4ac503396afdac1e1dc71
42248 F20110109_AACYEZ topsakal_o_Page_101.pro
1300cc845e86ea3703e3a1ead8807084
19d180cd75c1e8d79c5ebd5df338a58328a44e35
34097 F20110109_AACYGB topsakal_o_Page_016.QC.jpg
78ab8a939aa013fa0cd592d344deaa7b
3da4f878f418f632a1d0cd4e53da66f8772063e1
26433 F20110109_AACZJE topsakal_o_Page_053.QC.jpg
237f5af6482474241228ce33515fb1df
c61129634d40512fec7fce1500696d20f88353ca
24697 F20110109_AACZIQ topsakal_o_Page_089.QC.jpg
dd600e5b1ec50d8c73f8de5d3e3aede9
0ae009772aa896fde56d9a8386e3cfb5770820ce
5342 F20110109_AACYFO topsakal_o_Page_106thm.jpg
a185668885dec4c3d5ecdcefc78dc93c
29481dbb953c5afb36cf110acb15669b4a7f7a89
F20110109_AACYGC topsakal_o_Page_057.tif
1a9dda3898011726c9fd6c559ae6200e
587ce51273b7d27f569710ddd2463283251a31a5
6614 F20110109_AACZJF topsakal_o_Page_045thm.jpg
d7af8b773d30ba745f1fd999b85c70f2
52e0cf5ff1e6aadb7ed0a4f660de73b3b5c178df
27907 F20110109_AACZIR topsakal_o_Page_086.QC.jpg
982fd591d8811122691bfe12c2528485
8312a623d0d6af72d84f39790a867e774cb418b4
30003 F20110109_AACYFP topsakal_o_Page_063.QC.jpg
92ebc7d3ad20ebea16863baa2a8c5394
72f434b08e93b5454c7e5348032f888d050b422e
92356 F20110109_AACYGD topsakal_o_Page_119.jpg
362f8e70b5feefcccf73928b75a0cd86
439e34339d32610aea8bff0d144f8160e614bbd4
6536 F20110109_AACZJG topsakal_o_Page_012thm.jpg
9ec019464aa799ce07d5257d8dff3466
811454c54aef2514773fb01052f400d21af27ac7
29660 F20110109_AACZIS topsakal_o_Page_024.QC.jpg
f5c308a7b61a998dec0731d04028c0fa
7340867f5207d9da3738bba276099d8d08e4b5d9
F20110109_AACYFQ topsakal_o_Page_041.tif
e267440cef8edc3b75eb92752c63f3d1
683c4c1dc8ef3b1cc745f59afd08478ebf04fb87
28935 F20110109_AACYGE topsakal_o_Page_037.QC.jpg
e6b7c1a199ee06da2802bacafafae888
29d7ab2aded92c9c8f81ea2d63c28a5d204e9d7a
31893 F20110109_AACZJH topsakal_o_Page_074.QC.jpg
05a7e8734ca3ca8f5e33949c23a5920e
4428e423c3545be48fc990821ba452d89a68beea
7801 F20110109_AACZIT topsakal_o_Page_026thm.jpg
d96a595a50553a1f282621a723e7c031
275109c467b8dd824927bf991b14a010133d194d
1870 F20110109_AACYFR topsakal_o_Page_118.txt
a5ab253824fc3c3b86f6d9e054154772
859f644c6892d2a073beedd6535f66c044beede5
103148 F20110109_AACYGF topsakal_o_Page_043.jp2
29f0232614d7fde598e8966ea989dc0e
1b017969be5ac1c5206ca911ef6a27a4e67b2dda
20685 F20110109_AACZJI topsakal_o_Page_110.QC.jpg
31e6c2745db6d8550b46d6351efa04c6
1398a486943f7ba2947f9a3e207ad04da5a31061
29298 F20110109_AACZIU topsakal_o_Page_124.QC.jpg
a80dd7abd0ebeabc1fa17e865f02ca34
288dc4faddc00303638132edf3a9faf3fbe53f17
F20110109_AACYFS topsakal_o_Page_050.tif
978e5fdf391907c74edf0d0283240e69
f1e8bf53104206308ca4dbb9ec28fba3dd60973d
F20110109_AACYGG topsakal_o_Page_045.tif
8fe1b6261cac88c421db049b022d32dc
6283005e7159dc6abfe64467951aa32adf1829f3
7438 F20110109_AACZJJ topsakal_o_Page_077thm.jpg
3b3320a5d07e57ef78dc2856f3cb18a0
99f22b9570b6284e88a52bf2cea0af2c1ad46336
7123 F20110109_AACZIV topsakal_o_Page_054thm.jpg
5655ce61b12fcae0d4d9990b261e64ff
22d4a005a60b4be451a390a17f1fc3a33f725069
49114 F20110109_AACYFT topsakal_o_Page_093.pro
463a32a792f4e6b03a630483c4fe9dfd
9cdf1b567b3e2d10a7a9d320037b2821d0991e6a
1888 F20110109_AACYGH topsakal_o_Page_026.txt
ceaa43c20f86e4a900df856f5c65fcdc
c4323b24851d75d95e7af654b946f0b9eba15db8
997 F20110109_AACZJK topsakal_o_Page_020thm.jpg
1941f193126d298fa1dbce9e58fbd76a
0d68adae0417012e25d6e0af2d6d211ad18021e4
7580 F20110109_AACZIW topsakal_o_Page_036thm.jpg
c4a76716769b5c63dcbd80af0347d1e3
f25d3009e560c1608279fcea9df2a3b1b4f551e3
30793 F20110109_AACYFU topsakal_o_Page_099.jp2
b0bc30f38bf731563d8a322870d24743
4a516b4f6f703a155858dc4eb6afb0491269fe99
F20110109_AACYGI topsakal_o_Page_066.tif
91718e3d7a311582473292ce2ea740a7
6bcaa4e459c6c68be092fa9b3ab2e4dbd06f9690
7181 F20110109_AACZKA topsakal_o_Page_051thm.jpg
35a481f2ca9ee885fc4a94b3e6e13a26
d19499f9ac86c0690796b57eb344c10c892754f8
32102 F20110109_AACZJL topsakal_o_Page_017.QC.jpg
9b62c0ae17dd9750c192449aec96a72c
b3b8678ccbd7396832aa13aec74ce38f41558182
26584 F20110109_AACZIX topsakal_o_Page_120.QC.jpg
989e9705d9738a029aaa4da6d3798c89
4c8552021ddf26291ab9efcfae7769001f9b1d83
89966 F20110109_AACYFV topsakal_o_Page_078.jpg
581368d49b11da1143ec7e4af4435892
c285d35612c8ee958726f3cc794698f9a79d1d7a
97327 F20110109_AACYGJ topsakal_o_Page_123.jp2
e9dfc656ebd789d184aa54a87b551479
c952e9624c2c720bcc34f866671d22b341807d77
7113 F20110109_AACZKB topsakal_o_Page_059thm.jpg
d5f0452af6928d7579744fa88e2f8bf7
a83415158f73acc5835ced12d342c4ba66a78f91
6863 F20110109_AACZJM topsakal_o_Page_053thm.jpg
2ad66cb2965881f65635fbe0f7d68956
ae4168dc83ddbb2161cb754bc947a91763659147
6883 F20110109_AACZIY topsakal_o_Page_117thm.jpg
62195febf701473f77ccef4dec930147
4ff1e79b9600f722954ea08984c4f325bfded239
8117 F20110109_AACYFW topsakal_o_Page_082thm.jpg
5ec87f2547a11e20661bd1a924743f63
b87d0c40b734ea250fff262d41bb498c6ca7f767
F20110109_AACYGK topsakal_o_Page_102.tif
8efc551b131341a7bd1ac89f336a7637
c8bdb97ed52acf20a2ca0255c46d733bf991a231
26300 F20110109_AACZJN topsakal_o_Page_042.QC.jpg
baa02e43519c8ddec7fb372c7bea27e9
1f24517dd6e1eb126b3426be417ab26c1af280a1
28149 F20110109_AACZIZ topsakal_o_Page_078.QC.jpg
55411ce290c8f67fc21b82e4c30a96a5
d6ef589ea5087d0b0a390866ac7520b1e9d85d2f
F20110109_AACYGL topsakal_o_Page_091.tif
d5e73fe053ba2d356cc1c0eee6c1e72e
208f876656f66f3e2958f27dff2878b047fda9d0
F20110109_AACYFX topsakal_o_Page_019.tif
5b37421a06ee26a464bb357403a93492
e572e31b3b4c8b8fa08d81c802c860f851917f39
25443 F20110109_AACZKC topsakal_o_Page_064.QC.jpg
aa725d870402a798d3fe883893840690
ea050ac2530a7692dde63fffa12a059c85e28254
30102 F20110109_AACZJO topsakal_o_Page_122.QC.jpg
bff903c8a7d963d901ddcafe967b30fd
19ca6578030a3b6bc3d1e8d8a3daf9808066894b
94484 F20110109_AACYHA topsakal_o_Page_093.jpg
5f43d6f09147e9c8b794c1bee5c09bf8
a610434e34d3776d553c58e77e29a98ab459fb4f
7185 F20110109_AACYGM topsakal_o_Page_049thm.jpg
9491e83fb56ad628f75c83c78b0d48ad
2666d8810feac9cb2b808f51da2d1c6a7f2463ba
F20110109_AACYFY topsakal_o_Page_002.tif
c39da3665333f038bf08a67bce651012
7c4caa7540a259c2069724d1d7ee877227ad408f
33452 F20110109_AACZKD topsakal_o_Page_065.QC.jpg
43b6af00fd544b8d7cdf3f0e6ad990f2
4966b9277fc125c05f26c853edb3ecd9e123b7be
7604 F20110109_AACZJP topsakal_o_Page_124thm.jpg
7a4f4bb4c6c8a336201ed5fbe052fac2
2caa8ebd6231e48d18cbe0f8faff48c1bdb73746
99828 F20110109_AACYHB topsakal_o_Page_060.jpg
eee98cf5a0e602df2c53fc8758872d94
8784d1feee989419b33ddec7a2b59b161b820b44
7145 F20110109_AACYGN topsakal_o_Page_125thm.jpg
7f3d8daa65b65b146c39c3bcfb391174
b7371576ef639c7a197dd2c90a16abcb92b2e948
99096 F20110109_AACYFZ topsakal_o_Page_121.jp2
f48e9cdd98fa5a0cb94ff73c9e05a55c
930a2a8bb0567e858b365efa8954aeb4965da1b4
32550 F20110109_AACZKE topsakal_o_Page_066.QC.jpg
aadefaed70fef1a987226dfb929b2740
6481a716111f5b9781ca8a27a121c500bfc3d506
25279 F20110109_AACZJQ topsakal_o_Page_100.QC.jpg
ba7d1196c146a620b542b53e21fcbee2
44a261744e257ba313a9efdb7ba7643bb52e9e01
47647 F20110109_AACYHC topsakal_o_Page_081.pro
0fa0306256c435fec143e9c27e417d7f
bddaa4cfc618cfaa0dbb417adf42be0e8045e9b8
100438 F20110109_AACYGO topsakal_o_Page_008.jpg
e65c6f90d55f79fcc63ba80e027092b0
ec5846f0e719cb35ded37c0595daa97c693b4617
7620 F20110109_AACZKF topsakal_o_Page_068thm.jpg
f74e7309d721fa17d3d26f60a9138153
c5b19dea6ed1eebe7f7bf2c312af94c1f45b3975
27535 F20110109_AACZJR topsakal_o_Page_117.QC.jpg
acd3b9a3ada68231307ac31400c3bcb7
79b1389f1d5a361c6755a7442ca56de0a00170d1
30782 F20110109_AACYHD topsakal_o_Page_071.QC.jpg
4f9fc9c1c095d6c678e4a6952896d46e
3014c662e7d605d6ced41bc250dc31a72f475bc8
1553 F20110109_AACYGP topsakal_o_Page_052.txt
c4246ac763558b014bb7bdbf9b17f93a
cafb3a6e6874f33034d917bc31890bf7f4e01fae
33933 F20110109_AACZKG topsakal_o_Page_070.QC.jpg
2b3164c055658f0d3e043a6674e9575d
0fc440952327fa1282cf2feb89d1f39cbecf436a
5026 F20110109_AACZJS topsakal_o_Page_107thm.jpg
f4b92987fd39f510292f8eae06702445
4cfbb3486e741d5884dd435ca30c560a2f397e77
3829 F20110109_AACYHE topsakal_o_Page_013thm.jpg
6f9fcfc696cf6d9d3e783f623ebb1e53
685efe0c580b8156f0eae71bedfaa917a2a65657
61664 F20110109_AACYGQ topsakal_o_Page_113.jpg
6471910c5eeeb35d025d2675da55ece5
93690244bb2f2247466c241012d12a6ba2d94007
8041 F20110109_AACZKH topsakal_o_Page_070thm.jpg
6fea96df24486eacf39237d1509c2c3a
4b49bfb0c6772c754e3fa23dc66ae31780215812
196682 F20110109_AACZJT UFE0001210_00001.xml
2ae819929900b588442aff8b1cf055ee
19e2999b4c88f82cb977153270b25ca34d3abb86
6994 F20110109_AACYHF topsakal_o_Page_123thm.jpg
ff1e2909c37288d0a314c3f614d04667
5ee93b3dd92b64b5422ee1ec239064bd702ce9f2
42922 F20110109_AACYGR topsakal_o_Page_062.pro
23918b16a6df5458265b45768eee7702
1b35e489382a89493c82e277bc00985bed977935
6998 F20110109_AACZKI topsakal_o_Page_079thm.jpg
e4b9b8ca250c417dbb6a39bb2975ec35
730b418b16bac1b3df078a4f90e3e98e1c5f629c
22643 F20110109_AACZJU topsakal_o_Page_028.QC.jpg
0ce6c774a2f2013efc0e8ae9ae875c38
5149298b76ed32715cde86ce1b8678b06a8a842e
F20110109_AACYHG topsakal_o_Page_069.tif
14f667c0f7ef08517eee992065eecf48
272f13f4c2bda28ac1423d3e26fd5d1f4351447d
38676 F20110109_AACYGS topsakal_o_Page_072.pro
cf27c473b33cab1f5c3670057ba8d04c
5667a0551b1d483421f76757cc694fee7c0e9bf2
7742 F20110109_AACZKJ topsakal_o_Page_081thm.jpg
501fa628359696678291541e7392adeb
91a094587f51c160dab7b6fdcca05cb5c23be773
27998 F20110109_AACZJV topsakal_o_Page_030.QC.jpg
74df3c845f138c5c2f4bc62eb0f8689c
773cafdf0775ed11ac726425da9f698c5ec4c338
48724 F20110109_AACYHH topsakal_o_Page_013.jp2
0317386c70be80e7470be83c3ae5967c
f119b7afcac9d799a34987d10cabe25d68d272ae
25347 F20110109_AACYGT topsakal_o_Page_098.QC.jpg
4587d143cea7dc1e6522125fffc0ffdf
71393233c39cb24f57fe38b01b6c4cff3efceb5f
7258 F20110109_AACZKK topsakal_o_Page_086thm.jpg
78daa381edc396979e93c911396fcd6b
33aceeff54375ba193a9c00c6bf1f42abb6f8f12
8194 F20110109_AACZJW topsakal_o_Page_033thm.jpg
b63d79cf720a5abeb74f3eaa6112baef
10ba1b9935a34f0d6f08f518da5c4092abd3a9b0
8227 F20110109_AACYHI topsakal_o_Page_039thm.jpg
8ffa85f9a9e9c80d183936ae8bf05f0a
bd1d03a0cbf5bc51f0c94ce5f0083bfd6655b4a8
97495 F20110109_AACYGU topsakal_o_Page_087.jpg
de238c5252e79a2e39a3f1e967570b9e
2218749cc2fdb646f675e91ef9c90eacb0f4b4ec
29530 F20110109_AACZKL topsakal_o_Page_087.QC.jpg
a01b09e3416b5e7783c832a53edf04cc
54a51d68460506dc0e0d3a5aef3de8da4867fb44
7873 F20110109_AACZJX topsakal_o_Page_038thm.jpg
fbd733d532c5e052746940be27eb9edf
d9a472bdb51d1e391f3ad07e6b156657310b05e0
7828 F20110109_AACYHJ topsakal_o_Page_046thm.jpg
1b47d21c61f8ab5f7435cc274ce9f53c
a5d0221d58c70656f6f074f9ce64819ad90b78af
30953 F20110109_AACYGV topsakal_o_Page_128.QC.jpg
7348852d3688d8e675e07b86f2069cbb
2a28ad9c356679aff63d3434e9771d37d5e64ad0
31642 F20110109_AACZKM topsakal_o_Page_088.QC.jpg
7b5c50daa7df826bae1c9e0fe141bf4e
ae0e1853243952145f92fa791ee34283097570be
7835 F20110109_AACZJY topsakal_o_Page_043thm.jpg
68e982aac78aabb2150866afbf215fa9
a7e60f4b21817993aee9e4e85397bb775a1c8772
937053 F20110109_AACYHK topsakal_o_Page_079.jp2
8719d19bb1f911ae19c7dd3f7aa21693
531347b29336aebf55b9e358b99cc35314e2611f
1947 F20110109_AACYGW topsakal_o_Page_085.txt
8a8124056cd465014736dca901786b1e
8bb126f898903fb7d6ac28411cc238fc38b32357
32948 F20110109_AACZKN topsakal_o_Page_094.QC.jpg
077c927cb7fa1c3dd173c339632bc599
c4176463c403502d1c1ccb280fadd2a6ff7f71e3
31385 F20110109_AACZJZ topsakal_o_Page_046.QC.jpg
aced3966909f4ba056b1da6cf46c75ea
f8d98647bebec4d6c4071b4bc26226ac8275bbdd
F20110109_AACYHL topsakal_o_Page_059.tif
555d39e757c916285c1bd1f56efd82e5
a703bfcc60e6bb04bf8a695897e912949485e612
7839 F20110109_AACYGX topsakal_o_Page_031thm.jpg
c76468340129a2c23e2956e5c892fbd1
a9d67254620eedee5d9b9b886d70b94239f43e08
F20110109_AACYIA topsakal_o_Page_014.txt
5cd77881a3db65aa014e4a2f00f84ecd
03720c5e01cf3ced4b3d70c39cd013fa57ea5aeb
13570 F20110109_AACZKO topsakal_o_Page_097.QC.jpg
2154346853d46d9fcff1b6473ccde187
c6776da5ad33d9a410423ff88d2b84157f620935
1993 F20110109_AACYHM topsakal_o_Page_048.txt
066f187170b0dd8884108f7b27532ab5
fe4ac04716b21b746d60e53bfdeb16d022300725
731633 F20110109_AACYGY topsakal_o_Page_028.jp2
509a1a17ceda7863183f9bb4a2711399
eeeaaa9a001e0d77b47aa22951c7520ac07a9d13
3565 F20110109_AACZKP topsakal_o_Page_097thm.jpg
bdd5c2eb410f36dd2a3a30870aff716c
1830b84842938007c2725b1909e473847dc29317
F20110109_AACYHN topsakal_o_Page_007.tif
fb641c5b43e14b7bd923454ead65fe11
3074c1d4d3982d1ef4aaf4beec207ab0db9d9173
25037 F20110109_AACYGZ topsakal_o_Page_012.QC.jpg
5f310b003f6a916b6582bc202806ae88
2e66e88d033493ed7cba5d082be90ff98d290a4b
820 F20110109_AACYIB topsakal_o_Page_127.txt
7a09b0b66aa4a7f0ffee02d601983f05
7baffa9dd82db8aea25bdbb59fd31e4d095e0dc1
6316 F20110109_AACZKQ topsakal_o_Page_101thm.jpg
ef063aa118c2ce2122878af044d506a2
2c162fbc768c9726f485272d6c806831276639aa
39745 F20110109_AACYHO topsakal_o_Page_021.pro
b9e7cd66269dbc76ffcc5fba69fce2bb
d8a4e79385e1c534db7ba31ede1fb5e008ec116c
89215 F20110109_AACYIC topsakal_o_Page_042.jp2
429a0d9011929eb34b45fee89610e3d4
7b66ac32e72ba34ea6e0030055906b30acc056bd
7554 F20110109_AACZKR topsakal_o_Page_108.QC.jpg
8b5515136f7ec10ee087ccdb1176d43f
fea5a11d0edaf3eb3298952db0b6ae772fce6fc9
95153 F20110109_AACYHP topsakal_o_Page_125.jpg
8c6a131b33044165797721b4d0c6aba3
58848afc01c45d377fefd8d7a7d06a25ed9a952d
1652 F20110109_AACYID topsakal_o_Page_021.txt
2aee39a2c850c448c7eff0576aabcf9a
230ba889184192072baa045081f926f153d81c71
2196 F20110109_AACZKS topsakal_o_Page_108thm.jpg
3b0f46ec8a41fa0da28d71c32855e01f
f4fbcbb6c27a1a9055479b927d6d291d7249ad89
44363 F20110109_AACYHQ topsakal_o_Page_109.pro
c2ee47dd867ec544079d48390552c903
672647d818a13b15414ca5a0893743ecb0202478
98685 F20110109_AACYIE topsakal_o_Page_035.jpg
8fcd6c08913018fe6a66a027615e1480
b5c535b8f0b2f7f187755fbc898de846a8eb98d5
4986 F20110109_AACZKT topsakal_o_Page_110thm.jpg
5b635593df0b389572272fad7d001ebd
a8eddf9147f580b3824e463a1a78b5acdb4f212b
1818 F20110109_AACYHR topsakal_o_Page_117.txt
d50b45b9724c91db564fa63ba3f2f9fc
b88c130cdbf83d9981131b364b0179618028670a
F20110109_AACYIF topsakal_o_Page_128.tif
1488ca1fd6bc700f7f55af61cb91c903
a8c8c062382d24fa0ab336aafe258e736fbdd01e
23727 F20110109_AACZKU topsakal_o_Page_111.QC.jpg
09174f01531cb607b0d80f2697310e2d
bc4b3d3322ea19dcb11cef9cab81553078667aa0
43865 F20110109_AACYHS topsakal_o_Page_078.pro
879397af6c1ae51687e6d6de447cd355
e5c781edf686ea465b0dbd6182e40dbabd66334c
1716 F20110109_AACYIG topsakal_o_Page_044.txt
22c4131df1213596304b11e9cc952daf
0fc231b3be99f1a0f09dc707e4aba530f0335ede
27304 F20110109_AACZKV topsakal_o_Page_121.QC.jpg
219d9d6f7cccff775af544ee5922d9fd
72fd3588376d7d8d529ed90898b3b0eca36cd7de
60137 F20110109_AACYHT topsakal_o_Page_107.jpg
b433035f17b1dfd8b1ab74120d5baeb0
92ef58870637eb5397867a3a8bd638b91f32dfd4
24077 F20110109_AACYIH topsakal_o_Page_055.QC.jpg
91f1b37867bf3ae3e5639ace8801da6a
6b7449b996d3850941ef527b40e2338e5a892131
21418 F20110109_AACYHU topsakal_o_Page_105.QC.jpg
e86522ab74c68460b51509fdb788412f
7a04277e58827f47896515a7f95c7c676b02f4bb
F20110109_AACYII topsakal_o_Page_122.tif
64d3b0a68b5d3e08285d76e93cd2e362
56663a2ecd4d9722b68858d60e411ceafa3878ca
F20110109_AACYHV topsakal_o_Page_014thm.jpg
7f4588d7981082d67ab2fb4c6ffae412
5833840811bbb85df06e9ed39487ad99811101c1
39457 F20110109_AACYIJ topsakal_o_Page_054.pro
e20bb9a6ecae8372078c4137a3329201
8500e44b20b73203081a41993c4226047d1b92a2
53240 F20110109_AACYHW topsakal_o_Page_092.pro
e92106b1f9fa405f121c49265bc86e90
12b8f1ec243cfd6beab4710d88ac00665263a1ac
98962 F20110109_AACYIK topsakal_o_Page_036.jp2
2d8f023b32072698d46cbd5e50753914
0fd60b0796971abd221c9da475e723d6b9fc03b8
42085 F20110109_AACYHX topsakal_o_Page_114.pro
20071eeaeb52fd51403000bd912cf495
e7069ec954dab899ca568a0617757d12ca76335f
31862 F20110109_AACYJA topsakal_o_Page_127.jpg
d99c15291abe7b7c946a62209280369e
a93b98c1a53f8b312ef0bcf2e5c325df622b5806
45083 F20110109_AACYIL topsakal_o_Page_037.pro
a6461e3bc0d7a246499481b034e06c76
de23bc94d20dd7f8b5221cb43890a522e497ed8e
42435 F20110109_AACYHY topsakal_o_Page_097.jp2
85173870c4888e5bfe18ee513d407a91
08b06e75540c2910770ca78d373512b6f86ea876
23701 F20110109_AACYJB topsakal_o_Page_118.QC.jpg
90707a1c3d4faf36c2dc715e33105fa3
1f15d234d6dcb6510a894e730cddb0485d606105
46090 F20110109_AACYIM topsakal_o_Page_043.pro
11ea272bb87954d3e9bfbd784efce787
9e9d4d59f044ca5ff0df3c187f8dcf65da67aecc
8592 F20110109_AACYHZ topsakal_o_Page_061thm.jpg
23ad582ad04944660a93cc2f5c8953da
05a8b39919e81425baf6ec42c31e3c758a3af1aa
1051981 F20110109_AACYIN topsakal_o_Page_005.jp2
7d91c9599a77e7da3fdf1afc3fade45e
500cceacbffbfe8ff7b371d805457707b3fd18fe
38025 F20110109_AACYJC topsakal_o_Page_012.pro
a7ce05c2898f9b02ab42f29d65a070ff
e07f77fe0caa418ea145d6f186e0e2eefc483e6b
8270 F20110109_AACYIO topsakal_o_Page_094thm.jpg
c889d8e061cc2fea07878de0bfa6dc77
8d700d607ddd667a11f75e646de8af7d59674495
F20110109_AACYJD topsakal_o_Page_044thm.jpg
700dda1221d5d5d666f12ef0449f1df0
4dd63c08c1ce2f8cd2002844c8c6966a829293ec
45440 F20110109_AACYIP topsakal_o_Page_091.pro
7b949a17f99c4ff91c75291cf8915b47
ae6e88ffb7608f42f0a577f6e92235e6508b2747
23850 F20110109_AACYJE topsakal_o_Page_040.QC.jpg
dcc8ee230d15902c893cec933d9b6e6d
30157d2388af7008bc43f98973c1e1ec0f1fd980
8402 F20110109_AACYIQ topsakal_o_Page_060thm.jpg
4dd37125fed3baf123f7e7b50fd6e76d
f19ada584535d212c324051e0bd6dbecdd6e8787
2353 F20110109_AACYJF topsakal_o_Page_124.txt
b1f81f616fd04c3d4296849c9a3c82d2
9f24dd1373a19079b828052f3bc1b7704c029a01
52635 F20110109_AACYIR topsakal_o_Page_059.pro
d68d86f90ec0ad3f11d82f3521a3e41b
285d946942d2114de75c450956b77a797e33424a
2167 F20110109_AACYJG topsakal_o_Page_128.txt
813d0c44c7bed463ac087a2262b1d6b1
76156cbe18e334851a86ffa19c26d491f24fd058
6634 F20110109_AACYIS topsakal_o_Page_115thm.jpg
dbadae2271a39db5352e617d4d796a49
3b1f0e0dee211b15e5293b271a44061095f351dc
2263 F20110109_AACYJH topsakal_o_Page_030.txt
2576b838492dd65ad53ede424fbb76db
8b392e813931cfdcaaabefcc31fdbd6b8853ca70
7374 F20110109_AACYIT topsakal_o_Page_006thm.jpg
610051b379d17cd94e33e994885a52a5
f1100bf7c40d25f08fba0cd0a57fa5d64e4c4ba4
14474 F20110109_AACYJI topsakal_o_Page_112.QC.jpg
8193e296b921b7f79c01610f2365d7c0
e460323973a50b4048f4df85ab40c506f52c85b7
6557 F20110109_AACYIU topsakal_o_Page_089thm.jpg
2167225eea75b3d02dda77e0da8cba5d
bc3980aa432d16893c89571c351f2f1cd5b5e26a
27378 F20110109_AACYJJ topsakal_o_Page_076.QC.jpg
caec51fdf89956eaf4db0875972989ec
a665156958901c51fc7da62a87320f4ab4d5b4bb
30912 F20110109_AACYIV topsakal_o_Page_091.QC.jpg
316c734809ab38682b0d003be2f03111
cffd2900eadda5cc997f8a8c8438de48d264f7d2
89080 F20110109_AACYJK topsakal_o_Page_004.jp2
4de4a86d633a17e3f5324e966efdc07a
7e271d8d88c3c87544a06aa226e50cfff125bfe5
7838 F20110109_AACYIW topsakal_o_Page_093thm.jpg
53e67ead257f71029822a5368a062512
90e87921d0499d0187cae4f2337310afaa959d5b
F20110109_AACYKA topsakal_o_Page_074.txt
dc31876ca91dac005172d3d9f66d7de5
ed2afce7fdf4ec712013318fca82545f8802e0c2
27398 F20110109_AACYJL topsakal_o_Page_123.QC.jpg
058157828d338720497fd0f75ac76f8d
08946c0bebca7068f9a548a2b4dc696faa731cb7
30352 F20110109_AACYIX topsakal_o_Page_067.QC.jpg
7a6d26edf86cfa2e4a7e0c9d0e6c2acd
09ddea742d9e8052cea5b15d629a7492ef663c61
45261 F20110109_AACYKB topsakal_o_Page_036.pro
0242c5fdbf9f7829966653444b0e8ea7
28db7e9fbf35d0352538790fea4a4015d05bd28c
F20110109_AACYJM topsakal_o_Page_081.tif
0d8befdd6cc3202f98edac13ecc23121
11ca97cf2e51bfcf7d9441303c400521916bdf31
93676 F20110109_AACYIY topsakal_o_Page_029.jpg
0eaa8cfa9e5e15a0831eb381e67a0e60
bb3b76439985f85c31951661228ce372db7f424c
7608 F20110109_AACYKC topsakal_o_Page_050thm.jpg
a01cfa8e6d4353015e312ca6f83fe21e
42789a6e28d06da7a86634c459638ca48f884e3e
F20110109_AACYJN topsakal_o_Page_044.tif
a87890d5b68caa48d917924a935be4a9
087c021e7c807442c7f79ef9a61d7ca0efd55b91
28114 F20110109_AACYIZ topsakal_o_Page_062.QC.jpg
3c3b9494748537d359af2c352dcb3734
6de1caa6b15dcc1b111cc08d963c931c06a967ec
5642 F20110109_AACYJO topsakal_o_Page_111thm.jpg
2c1adbb4129e409a8c9c692a4d974514
4a940c80d925aa3d1a572b8e8578c6bf662abc3b



PAGE 1

EXTRACTING SEMANTICS FROM LEGACY SOURCES USING REVERSE ENGINEERING OF JAVA CODE WITH THE HELP OF VISITOR PATTERNS By OGUZHAN TOPSAKAL A THESIS PRESENTED TO THE GRADUATE SCHOOL OF THE UNIVERSITY OF FLORIDA IN PARTIAL FULFILLMENT OF THE REQUIREMENTS FOR THE DEGREE OF MASTER OF SCIENCE UNIVERSITY OF FLORIDA 2003

PAGE 2

Copyright 2003 By Oguzhan Topsakal

PAGE 3

To My Mother H. Nedret Topsakal And To My Father Sabahatdin Topsakal

PAGE 4

ACKNOWLEDGMENTS I would like to give my sincere thankfulness to my thesis advisor, Dr. Joachim Hammer. His kindness, encouragement and thoughtfulness meant so much during this thesis study. I also would like to thank Dr. Douglas Dankel and Dr. Beverly Sanders for serving on my committee. I also would like to thank all of my colleagues in the Scalable Extraction of Enterprise Knowledge (SEEK) project, especially Dr. Mark Schmalz, Lucian, Ming Xi, Nikhil and Sangeetha. I am grateful to my parents, H. Nedret Topsakal and Sabahatdin Topsakal; to my brother, Metehan Topsakal; and to my sister-in-law, Sibel Topsakal. They were always there when I needed them; and they support me in whatever I do. I also would like to thank all of my friends, my special treasures, for affecting my life positively. There are some friends who have showed their care the most in the past two years. H. Levent Akyil and Saskia Kameron are the ones who encouraged me the most in pursuing advanced study in the U.S.; and supported me in every aspect during my stay in U.S. My dear friend, Evren Dilbaz was always with me although he is thousands of miles away. Members of Hayallerimiz team, Bahri Okuroglu and Oguzhan Poyrazoglu, have always amazed me with their friendship. A. Koksal Hocaoglu, Nihat Kasap and Aylin Yilmaz are the new treasures I have gained in Gainesville. I would like to acknowledge the National Science Foundation for supporting this research under grant numbers CMS-0075407 and CMS-0122193. iv

PAGE 5

TABLE OF CONTENTS page ACKNOWLEDGMENTS.................................................................................................iv LIST OF TABLES...........................................................................................................viii LIST OF FIGURES.............................................................................................................x ABSTRACT......................................................................................................................xii CHAPTER 1 INTRODUCTION........................................................................................................1 1.1 Motivation............................................................................................................2 1.2 Solution Approaches............................................................................................3 1.3 Challenges............................................................................................................4 1.4 Contributions.......................................................................................................5 1.5 Organization of Thesis.........................................................................................6 2 RELATED RESEARCH..............................................................................................8 2.1 Code Reverse Engineering..................................................................................9 2.1.1 What is a Decompiler?..............................................................................9 2.1.2 History of Decompilers...........................................................................10 2.1.3 Why Successful Decompiling is Possible in Java...................................10 2.1.4 Purpose of Decompilation.......................................................................11 2.1.5 Examples of Decompilers........................................................................11 2.1.5.1 Mocha............................................................................................11 2.1.5.2 Jad..................................................................................................12 2.2 Parser Generation...............................................................................................12 2.2.1 Compiler-Compiler Tools.......................................................................13 2.2.2 JavaCC and its Features...........................................................................13 2.2.3 The Grammar Specification File of JavaCC...........................................16 2.2.4 Java Tree Builder (JTB)..........................................................................16 2.3 Visitor Design Pattern........................................................................................19 2.3.1 Design Patterns........................................................................................19 2.3.2 Features of Visitor Design Pattern..........................................................19 2.3.3 Analogy for Visitor Pattern.....................................................................20 2.3.4 Double Dispatching in Visitor Patterns...................................................21 v

PAGE 6

2.4 State-of-the-art in Extracting Knowledge from Application Code....................22 2.4.1 Lexical and Syntactic Analysis...............................................................22 2.4.2 Control Flow Analysis.............................................................................22 2.4.3 Program Slicing.......................................................................................23 2.4.4 Pattern Matching.....................................................................................23 2.5 Business Rules Extraction.................................................................................23 2.5.1 Business Rules.........................................................................................24 2.5.2 Categories of Business Rules..................................................................24 2.5.3 Where Are Business Rules Implemented in Information Systems.........25 2.5.4 Extracting Business Rules.......................................................................26 2.5.5 Importance of Business Rule Extraction from Program Code................26 3 SEMANTIC ANALYSIS ALGORITHM..................................................................27 3.1 Introduction........................................................................................................27 3.2 Objective of Semantic Analysis.........................................................................30 3.3 Components of the Semantic Analyzer.............................................................31 3.3.1 Decompiler..............................................................................................31 3.3.2 Abstract Syntax Tree Generator..............................................................32 3.3.3 Information Extractor..............................................................................33 3.4 Extensibility of the Semantic Analyzer.............................................................34 3.5 Extracting Semantics from Multiple Files.........................................................35 3.6 Finding the Class Source Code Files.................................................................36 3.6 Slicing Variables................................................................................................37 3.7 Heuristics Used..................................................................................................38 4 IMPLEMENTATION OF THE JAVA SEMANTIC ANALYZER..........................44 4.1 Package Structure..............................................................................................45 4.2 Using the Java Tree Builder To Augment the Grammar Specification File......48 4.3 Generate Parser by JavaCC...............................................................................49 4.4 Execution Steps of Java Semantic Analyzer.....................................................50 4.4.1 Making Preparations to Analyze.............................................................51 4.4.2 Analyze Source Code..............................................................................52 4.5 Functionality of Visitor Classes.........................................................................54 4.5.1 Output Abstract Syntax Tree to XML File..............................................54 4.5.2 Get Variable and Method Declaration Information.................................55 4.5.3 Get Slicing Information...........................................................................56 4.5.4 Get Business Rules and Comments.........................................................57 4.5.6 Get Method Calls.....................................................................................60 4.5.7 Get Package-Import-Extend Info............................................................61 4.5.8 Get SQL Statements................................................................................61 4.5.9 Parse SQL Strings....................................................................................61 vi

PAGE 7

5 EVALUATION OF SEMANTIC ANALYZER........................................................63 5.1 Can Features of Semantic Analyzer Extract Semantics Correctly?...................63 5.1.1 Targeting a Specific Column from the Query.........................................63 5.1.2 Extracting the Column Name from Mathematical Expression................65 5.1.3 Geting Query Expression from the Variable Value................................66 5.1.4 Concatenating Strings to Get the Query Expression...............................67 5.1.5 Geting the Meaning of Slicing Variable from the Output Text...............68 5.1.6 Passing Semantics from one Method to Another....................................69 5.1.7 Extracting the Meaning from the Title Output........................................69 5.2 Correctness Evaluation......................................................................................71 5.3 Performance Evaluation.....................................................................................75 6 CONCLUSION AND OPPORTUNITIES FOR FUTURE RESEARCH..................78 6.1 Contributions.....................................................................................................79 6.2 Future Work.......................................................................................................80 APPENDIX A GRAMMAR SPECIFICATION FILE EXAMPLE FOR JAVACC..........................83 B COMPILER BASIC TERMS.....................................................................................85 B.1 Production Rules...............................................................................................85 B.2 LL and LR Grammars.......................................................................................85 B.3 Table Driven Top-Down Parsing......................................................................85 B.4 Lexical Analyzer...............................................................................................86 B.5 The Parser.........................................................................................................86 C DECOMPILED FILE EXAMPLE.............................................................................87 D VISITOR CLASS EXAMPLE...................................................................................92 E JAVA GRAMMAR....................................................................................................96 F ORACLE SQL GRAMMAR....................................................................................101 G CONSTRUCTION SCHEDULING PROGRAM....................................................104 LIST OF REFERENCES.................................................................................................115 BIOGRAPHICAL SKETCH...........................................................................................117 vii

PAGE 8

LIST OF TABLES Table page 2-1 Automatically generated tree node interface and classes.........................................17 4-1 JavaCC generated parser files..................................................................................49 4-2 Information stored for variable/method declaration in SymbolTableElement.........57 4-3 Information stored in BusinessRule class................................................................58 4-4 Information stored in ResultsetSQL structure..........................................................62 5-1 Examples of ResultSet get method parameters........................................................64 5-2 Example of a SQL query that has mathematical expression in its column list........65 5-3 Example of using variable in the executeQuery method..........................................66 5-4 Example of Concatenating String to Get the Query Expression..............................67 5-4 Making relations between output statements and columns......................................68 5-5 An example of passing parameter values.................................................................70 5-6 Extracting the meaning from the title.......................................................................70 5-7 Extracted Meanings of the Columns from the Construction Scheduling Program Source Code.............................................................................................................72 5-8 Extracting the meaning from title of the outputs......................................................73 5-9 Code fragment inside the main method of ScheduleMenu.java...............................74 5-10 Code fragment from ScheduleList.java shows how variable semantic is transferred from one method to another...................................................................74 5-11 Time spent (in seconds) in sub steps of previous version of SA..............................76 5-12 Time spent (in milliseconds) in current version of SA............................................77 A-1 Example of .jj file.....................................................................................................84 viii

PAGE 9

C.1 Original version of ScheduleMenu.java code..........................................................87 C.2 De-compiled version of ScheduleMenu.java code...................................................89 D.1 Class Definitions of Example Nodes of Tree...........................................................93 D.2 Visitor Interface........................................................................................................93 D.3 Visitor Class Example..............................................................................................94 G.1 Code of ScheduleMenu.java..................................................................................104 G.2 Code of ScheduleList.java......................................................................................106 G.3 Code of ManipulateActivity.java...........................................................................107 ix

PAGE 10

LIST OF FIGURES Figure page 3-1 High-level view of the SEEK Architecture..............................................................27 3-2 Semantic Analyzer Components..............................................................................31 3-3 Checking the success of decompiling process.........................................................32 3-4 Two main steps of Information Extraction..............................................................33 3-5 Traversing between class files..................................................................................36 3-6 File Finder................................................................................................................37 4-1 Architectural overview of the SA prototype and related components.....................44 4-2 Java Semantic Analyzer Packages Structure 1.........................................................46 4-3 Java Semantic Analyzer Packages Structure 2.........................................................47 4-4 Input and outputs of the JTB tool.............................................................................49 4-5 Initialization of the Java Semantic Analyzer............................................................51 4-6 Eight steps that make up prepareForProcess method.............................................51 4-7 Seven steps that make up analyzeMethods method.................................................53 4-8 Link List Structure of Traversed Method Tree of SA..............................................55 4-9 Example of a business rule that inherits another business rule................................58 4-10 The content of the stacks at point when * in Figure 4-9 is reached......................59 4-11 The content of the stacks at point when # in Figure 4-9 is reached......................60 4-12 List of Method Calls Structure.................................................................................60 4-13 Example of a ResultsetSQL class.............................................................................62 5-1 Example of a ResultsetSQL class and ColumnElement and TableElement lists......65 x

PAGE 11

5-2 ResultSetSQL class representation of the query in Table5.2...................................66 5-3 Illustration of String SymbolTableElements and their values..................................67 D-1 Example of production rules of Java grammar........................................................92 xi

PAGE 12

Abstract of Thesis Presented to the Graduate School of the University of Florida in Partial Fulfillment of the Requirements for the Degree of Master of Science EXTRACTING SEMANTICS FROM LEGACY SOURCES USING REVERSE ENGINEERING OF JAVA CODE WITH THE HELP OF VISITOR PATTERNS By Oguzhan Topsakal August 2003 Chair: Joachim Hammer Major Department: Computer and Information Science and Engineering As the need increase for enterprises to participate in large business networks (e.g., supply chains), the need to optimize these networks to ensure profitability also increases. However, because of the heterogeneities of the underlying legacy information systems, existing integration techniques fall short of enabling the automated sharing of data among participating enterprises. Current integration techniques require manual effort and significant programmatic set-up. This necessitates the development of more automated solutions to enable scalable extraction of knowledge resident in legacy systems of a business network, to support efficient sharing. Given that an application is a rich source for semantic information including business rules, we developed algorithms and methodologies to extract semantic knowledge from the legacy application code. Our novel methodology integrates and improves existing techniques including program slicing, program dependence graphs, pattern matching, and design patterns. Our xii

PAGE 13

techniques advance the state-of-the art in many ways, most importantly to bring a generic approach that can be applied to any language code. Semantic knowledge extracted from the legacy application code contains information about the application-specific meaning of entities and their attributes as well as business rules and constraints. Once extracted, this semantic knowledge is important to the schema matching and wrapper generation processes. This thesis presents an overview of our approach. Evidence to demonstrate the extraction power and features of this approach is presented using a prototype developed in the context of the Scalable Extraction of Enterprise Knowledge (SEEK) project at the Database Research and Development Center at the University of Florida. xiii

PAGE 14

CHAPTER 1 INTRODUCTION In todays business markets, many factors increase the competition such as customization of products, demand on rapid delivery, and decrease in profit. To survive in this competitive environment, efficient collaborative production in a business network is required. An enterprise or business network is the collaboration of several firms to achieve a common goal. The success of a business network is highly dependent upon coordination among participants. Decision and integration support tools are needed to improve the ability of a participant in a business network to coordinate, plan, and respond to dynamically changing conditions. Because of the heterogeneity of the legacy information systems of the participants, data and knowledge integration among systems in a business network require a great deal of programmatic setup with limited code reusability. Therefore, there is a need to develop a toolkit that can semi-automatically discover enterprise knowledge from sources; and use this knowledge to configure itself and act as software between the legacy sources. The Scalable Extraction of Enterprise Knowledge 1 (SEEK) project underway in the Database Research and Development Center at the University of Florida is directed at developing methodologies to overcome some of the problems of assembling knowledge in numerous legacy information systems [1,2]. 1 This project is supported by National Science Foundation under grant numbers CMS-0075407 and CMS0122193. 1

PAGE 15

2 1.1 Motivation A legacy source is defined as a complex stand-alone system with poor or nonexistent documentation for the data and application code or other components of the information system. A typical enterprise network has contractors and subcontractors that use such legacy sources to manage their data. The data present in these legacy sources is an important input to making decisions at the project level. Legacy systems of participants of enterprise network usually have a high degree of physical and semantic differentiations for the reasons stated below. These differences cause many problems for accessing and retrieving data from the underlying legacy source to provide input to decision support tools. The problems of providing information for decision support tools [1] can be stated as follows. There is a difference between various internal data storage, retrieval, and representation methods. Some firms might use professional database management systems while some others might use simple flat files to store and represent their data. There are many interfaces including SQL or other proprietary languages that a firm may use to manipulate its data. Because of such high degrees of physical heterogeneity, the effort to retrieve even similar information from every firm in the supply chain requires extensive work on the data stored in each system. There is semantic heterogeneity among firms. Even though the supply chain consists of firms working in the closely related domains, there is a difference in the internal terminology. This kind of heterogeneity presents at various levels in the legacy information source including the application code that may encode business rules. Another challenge in accessing the firms data efficiently and accurately is safeguarding the data against loss and unauthorized usage. Participating firms in the supply chain may want to restrict the sharing of strategic knowledge including sensitive data or business rules. Therefore, it is important to develop third-party tools that assure the privacy of the concerned firm and still extract useful knowledge. The frequent need of human intervention in the existing solutions is another major problem for efficient cooperation. This limits automation of the process which makes it costly and inefficient.

PAGE 16

3 Thus, it is necessary to build extensible data access and extraction technology that automates the knowledge extraction process. 1.2 Solution Approaches The role of the SEEK system is to act as an intermediary between the legacy data and the decision support tool. In general, SEEK [1-3] operates as a three-step process: Step 1: SEEK generates a detailed description of the legacy source including application-specific meanings of the entities, relationships, and business rules. We collectively refer to this information as enterprise knowledge. Extracting enterprise knowledge is a build-time process which is achieved by the data reverse engineering (DRE) component of SEEK. The Schema Extractor (SE), which is a sub-component of DRE, extracts the underlying database conceptual schema while another sub-component of DRE, the Semantic Analyzer (SA), extracts application specific meanings of the entities, attributes, and the business rules of the enterprise. Step 2: The semantically enhanced legacy source schema must be mapped onto the domain model (DM) used by the applications that want to access the legacy source. This is done using a schema mapping process that produces the mapping rules between the legacy source schema and the application domain model. Step 3: The extracted legacy schema and the mapping rules provide the input to the wrapper generator, which produces the source wrapper. The source wrapper at run-time translates queries from the application domain model to the legacy source schema. In this thesis we focus exclusively on the build-time component which is described in Step 1. Specifically, we focus on developing robust and extensible techniques to extract application-specific meanings from code written for a legacy database. To get a comprehensive understanding of the source data and how it is represented, we augment

PAGE 17

4 the schema information extracted by the SE with application-specific meanings discovered by the SA. Let us briefly illustrate our approach using a very simple example from the Construction Scheduling domain. Let us assume that when we extract the schema from the existing legacy source database using SE, we find that it contains a table named Proj which has an attribute named p_id. Without any further knowledge, we would probably not be able to understand the full meaning of these two schema items. This is where semantic analysis comes in. Let us assume we also have access to the application code that uses the database and upon further investigation, SA encounters output statements of the form: "Please Enter Project Number." Using program comprehension techniques described later in this thesis, SA can trace this and other output statements back to the corresponding items in the database where the values are eventually stored. So, if SA can trace the output statement above to p_id of Proj table, we can conclude that Proj stores information about projects and that p_id contains project numbers. Describing the details of how SA works is the focus of this thesis. Specifically, the research describe here extends some of the heuristics for semantic extraction developed previously [2] and produces a more robust, extensible infrastructure for semantic extraction with improved accuracy and performance. 1.3 Challenges Semantic analysis can be defined as the application of techniques to one or more source code files, to extract semantic information to provide a complete understanding of the enterprises business model. There are numerous challenges in the process of extracting semantic information from source code files with respect to the objectives of SEEK, which include the following:

PAGE 18

5 The functionality of the enterprise information system could be separated across several files. Thus, careful integration of the semantic information should be achieved. To gather information from multiple files, first the location of the file in the classpath or inside the imported packages should be specified. The SA may not have access or permissions to all the source code files. The accuracy and the correctness of the semantic information generated should not be affected even if partial or incomplete semantic information is extracted. High-level object oriented language features such as inheritance and method overloading increases the complexity of the SA. Source code and the underlying database design could be modified because of the changing business needs. Attributes with non-descriptive, even misleading names may be added to relations. The SA should correctly discover the application-specific meanings behind this attributes. Existing source code of a legacy system may not reflect the functionality of the running application. The source code might have been displaced or the version information of it may not be accurate. A way of using an applications binary code should be determined to get the latest functionality of the system. The semantic analyzer must be robust and must be capable of analyzing any source code of the target language. The semantic analyzer could be easily configured to accept other language source codes as an input. The semantic analysis approach should be generic enough to accept implementation of new heuristics to extract more information from the source code. Semantic analyzer should be easily maintained when an improvement is desired to be made on the existing functionality. Although the time performance is not a primary concern, SA should finish the analysis in a reasonable time period. SA should be able to parse any SQL statement, obtaining information from it. 1.4 Contributions SA has brought the following contributions, which correspond to the challenges listed above:

PAGE 19

6 SA prototype can accurately integrate the information gathered from multiple files. Current SA can correctly find the location of the desired file in the classpath or inside the imported packages even if it is inside a compressed jar or zip files. The output of current SA still provides potentially valuable information for schema matching. High level object oriented language features like method overloading are successfully handled by SA. SA can correctly discover the application specific meanings of attributes even if the attributes names are non-descriptive or misleading. SA uses state-of-the-art code reverse engineering techniques to get the source code back from the binary code if the source code is misplaced. SA can parse and analyze any source code of Java language. SA can be easily extended to analyze other language source code inputs. SA can be extended to cover new heuristics. SA uses dynamic link list structures not to limit its capacity. SAs object oriented structure provides abstraction and encapsulation of the functionality which makes the maintenance easier. SAs time complexity has significantly decreased. It extracts the semantics with the same accuracy in a shorter period of time when compared to the previous version. Current version of SA can not only extract meaning from SQL Select statements, but also extract semantics from Update, Insert, and Delete statements. 1.5 Organization of Thesis Chapter 2 presents an overview of the related research in the field of business rules, abstract syntax tree generator tools and design patterns. Chapter 3 provides a description of the approach for extracting semantics from the legacy code. Chapter 4 is dedicated to describing the implementation details of semantic analyzer. Chapter 5 highlights the power of the SA in terms of what kind of semantics it can capture. Finally, Chapter 6

PAGE 20

7 concludes the thesis with a summary of our accomplishments as well as issues to be considered by future research projects.

PAGE 21

CHAPTER 2 RELATED RESEARCH In this chapter, we introduce the related research topics of our semantic analyzer. We have combined and used various techniques from different research areas to produce a novel methodology for extracting semantic information from legacy information sources. The research areas mainly related with our semantic analyzer are code reverse engineering, parser generation, design patterns, business rule extraction, and state-of-the-art knowledge extraction techniques like program slicing and pattern matching. We not only base our work on these research areas, but also use state-of-the-art tools that are outcomes of these research areas as well. We introduce these research areas and tools in the order they are used in the implementation of semantic analyzer component of SEEK prototype. First, a code reverse engineering tool, Java decompiler, is introduced. Second, a parser generator tool, Java Compiler Compiler (JavaCC), is introduced. Introduction of the Java Tree Builder (JTB) tool, which is highly related with JavaCC, follows this section. Next, the Visitor Design Pattern, which has an important role in the structure of our approach, is introduced. The Section about lexical and syntactic analysis, control flow graph, program slicing and pattern matching techniques that are use in extracting semantic information follows. Last, we introduce the concept of business rules and the possible locations that they could be found in an information system. 8

PAGE 22

9 2.1 Code Reverse Engineering Source code is the input to our semantic analyzer. This is useful in situations where source code is misplaced or we can not be sure which source code was used to produce the running code in the legacy system. In such a case, we need a way to translate the running code back into source code by using code reverse engineering techniques. This section introduces the decompiler concept and the tool that we use to get .java source code files from .class files. 2.1.1 What is a Decompiler? A compiler translates source code into machine code which the computer can interpret as actions or steps that the programmer wants it to perform 1 In this translation process, a lexical analyzer tokenizes the source code. The tokens are then passed to the language parser which matches one or more tokens to a series of rules and translates these tokens into intermediate code or into machine code. Any source code that does not match a compilers rules is rejected. Most compilers perform much preand post-processing. The pre-processor prepares the source code for the lexical analysis by omitting all unnecessary information, such as the programmers comments and adding in any standard or included header files or packages. A typical post-processor stage is code optimization, where the compiler parses or scans the code, reorders it, and removes any redundancies to increase the efficiency and speed of the code. 1 Decompiling Java Book by Godfrey Nolan, McGraw-Hill, 1998, 358 pages.

PAGE 23

10 A decompiler translates the machine code or intermediate code back into source code. This transformation rarely results in original source code because of the preand post-processing stages. 2.1.2 History of Decompilers The earliest example of a decompiler was written for the Algol-like language Neliac (Navy Electronics Laboratory International ALGOL Compiler) in 1960. Its primary function was to convert non-Neliac compiled programs into Neliac compatible binaries. The first real Java decompiler was written at IBM by Daniel Ford 2 Mocha, the most famous Java decompiler was written by Hanpeter Van Vliet 3 2.1.3 Why Successful Decompiling is Possible in Java Decompiling Java code requires a deep understanding of the Java byte code and the Java Virtual Machine (JVM) The current design of the Java Virtual Machine is independent of the Java Development Kit or JDK. It means that the language may change but the JVM specification is fixed. Decompilation can be done because the JVM is a simple stack machine with no registers and a limited number of high-level instructions or byte codes, making it easy to understand. The JVM requires the compiler to pass on much information such as variable and method names, which would otherwise not be available. The JVMs restricted execution environment and straightforward architecture as well as the high-level nature of many of its instructions help decompilers. 2 Ford D, Jive: A Java Decompiler, at IBM, May 1996. 3 Hanpeter V, C|Net article on August 23, 1996.

PAGE 24

11 Adding a new method in C++ means that all classes that reference that class need to be recompiled. This is known as the fragile superclass problem 4 Java gets around this problem by putting all the necessary symbolic information into the class file. The JVM then takes care of all the linking and final name resolution, loading all the required classes including any externally referenced fields and methods on the fly. This delayed linking or dynamic loading, possibly more than anything else, is why Java is so amenable decompilation. 2.1.4 Purpose of Decompilation Decompilation is often used for retrieving lost source code, learning Java, understanding someones algorithms or techniques, fixing and debugging class-files, and pretty printing. Our reason for Java decompilation is to get the .java source code from our own .class files, when we are not sure about whether .java source code files have the latest functionality of the legacy system. 2.1.5 Examples of Decompilers There are several examples for decompilers. Here, we briefly introduce the first Java decompiler, Mocha, as well as the Jad decompiler that we have used in our project to decompile class files. 2.1.5.1 Mocha Mocha is the first publicly available decompiler which was written by Hanpeter Van Vliet. He also wrote an obfuscator 5 called Crema that attempted to protect Java source code. The source code for both Crema and Mocha were sold to Borland. After 4 Definition of the Fragile Superclass Problem can be found in the white paper The Java Language Environment by James Gosling and Henry McGilton, May 1996. 5 An Obfuscator removes all clues that might have given by programmer when naming variables, methods, and parameters by altering the names into unintelligible names or even into control characters.

PAGE 25

12 that, Borland released JBuilder with a built in obfuscator. Borland claims that JBuilders obfuscator safeguards Java code from decompilation by replacing ASCII variable names with control characters. JBuilder comes with an API decompiler, which shows the public methods and their parameters. The same thing can be achieved using the javap 6 command in JDK. 2.1.5.2 Jad Jad is the decompiler that we selected from among a number of decompilers because of its features [4]: Jad is a 100% pure C++ program and it works several times faster than other decompilers written in Java. Jad does not use the Java runtime for its functioning; therefore no special setup, like changes to the classpath variable, is required. Jad gives full support for inner and anonymous classes. Jad automatically converts identifiers garbled by Java obfuscators into valid ones. Jad is free for non-commercial use. Jad can be used for the following reasons: For recovering lost source codes; For exploring the sources of Java runtime libraries; As a Java dis-assembler; As a Java source code cleaner and beautifier. Like every decompiler, Jad has some limitations. While decompiling classes which contain inner classes, Jad cannot reliably sort out the extra arguments added to class constructors by Java compiler. Currently Jad makes no use of the Java class hierarchy information. Consequently, Jad always chooses java.lang.Object as a common super class of two different classes and inserts auxiliary casts where necessary. 2.2 Parser Generation For programmers, writing a parser for a grammar has always been an error-prone task. Especially when we deal with a grammar like Java that has so many productions, it is also a time-consuming task to get a parser for that grammar. Therefore, there has been a lot of research on automatically generating a compiler from a formal specification of a 6 javap: Java profiler outputs ASCII representations of a class files byte code

PAGE 26

13 programming language. Our focus in this thesis is extracting valuable information from legacy source code. For this reason, we choose to use one of this state-of-the-art parser generation tools to get our Java and SQL parsers, instead of writing our parsers from scratch. In this section, Java Compiler Compiler (JavaCC) tool, which is used to generate our parsers, is introduced. 2.2.1 Compiler-Compiler Tools Research on automatic generation of compiler from a formal specification of a programming language brought us so-called compiler-compiler tools such as Yacc, Bison, ANTLR, and JavaCC. These tools play a key role in the software development process of compilers and have made their construction much easier. Some of these well-known compiler-compiler tools are: Lex & Yacc: Lex builds lexical analyzers from regular expressions. Yacc converts a grammar specification into a table-driven compiler that could produce code when it had successfully parsed productions from that grammar. Flex & Bison: They are Free Software Foundation's GNU project produced improved versions of lex and yacc for use on platforms that did not run a derivative of the Unix operating system. DFA and ANTLR (Components of PCCTS 7 ): They provide the same functions as Lex and Yacc. However, the grammars that ANTLR accepts are LL(k) grammars as opposed to the LALR grammars used by Yacc. 2.2.2 JavaCC and its Features JavaCC (Java Compiler Compiler) is the most popular parser generator for use with Java applications [5]. It is a tool that reads a grammar specification and converts it to a Java program that can recognize matches to the grammar according to that specification. 7 PCCTS: The Purdue Compiler Construction Tool Set was developed at Purdue University.

PAGE 27

14 JavaCC was first released by Sun with the name JACK. The latest version was released by Metamata Inc. WebGain 8 was the caretaker company of it for a while. Currently, JavaCC can be obtained from Sun Microsystems Web site 9 In addition to the parser generator itself, JavaCC provides other standard capabilities related to parser generation such as tree building (via a tool called JJTree), actions, debugging, etc. JavaCC does not have any runtime libraries (such as JAR files). The only files that are needed for the parser are those generated by JavaCC. The parser, which is generated by JavaCC, is a top-down LL(1) parser 10 with a variable amount of look-ahead. JavaCC gives the ability to define LL(k 11 ) grammars as well. Lexical specifications can define tokens not to be case sensitive either at the global level for the entire lexical specification or on an individual lexical specification basis. The lexical analyzer of the JavaCC-generated parser has a feature for keeping comments when they are defined as special tokens. Special tokens are ignored during parsing, but these tokens are available (unlike skipped items, such as white spaces) for processing by the tools. In our implementation, we used this feature to gather comments associated with business rules and methods. Figure 2-1 below illustrates how special tokens are handled in a JavaCC parser. In Figure 2-1, S1, S2, and S3 devote special tokens, while T1, T2, and T3 devote the real tokens. If there were not a feature for keeping special tokens, S1, S2, and S3 would be skipped during parsing the code. As shown in Figure 2-1, Token class has a specialToken member to point the special token 8 http://www.webgain.com 9 http://javacc.dev.java.net/ 10 Definitions of basic compiler terms can be found in Appendix B 11 k: number of look-ahead.

PAGE 28

15 that resides just before itself inside the code. T2 token, which is class, has two special tokens (comments) (S1://open to public and S2:/* special token */ ) that are connected to its specialToken pointer. The left-hand side of Figure 2-1, is the figurative representation of the code that is on the right-hand side. ---next ---next ---. | T1 | -----------------> | T2 | -----------------> | T3 | . ---------/ / ---next ---/ ---/ | S1 | <-| S2 | <| S3 | <---------/ / ----.next --------> ' .specialToken <-------------Class Token{ Int kind; String Image; Token next; Token specialToken;} ---------------------------------------------------------------public //open to public /* special token*/ class /*this is a sample*/ Sample1{ public Sample1() {} } --------------------------------------------------------------S1 : open to public S2 : special token S3 : this is a sample T1 : public T2 : class T3 : Sample1 Figure 2-1 Special tokens in JavaCC As shown in Figure 2-2, JavaCC processes specification file (.jj extension) and output the Java files that has the code of the parser that can process the languages that are according to the grammar in the specification file. Parser Java files are both listed in Figure 2-2 and their functionality is described in Section 4.3. JavaCC Grammar Specification .jj file Parser Java Files ParserName.java ParserNameConstants.java ParserNameTokenManager.javaParseException.java SimpleCharStream.java ParserNameTokenManager Token.java TokenMgrError.java Java Compiler Figure 2-2 Input and output of JavaCC

PAGE 29

16 Once the parser code is generated, it is compiled with the Java compiler (javac) to get the parser. The outcome code is used to parse the desired grammar, see Figure 2-3. Java Compilerjavac ParserName.java Parser Class Files java ParserName FileName Abstract Syntax Tree Parser Java Files AST Figure 2-3 Compiling the Parser Generated by JavaCC and Using It to Get AST. 2.2.3 The Grammar Specification File of JavaCC There are three major components in the grammar specification file. Definitions of terminal tokens (or terminals), e.g., words that are expected in the input. Definitions of production rules (or productions), e.g., rules about how tokens combine to form legal statements in the language. Java code to tie everything together and perform actions when certain productions occur. Grammar specification files 12 for some grammars such as Java, C ++, C, SQL, XML, HTML, Visual Basic, and XQuery can be found at the JavaCC grammar repository Web site at UCLA [6]. 2.2.4 Java Tree Builder (JTB) In this subsection Java Tree Builder tool is introduced. We build our semantic analyzer structure according to the visitor pattern technique. Rationale behind the usage of visitor patterns is explained in the following section and in Chapter 3. JTB essentially takes a grammar specification file as an input and changes this specification file so that JavaCC can use this specification file to generate parsers according to visitor pattern structure. JTB, written at Purdue University, is used with the JavaCC parser generator tool [7]. It takes a plain JavaCC grammar file as input and automatically generates the following: 12 An example of a grammar specification file can be found in Appendix A

PAGE 30

17 A JavaCC grammar with the proper annotations building the syntax tree during parsing. (The file jtb.out.jj) A set of syntax tree classes based on the productions in the grammar, utilizing the Visitor design pattern. (Files in syntaxtree directory/package) Visitor and ObjectVisitor interface, DepthFirstVisitor and ObjectDepthFirst visitors (Files in visitor directory/package) The inputs and outputs of JTB are shown in Figure 2-4. The syntaxtree and visitor package outputs (Figure 2-4) are explained in the following paragraphs. EBNF grammar Java Compiler Compiler JavaCC JTB Tool Syntax Tree Node Classes(in syntaxtree package) EBNF Grammar with Embedded Java Code (jtb.out.jj file) Default Visitors and Interfaces (in visitor package) Figure 2-4: Inputs and Outputs of JTB Tool. The syntaxtree directory/package contains syntax tree node classes generated based on the production rules in JavaCC grammar. Each production has its own class. Syntax directory also contains eight special node classes like Node, NodeChoice, NodeOptional, etc. Table 2-1 below specifies a list of these special nodes. Table 2-1 Automatically generated tree node interface and classes Node Node interface that all tree nodes implement. NodeListInterface List interface that NodeList, NodeListOptional, and NodeSeqeunce implement. NodeChoice Represents a grammar choice such as ( A | B ) NodeList Represents a list such as ( A )+ NodeListOptional Represents an optional list such as (A )* NodeOptional Represents an optional such as [ A ] or ( A )? NodeSequence Represents a nested sequence of nodes NodeToken Represents a token string such as "package"

PAGE 31

18 The generated classes include accept methods with the visitor interface as a formal parameter. This parameter is used to pass the name of the class back to the visitor through dynamic binding. Each accept method takes a visitor as an actual parameter and invokes the visit method of that visitor having the node class as an actual parameter to determine the appropriate visit method. [8] Separating the generated tree node classes into their own package greatly simplifies file organization. When the grammar is stable and not subject to change, once these classes are generated and compiled, it is not necessary to deal with them again. All of the changes and additions are done to the visitor classes when a new functionality is introduced or an existing functionality is changed. The visitor directory/package contains the visitor interfaces, Visitor and ObjectVisitor, and their default implementations, DepthFirstVisitor and ObjectDepthFirst. 13 The Visitor interface contains one visit method declaration per production in the grammar, plus one visit method declaration for each of the automatically generated special node classes. The default visitor, DepthFirstVisitor, class implements the visitor interface and it simply visits each node of the tree. The JTB puts the navigation control into the visit methods of the Visitor [9]. JTB generates default navigation behavior in the implementation of the default visitor, DepthFirstVisitor or ObjectDepthFirst. A visitor that wants to use this route to process operations on specific nodes of tree extends the default visitor and overrides the method related to those specific nodes 14 13 An example of visitor class implementation can be seen in Appendix D. 14 An example of a visitor class can be found in the Appendix D.

PAGE 32

19 Operations on abstract syntax trees can then be defined separately from the abstract syntax classes in visitor classes that rely on the generated accept methods. The separation of operation and structure is crucial in this class of tools to avoid editing and recompiling generated code [9]. 2.3 Visitor Design Pattern Our goal is to build semantic information extraction techniques that can be applied to any source code and can be extended with new algorithms. Visitor design pattern is the key object oriented technique to reach this goal. In this section, we introduce the Visitor Design Pattern and its features. 2.3.1 Design Patterns Design Patterns [10] are general solutions to design problem occurring repeatedly in many projects. The Design Patterns can be listed in three categories: Creational Patterns: Abstract Factory, Builder, Factory Method, Prototype, and Singleton. Structural Pattern: Adapter, Bridge, Composite, Decorator, Flyweight, and Proxy. Behavioral Patterns: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, and Visitor. 2.3.2 Features of Visitor Design Pattern A Visitor design pattern is a behavioral pattern which is used to encapsulate the functionality that is desired to be performed on the elements of a data structure. It gives the flexibility to change the operation being performed on a structure without the need to change the classes of the elements on which the operation is performed. Visitors make it easy to add operations. New operations over the object structure can be defined simply by adding a new visitor. In contrast, if the functionality is spread over many classes, each

PAGE 33

20 class must be changed to define a new operation 15 The idea behind a visitor pattern is to insert an accept method in each class. The accept method passes control back to the visitor which acts as a repository for the new methods 16 Visitor classes localize related behavior in the same visitor and unrelated sets of behavior are partitioned in their own visitor subclasses. Using visitor patterns, each new operation can be added separately and the member classes are independent of the operations that apply to them. If the classes defining the object structure rarely change, but new operations over the structure are often defined, a visitor design pattern is the perfect choice. Since object structure classes do not change, we do not need to recompile them when new functionality is added. 2.3.3 Analogy for Visitor Pattern It is often difficult to understand design patterns. To explain concepts like design patterns, analogies from real life are useful. To increase the readers understanding of visitor pattern, we introduce the following analogy. Let us suppose that our concrete, invariant structure is the digestive system of human-body and our visitor is a computerized pill. Let us further assume, we would like to get information from our digestive system by using the pill as an information carrier. When the pill is swallowed, it visits the organs of our digestive system and sends information about those organs to the outside world. In this way, no surgery is needed to put devices inside each organ to send information to the outside world. The pill sends information about the organs while it is traversing through the digestive system. The 15 Comparison of possible approaches (Instanceof and Type Casts, Dedicated Methods and The Visitor Pattern) for performing operations on node objects in a heterogeneous aggregate structure are discussed in detail in [5]. 16 An example of a visitor pattern implementation can be found in Appendix D.

PAGE 34

21 information that is send is processed in the outside world. Figure 2-5 may help you to imagine this analogy. A B Figure 2-5 Analogy for visitor pattern. A) Human digestive system (Concrete structure) B) Pill (Visitor Structure). 2.3.4 Double Dispatching in Visitor Patterns The visitor pattern mechanism provides double dispatching for the selection of the functionality that will be performed on a specific node. This means that the call made to the method that inherits the functionality for a specific node depends both upon the type of the visitor and of the data structure of the node. This is achieved as follows: Each node in the data structure has an accept method that deals with the abstract visitor. When a node accepts a visitor, it makes a call to the visitor which includes the node's class. The visitor will then execute its algorithm for that element. The double dispatching technique completely replaces the need for conditional statements.

PAGE 35

22 2.4 State-of-the-art in Extracting Knowledge from Application Code In this section, we introduce several techniques for extracting information from source code. The problem of extracting knowledge from application code has been investigated in several research areas such as lexical and syntactic analysis, control flow analysis, program slicing, and pattern matching. These areas are described in the previous work about semantic analysis applied to SEEK project [2]. We briefly describe these techniques, since they are used by our semantic analysis approach. 2.4.1 Lexical and Syntactic Analysis Analysis of source code requires conversion to a form that can easily be processed by a program. An abstract Syntax Tree (AST) is a type of representation of source code that facilitates the usage of tree traversal algorithms. Lexical and syntactic analysis of a source code, in accordance to the context free grammar of the underlying language, generates an AST. Grammars themselves are described in a stylized notation called Backus-Naur Form [11] in which the program parts are defined by rules and in terms of their constituents. An AST is used to show how a natural language sentence is broken up into its constituents. The parser that is generated by JavaCC produces AST of a source code. After the AST is produced, it is ready to be analyzed by visitor patterns. 2.4.2 Control Flow Analysis After we obtain the AST, it is used for Control Flow Analysis [12]. There are two major types of CFA; Inter-procedural and Intra-procedural analysis. Inter-procedural analysis determines the calling relationship among program units while intra-procedural analysis determines the order in which statements are executed within these program units. Together they construct a Control Flow Graph (CFG). In our approach we

PAGE 36

23 construct the CFG and use the calling relationships on CFG between methods to traverse between classes. 2.4.3 Program Slicing Program slicing was introduced by Weiser [13] and has supported various program comprehension techniques. Weiser defines the slice of a program for a particular variable at a particular line in the source code as that part of the code that is responsible for giving a value to the variable at that point in the code. The idea behind slicing is to retrieve the code segment that has a direct impact on variables of interest. Starting at a given point in the program, program slicing automatically retrieves all relevant code statements containing control and/or data flow dependencies. 2.4.4 Pattern Matching Pattern matching identifies interesting code patterns and their dependencies. For example, conditional control structures such as if..then..else or case statements may encode business knowledge, whereas data type declarations and class or structure definitions can provide valuable information about the names, data types, and structure of concepts represented in an underlying database. A code pattern recognizer performs the matching of patterns from the templates against patterns in the source code. 2.5 Business Rules Extraction In this last section of Chapter 2, we investigate the research on business rules. Extracting business rules embedded in information systems is an important issue in understanding the functionality of the information system. Before attempting to solve the problem of extracting business rules, we define what a business rule is, what kinds of business rules typically exist, and how they are encoded in the information systems.

PAGE 37

24 2.5.1 Business Rules Business rules represent core business practices and policies, and they determine what is possible or desirable in running a business [14]. A well-known definition states that: A business rule is a statement that defines or constrains some aspect of the business. It is intended to assert business structure or to control or influence the behavior of the business [15]. 2.5.2 Categories of Business Rules Business rule may be implemented differently in different parts of a system and require different techniques to extract them. For this reason, it is beneficial to know the categories of business rules and how they could be implemented in an information system. For example [14], [15] provide two possible ways to categorize business rules. Using the approach suggested in [14], we can distinguish the following classes of business rules: 1. Structural business rules: Structural business rules are statements about the data objects belonging to an organization. Structural business rules can be further divided into following categories: Definitions Example: Anyone placing an order with us is a customer. Relations between objects Example: Customers are identified by their address, postcode, and contact. Derivation statements Example: The total cost of the rental is calculated from the sum of insurance amount and rental amount. 2. Behavioral business rules: Behavioral business rules are statements about dynamic aspects of a business. They specify what can or will be done to data objects in response to events. The actions taken in response to the events may result in a state change for the data objects affected by the business rules.

PAGE 38

25 Example: When an insurance claim is made, a claim reference number is allocated. 3. Constraint business rules: Constraint business rules are statements that bring limitations on the operation of the business rules. Constraint business rules define the conditions under which a business can operate. Example: A customer must have at least one account, but no more than three. 2.5.3 Where Are Business Rules Implemented in Information Systems Categories of business rules that are stated in the previous section can be implemented in various parts of an information system. It is beneficial to identify what we are looking for before we look for it. If we know what kind of business rule we can find in the subparts of the information system, then we can construct our search algorithms according to the category of the business rule for which we are looking. Therefore, we define which business rule categories could be implemented in which part of the information system. Structural business rules: Definitions which are also a part of structural business rules are trying to be supported by the ontology. Relations which are also structural business rules are generally defined by the data model and implemented in the schema. Derivation business rules are implemented as program code. Behavioral business rules: Behavioral business rules often implement more complex business logic than can be defined through a data model, and they are usually implemented as procedural programs. Constraint business rules: Constraint business rules may be implemented in various parts of an information system. In older systems, constraint business rules tend to be implemented as program code. In newer systems, they are also implemented in the schema.

PAGE 39

26 2.5.4 Extracting Business Rules The aim of extracting business rules is to understand the functionality of information system. There are mainly four inputs to our methodology for business rule extraction. These are: Schema: It is the main input for data understanding, and it provides structural and some constraint information about data. Data: The data stored in a database may also be examined for data understanding purposes. This is because data may contain certain properties that are not specified in the schema. Also business rules that were extracted from data can be used to verify the business rules that were extracted from other inputs (namely, schema or programs). Programs: Program code associated with a database system is another type of input for data understanding. A database system may include application programs, stored procedures, or user interface forms. These programs contain clues about data structures and constraints. These clues, when used in conjunction with schema/data, could potentially increase data understanding. Transactions: Operations are recorded in a transaction log in a database system. A transaction log may be used as an input for data understanding. The sequence of operations on a database, and the relationship among operations that take place in one transaction, can be beneficial to understand the functionality of the information system. 2.5.5 Importance of Business Rule Extraction from Program Code Over time, business rules evolve and the software that encodes them is also changed and maintained. As the information system becomes large and ages, the changes in business functionality are reflected in program code, without changing the corresponding documentation, or without changing any other part of the information system. Thus, the business organization often trusts the code more than any other documents. Therefore, extracting business rules from program code becomes more important for a better understanding of the legacy information systems. Information gathered from the business rules inside the program code are then used to semantically enhance the schema of the information system.

PAGE 40

CHAPTER 3 SEMANTIC ANALYSIS ALGORITHM 3.1 Introduction A conceptual overview of the SEEK knowledge extraction architecture is shown in Figure 3-1 [1]. SEEK applies Data Reverse Engineering (DRE) and Schema Matching (SM) processes to legacy database(s), to produce a source wrapper for a legacy source. This source wrapper will be used by another component (not shown in Figure 3-1) to communicate and exchange information with the legacy source. It is assumed that the legacy source uses a database management system for storing and managing its enterprise data or knowledge. Reports Legacy DB Legacy ApplicationCode Schema Matching (SM) Mapping rules revise, validatetrain, validate Schema Information Schema Extractor (SE) Embedded Queries Semanti c Analyzer(SA) Data Reverse Engineering (DRE) Domain Ontology DomainModel Source Schema,Semantics, Business Rules, Legacy Source to Wrapper Generator (WGen) Application Figure 3-1 High-level view of the SEEK Architecture. 27

PAGE 41

28 First, SEEK generates a detailed description of the legacy source by extracting enterprise knowledge from it. The extracted enterprise knowledge forms a knowledge base that serves as the input for subsequent steps. In particular, the DRE module shown in Figure 3-1 connects to the underlying DBMS to extract schema information (most data sources support at least some form of Call-Level Interface such as JDBC). The schema information from the database is semantically enhanced using clues extracted by the semantic analyzer from available application code, business reports and, in the future, perhaps other electronically available information that could encode business data such as e-mail correspondence, corporate memos, etc. It has been the experience, through visits with representatives from the construction and manufacturing domains, that such application code exists and can be made available electronically [1]. Second, the semantically enhanced legacy source schema must be mapped into the domain model (DM) used by the application(s) that want(s) to access the legacy source. This is done using a schema mapping process that produces the mapping rules between the legacy source schema and the application domain model. In addition to the domain model, the schema matcher also needs access to the domain ontology (DO) that describes the domain model. Finally, the extracted legacy schema and the mapping rules provide the input to the wrapper generator (not shown), which produces the source wrapper. The three preceding steps can be formalized as follows [1]. At a high level, let a legacy source L be denoted by the tuple L = (DBL, SL, DL, QL), where DBL denotes the legacy database, SL denotes its schema, DL the data, and QL a set of queries that can be answered by DBL. Note, the legacy database need not be a relational database, but can

PAGE 42

29 include text, flat file databases, or hierarchically formatted information. SL is expressed by the data model DML. We also define an application via the tuple A = (SA, QA, DA), where SA denotes the schema used by the application and QA denotes a collection of queries written against that schema. The symbol DA denotes data that is expressed in the context of the application. We assume that the application schema is described by a domain model and its corresponding ontology (as shown in Figure 3-1). For simplicity, we further assume that the application query format is specific to a given application domain but invariant across legacy sources for that domain. Let a legacy source wrapper W be comprised of a query transformation (3-1) and a data transformation (3-2) where the Q and D are constrained by the corresponding schemas. fWQ : QA QL (3-1) fWD : DL DA (3-2) The SEEK knowledge extraction process shown in Figure 3-1 can now be stated as follows. Given SA and QA for an application that attempts to access legacy database DBL whose schema SL is unknown, and assuming that we have access to the legacy database DBL as well as to application code CL that accesses DBL, we first infer SL by analyzing DBL and CL, then use SL to infer a set of mapping rules M between SL and SA, are used by a wrapper generator WGen to produce (fWQ, fWD). In short: DRE: (DBL, CL) SL (3-3) SM : (SL, SA) M (3-4) WGen: (QA, M) (fWQ, fWD) (3-5)

PAGE 43

30 Thus, the DRE algorithm (3-1) is comprised of schema extraction (SE) and semantic analysis (SA). This thesis concentrates on the semantic analysis process by analyzing application code CL to provide vital clues for inferring SL. The implementation and experimental evaluation of the DRE algorithm have been described in detail in [1]. The following section focuses on the semantic analyzer approach. 3.2 Objective of Semantic Analysis The main purpose of semantic analysis is to understand the meaning of database repository. In the process of semantic analysis, we extract information that can be used to enhance the schema of the legacy source (SL). This SL will then be used to produce mapping rules between SL and the applications (SA) that want to access the legacy source. Our input to the semantic analysis process can be any kind of code (CL) that inherits functionality that operates on the legacy database (DBL). This code can be application code, as well as triggers or stored procedures inside the corresponding database. Our current prototype works on application code and extracts semantics out of that by using state-of-the-art techniques in code reverse engineering, abstract syntax tree generation and object oriented programming. Our prototype is easily extensible to analyze any programming language, trigger codes, and stored-procedure code that exist inside legacy databases. Our current semantic analyzer is configured to extract information from Java code. We choose the Java programming language because it is becoming the dominating programming language in the enterprise information systems. Also, Java promises to be the programming language that inherits semantics of future legacy systems. In the next

PAGE 44

31 section you will find detailed explanation of the main components of our Java semantic analyzer. 3.3 Components of the Semantic Analyzer The semantic analyzer (Figure 3-2) has three main components. Decompiler, Abstract syntax tree generator Information extractor. Let us give a detailed description of the techniques and rationale used to form each of these components. Java File De-compiler Abstract Syntax Tree Generator Class File Information Extractor Figure 3-2 Semantic Analyzer Components. 3.3.1 Decompiler Legacy information systems often have poor or outdate documentation. Application code is changed over time and documentation becomes inconsistent with the functionality of the code. In such a case, the most reliable source of semantic information of the legacy system becomes the application source code. There can be situations where source code could be misplaced, or the versions of source code could be disorganized. In that case, we can not be sure as to which source code used to produce the running code on the legacy system and which source code was has the latest functionality of the legacy system. In this situation, the only reliable information source may be the running application, .class files. We can recover Java source code (.java) files by the decompiler component of semantic analyzer. As it is illustrated in Figure 3-2, using decompiler is optional. If we

PAGE 45

32 are sure that .java files reflect the latest functionality of the legacy system, we can skip the decompiler stage. How can we be sure that the original source code and the de-compiled source code are the same? There is a way to test this. We can recompile the .java file of decompiled .class file with javac and check if the sizes of the original class file and the recompiled class files are the same. The approximation of the length of the sizes of these two files will give us a clue about how the decompiling process is successful. The Figure 3-3 illustrates this test. Class File found and copied Check whether they are equal in size or not? Recompiled Class File Directory Class File Directory JAD decompiler j avac Decompiled Java File Directory Class Decompiler Class Recompiler Figure 3-3 Checking the success of decompiling process. 3.3.2 Abstract Syntax Tree Generator Our second component is the abstract syntax tree generator. The essence of the abstract syntax tree (AST) in program comprehension is introduced in Chapter 2. We use JavaCC tool to automatically generate AST generator programs. Detail description of JavaCC tool and the idea behind using this tool is given in Chapter 2. The AST generator (parser) that is produced by JavaCC was tested over thousands of java program code. This makes our AST generation process robust and error-free.

PAGE 46

33 3.3.3 Information Extractor The information extractor component, which is shown in Figure 3-2, is composed of several visitor classes. These visitor classes traverse on the AST of the application code to extract the desired information. A visitor pattern lets programmer to encapsulate related behavior in the same visitor and separate the unrelated ones into other visitors. Our information extractor contains visitor patterns to extract variable information, to identify the potential value of variables, to extract the flow of program code, to extract the business rules, to extract the comments inside the code, to extract the SQL statements, and to write the AST in an XML file. If we need any new operation over the object structure, it can be defined simply by adding a new visitor. Detailed descriptions and implementations of visitor patterns are explained in Chapter 2 and Chapter 4. There are two main steps in the algorithm that extract semantic information. In the first step, control flow graph (CFG) is extracted, declaration information of each variable and method are written into symbol table and AST of the program code is written into an XML file. In the second step, we identify the slicing variables and get the business rules, comments, SQL statement, and relate meanings of the variables with the table columns. These steps are illustrated in Figure 3-4 and are explained in detail in Section 4.4. Prepare Classes: Form Symbol Table Form Control Flow Graph Anal y ze Methods: Extract Slicing Variable Extract Business Rules and Comments Process SQL statements AST Symbol Table CFG Semantic Info Figure 3-4 Two main steps of Information Extraction. In the first step, information about all variables is gathered and the AST of each method is saved. In the second step, we do not analyze the class as whole but we analyze

PAGE 47

34 only the methods in the class that are used by method calls. By this approach, we save work and improve performance. 3.4 Extensibility of the Semantic Analyzer The objective of semantic analysis is to develop techniques for extracting information from legacy systems. The input of the semantic analysis process can be a trigger code, a stored procedure, or a java code. More generally, the input can be any code that expresses semantic information about the legacy source on which it operates. For this reason our techniques in semantic analysis should be extensible to any programming language platform. Extensibility of the semantic analyzer is achieved because JavaCC provides an AST generator that can easily be plugged in and out. Abstraction of AST generator from the information extractor increases the extensibility of semantic analyzer. If the functionality of information extraction and AST generation are fully separated from each other, then the extensibility of semantic analyzer to other languages will be much easier. This separation of functionality of these two components is supported by visitor patterns. Visitor patterns provide the flexibility to change the operation being performed on a structure without the need for changing the classes of the elements on which the operation is performed. By using visitor patterns, we do not embed the functionality of the information extraction inside the classes of AST generator. This separation lets us to focus on the information extraction algorithms regardless of the programming language that is being analyzed. To get a structure for Visitor pattern usage we use the JTB tool [7] to augment our structure to be used by visitor patterns. A detailed description and implementation of JTB is given in Chapter 2 and Chapter 4.

PAGE 48

35 3.5 Extracting Semantics from Multiple Files The current version of the SA prototype can extract semantics from multiple class files by starting from an initial driver program file and analyzing all program files in the control flow graph. The functionality of typical enterprise applications spreads over multiple files. Therefore, one must extract semantics from multiple files and combine them for a better understanding of legacy source. Figure 3-5 gives an example of how functionality could be separated into different files. In this example, we start from the main method of Class1 source file. Inside the main method, method2 of Class2 class is invoked. This means, we need to examine method2 of Class2. To examine it, our File Finder finds the location of the source code file of Class2. Whenever a method is invoked on another class, this class source file is found and process continues from this class file. As we have mentioned before, there are two main steps in information extraction. In the first step, we find all the class files that will be analyzed and prepare the control flow graph by finding out interand intra-procedural relationships. In the second step, we analyze the methods in the order they are called starting from the main method of the driver class. These steps are explained in detail in Section 4.4. It can be readily observed in Figure 3-5 that all the methods of a class file may not be used. For this reason, our information extractor only analyzes the methods that are used in the control flow. In the example Figure 3-5, we do not analyze method1 of Class1, method1 of Class2, and method3 of Class3. Analyzing the code, method by method, helps us to improve not only the temporal performance of semantic analyzer, but also its correctness. Unused code (methods) inside classes may lead to incorrect, misleading information.

PAGE 49

36 Class1 Class2 Class3 method1 { } method2 { } main{ .. Class2.method2 .. method2 .. } method1 { } method2 { Class3.method2 .. . .. } method3 { } method1 { } method2 { .. .. method1 .. .. } Figure 3-5 Traversing between class files 3.6 Finding the Class Source Code Files The Semantic Analyzer follows the same logic as the Java Virtual Machine (JVM) to find a class source code file. When we run a Java application, the JVM first searches for the class that was given as a parameter. JVM searches for this class file in the directories that are stated in the environment variable ClassPath. When JVM finds the class file, it starts executing it from its main method. When a method is invoked on an instance of a class, JVM continues its execution inside that method of the specified class. JVM finds this class by using both the ClassPath information and package import information of the class that is currently being executed.

PAGE 50

37 The File Finder module of the SA imitates the same logic to find the files that is analyzed. File Finder module first gets the ClassPath information. As we traverse through the classes, the current classs package/class import information is given to the File Finder. When a new class file is searched, File Finder uses both ClassPath and import information to find the location of the searched file. As it is illustrated in Figure 3-6, ClassPath information is initially given to File Finder module. While we traverse between classes, each class package and import information is feed backed to the File Finder. When a class is to be analyzed, its name is given to File Finder and its source code file location is found by the File Finder. File Finder can correctly find the location even if it is inside a compressed jar or zip file. File Finder CLASSPATH Package Import Info File Name to Search Location of File Figure 3-6 File Finder 3.6 Slicing Variables The semantic analysis algorithm is based on several observations based on the general nature of legacy application code. Database application code always has embedded queries. The data retrieved or manipulated by queries is displayed to the end user. Both the queries and the output statements contain rich semantic information [2]. The SEEK SA aims at augmenting entities and attributes in the database schema with their application specific meanings. It is reasonable to state that the variables that appear in input/output or on database statements should be traced throughout the application code. We will call these variables slicing variables [2]. No matter how large the number

PAGE 51

38 of slicing variables is, we can extract the semantics by a single pass through the AST. In each input-output statement we check if the variable in the statement is a slicing variable or not. If it is a slicing variable, we associate the meaning that was gathered thus far with that slicing variable. The single pass does not cause any information loss because of the data structure used, but it decreases the run-time complexity of the algorithm. 3.7 Heuristics Used In this section, we describe the heuristics used in extracting information from input/output statements. Heuristic1: Application code generally has input-output statements that display the results of queries executed on the underlying database. Typically, output statements display one or more variables and/or contain one or more format strings. A format string is defined as a sequence of alphanumeric characters and escape characters within quotes. An escape character is a backslash character and followed by a sequence of alphanumeric characters (e.g., \n, \t, \r etc), which in combination indicate how to align and format the output. System.out.println(\n Activity Name: \t + v); In the example above, the string \n Activity Name: in the statement represents the format string. The escape sequence \n specifies that the output should begin on a new line. Heuristic 2: The escape characters in format string do not include any semantic meaning, so we can eliminate them. In the example below; \n and \t have no semantic meaning. System.out.println(\n Activity Name: \t + v);

PAGE 52

39 Heuristic 3: The set of slicing variables includes variables that appear in input, output, or database statements. This is the set of variables that provide the maximum semantic knowledge about the underlying legacy database. Heuristic 4: The format string in an input-output statement describes the displayed slicing variable that comes after this format string. System.out.println(\n Activity Name: \t + v); In the example above, the semantic of the variable v exists inside the format string \n Activity Name: \t. Heuristic 5: The format string that contains semantic information and the variable may not be in the same statement. System.out.println(\n Activity Name:); System.out.print(v); Let us refer to the first output statement with the format string as s1 and the second output statement that actually outputs the value of the variable as s2. Notice that, s1 and s2 can be separated by an arbitrary number of statements. The format string s1 gives clues about the application meaning of v in output s2. Heuristic 6: There may be an arbitrary number of format strings in different statements that inherits semantics, before we encounter an output of slicing variable. Concatenation of the format strings before the slicing variable will give more clues about the variable semantic. System.out.println(\n Project:); System.out.println(\n Activity Name:); System.out.print(v);

PAGE 53

40 In the example above, variable v is described by both \n Project: and \n Activity Name: format strings. Let us call the first output statement with the format string as s1, the second output statement with the format string as s2, and the second output statement that actually outputs the value of the variable s3. Notice that, s1, s2, and s3 can be separated by an arbitrary number of statements. In such a case, all the format string should be concatenated to form the format string that gives clues about the application meaning of v. Heuristic 7: There may not be any output statement that has format string before the output statement of variable. The semantic information of variable may be given before the output statement of another statement. In the example below, the semantic of variables v1, v2, and v3 are all inherited inside the format string of first output statement. System.out.println(\n Project \t Activity \t Work Item); System.out.print(\t + v1); System.out.print(\t + v2); System.out.print(\t + v3); A classic example of this situation in database application code is the set of statements that display the results of a SELECT query in a matrix format. The matrix title and the column headers contain important clues about the application specific meanings of variables displayed in the individual columns of the matrix. Heuristic 8: If a statement s assigns a value to variable v, and s retrieves a value of a column c of table t from the result set of a query q, we can associate vs semantics with column c of table t.

PAGE 54

41 resultset1 = s.executeQuery(Select number from Activ); no = resultset1.getString(1); System.out.println(Activity no: + no); In the example above, no variable is associated with the semantic Activity no. It is also associated with first column of the query which is number. So the column number can be associated with the semantic Activity no. Heuristic 9: If a variable is used in the where clause of a SQL statement, then this variables application meaning can be associated with the column in the where clause. query = "SELECT activ FROM Activity WHERE activ_no = '"+input+"'"; resultSet = sqlStatement.executeQuery(query); System.out.println(Activity no: + input); The example above shows an example of how a variable can be used in the where clause of a SELECT condition. In this example, the input variables meaning can be associated with the meaning of activ_no column. This heuristic can be used for UPDATE, DELETE, and INSERT conditions as well. The where clause of any SQL statement can give clues of variable-column relations. Heuristic 10: If a variable is used to set the value of a column in the UPDATE SQL statement, then this variables application meaning can be associated with that column. In the example below, the application specific meaning of name variable can be associated with the column active_name. updateSQL = UPDATE Activity SET active_name = +name+"' WHERE activ_no='"+first + "'"; sqlStatement.executeUpdate(updateSQL);

PAGE 55

42 Heuristic 11: Business logic is encoded either as assignment statements or conditional statements like if..then..else, switch..case, etc. or a combination of them. Mathematical formulae translate into assignment statements while decision logic translates into conditional statements [2]. If slicing variable v is part of an assignment statement s then statement s represents a business rule involving variable v. The assignment, in the below example, is a potential business rule. slicingVar1 = var1 + var2; Heuristic 12: If slicing variable v appears in the condition expression of an if..then..else or switch..case or any other conditional statement s, then s represents a business rule involving variable v. In the example below, variable NoOfPurchases is a slicing variable. if (NoOfPurchases > 50){ totalAmount = totalAmount 0.9; } Heuristic 13: Another source of information could be comments inside the code. General policy of writing comment is to write them right before the statement with what it is related. We assume that comments about business rules, if written, exist just before the business rule. In example below, there is a comment right before the business rule. // if number of purchases exceeds 50, make a 10% discount on the total prize if (NoOfPurchases > 50){ totalAmount = totalAmount 0.9; }

PAGE 56

43 Heuristic 14: If there is a comment about the functionality of a method, general policy of writing this comment is to write it right before the method declaration. We assume that comments about method functionality, if written, exist just before the method declaration. In the example below, the comment about the method is placed right before its declaration. /** Method: void parseClassPath() parses CLASSPATH string and fills the classPart array */ public void parseClassPath() {String tempPath = classPath;

PAGE 57

CHAPTER 4 IMPLEMENTATION OF THE JAVA SEMANTIC ANALYZER As illustrated in Figure 4-1, the Schema Extractor (SE) and Semantic Analyzer (SA) are embedded inside the data reverse engineering (DRE) module of the SEEK prototype. The SE connects to the underlying DBMS to extract schema information and has been implemented by my previous colleague in SEEK [1],[2]. The schema information from the database is semantically enhanced using clues extracted by the SA. We have integrated the current Java SA code with the SE code as well, but we do not describe the integration details herein. Instead, in this chapter, we focus on the implementation details of the current Java SA prototype. Legacy application code is the input of SA, whose output consists of semantic descriptions for the legacy source schema extracted by DRE. In addition, SA elicits business rules describing some of the enterprise knowledge that is implicitly embedded in the application code. Repor Legacy DB Legacy Application Code revise,validate Schema Information Schema Extractor(SE) Embedded Queries SemanticAnalyzer(SA) Data Reverse Engineering (DRE) Figure 4-1 Architectural overview of the SA prototype and related components. 44

PAGE 58

45 The SA prototype is implemented using the Java SDK 1.4 from Sun Microsystems. The Jad v1.5.8 decompiler is used to convert class files to Java source files. Java Tree Builder (JTB) v1.2.2 and JavaCC v1.1 are used to generate Java and SQL parsers. 4.1 Package Structure The SEEK prototype code is placed in the seek package. Like other module codes in the SEEK prototype, the SA module code resides in the seek package. The code for the SA, SE, and the analysis module (AM) reside in seek.sa, seek.se, and seek.am respectively. This package structure helps us to separate the functionality of each module from one another and to encapsulate similar functionality within the same package. Java classes in the SA package are further divided into sub-packages according to their functionality. These packages are: seekstructures, seekvisitors, syntaxtree, visitor, and parsers and their content are described below: The package seekstructures contains files that were written for analyzing the Java code. The package seekvisitors contains visitor classes that were written to traverse the abstract syntax tree of Java code and SQL statements. The package syntaxtree contains classes that were created by JTB, and each class in this package corresponds to a non-terminal in the production rules of Java and SQL grammars. The package visitor contains JTB created base visitor classes. The package parsers contains Java and SQL parser files. These package structures are shown in Figures 4.2 and 4.3. The classes inside the packages syntaxtree, visitor, and parsers are automatically created by JTB and JavaCC tools and augmented to fit into seek package structure. The classes inside the packages seekstructures and seekvisitors are manually written classes to fulfill the goals of SA module. The syntaxtree, visitor, and parsers packages have 141, eight and 13 classes respectively. The classes inside these packages will remain the same as long as

PAGE 59

46 the Java and SQL grammars do not change. The seekstructures and seekvisitors packages have 25 and nine classes respectively and are subject to change as we add new functionality to SA module. Figure 4-2 Java Semantic Analyzer Packages Structure 1.

PAGE 60

47 The entire package structure is depicted in Figures 4-2 and 4-3. In Figure 4-2, some of the automatically generated classes of parsers and syntaxtree packages can be seen. Figure 4-3 shows some of the classes of seekvisitors and seekstructures that we have written. Figure 4-3 Java Semantic Analyzer Packages Structure 2. As it can be noticed in Figure 4-2 and Figure 4-3 there are other packages in the Java SA package, namely, classfiles, javafiles, dcjava, rcclasses, and xmloutput. They are

PAGE 61

48 the directories in which we keep the inputs and outputs of SA. The directory classfiles stores .class files that are being analyzed. The directory javafiles stores .java files that are being analyzed. The directory rcclasses stores recompiled classes. The directory dcjava stores .java files that were generated by decompiling classes by JAD decompiler. The directory xmloutput stores output files of Java semantic analyzer which contains abstract syntax tree of parsed classes and SQL statements. 4.2 Using the Java Tree Builder To Augment the Grammar Specification File Implementation started with the augmentation of the grammar specification file with the Java Tree Builder (JTB). As explained in the Chapter 2 and 3, to have a more robust parser, the JavaCC parser generator technology is used. To utilize the benefits of visitor patterns, JTB technology is used to add desired Java code inside the grammar specification file. When the grammar specification file is given to the JTB, a new grammar specification file with visitor patterns is produced. Details of JavaCC, JTB, and visitor patterns are described in Chapter 2. The grammar specification file (.jj file) for Java that was obtained from JavaCC repository [6] is given as an input to JTB 1.2.2. The outcomes are the Java files in the syntaxtree and visitor directories and also the new grammar specification file, jtb.out.jj. Figure 4-4 illustrates the input and outputs of the JTB tool. JTB produces the Java classes in the syntaxtree directory according to production rules in the grammar. Each Java class also has an accept method to be used by visitors. Visitor Java classes that are created in the visitor directory have a method that corresponds to each of the Java classes inside syntaxtree package. Each of the Java classes are modified to put them into appropriate seek packages, syntaxtree classes into the seek.sa.syntaxtree, and visitor classes into seek.sa.visitor packages. This is done by adding Package seek.sa.syntaxtree; line at the

PAGE 62

49 beginning of the all Java class files in the syntaxtree directory and Package seek.sa.visitor; line at the beginning of all Java class files in the visitor directory. EBNF grammar Syntax Tree Node Classes(in syntaxtree package) Default Visitors and Interfaces(in visitor package) EBNF Grammar with Embedded Java Code (jtb.out.jj file) JTB Tool Figure 4-4 Input and outputs of the JTB tool. 4.3 Generate Parser by JavaCC The output of the JTB tool, the grammar specification file, is input to JavaCC. JavaCC generates the parser files that will accept grammar according to the input specification file. The parser files are listed in Table 4-1. Table 4-1 JavaCC generated parser files. ParserName.java Has main method, methods for each non-terminals, debug(trace) methods, getNetToken method. ParserNameConstants.java Interface for tokens ParserNameTokenManager.java Manages the token source file ParseException.java Exceptions SimpleCharStream.java ParserNameTokenManager uses Token.java Describes the input token stream TokenMgrError.java Returns a detailed message for the Error when it is thrown by the token manager to indicate a lexical error. For the SA component of the SEEK prototype, two parsers are created, namely a Java and an SQL parsers. Both parsers use the same SimpleCharStream, Token, TokenMsgError, and ParseException classes and they have their own ParserName, ParserNameConstants, and ParserNameTokenManager classes. These parser files are placed in the parsers directory for a better package organization. To put them in the

PAGE 63

50 proper package structure, the Package seek.sa.parsers line is placed at the beginning of each file. 4.4 Execution Steps of Java Semantic Analyzer The driver class for the semantic analyzer is the SADriver class. The SADriver accepts the name of the source code file as an argument. The analyzing process starts with this source code file. The SADriver invokes the recursive processFile method of the ProcessFile class with its initial parameters. The parameters of the processFile method are class name, method name, and arguments of method. Initially, parameters of the processFile are source file name as class name, main as a method name, and String[] as the argument of the main method. It is assumed that the class name parameter that is given to the SADriver is the name of the stand-alone Java class, which has the main method. Starting from this stand-alone file, all user-defined classes on the control flow graph are traversed during the analyzing process. As it is illustrated in Figure 4-5, the SADriver.java takes Class Name as a parameter and invokes the ProcessFile method on ProcessFile class with the parameters Class Name, Method Name (main), and Arguments (String[]).The ProcessFile method executes two main steps: Step 1: The ProcessFile method makes preparations necessary for analyzing the source code. Starting from Class Name and main method of that class, ProcessFile.java finds the files that are going to be analyzed with the help of the FindClass.java. Then, it copies them into proper directories and extracts the control flow graph by traversing the source code classes. Step 2: The ProcessFile.java starts analyzing the methods in the control flow graph. These two steps are shown in bold face in the ProcessFile.java box of Figure 4-5 and are described in the following sections.

PAGE 64

51 Class Name SADriver.java ProcessFile.java 1. Make Preparations to analyze 2. Analyze Report Analysis Class NameMethod Name Arguments FindClass.java *Get Class Path Info *Search Class Path for Class File Name Class File Name Class File Location Initialization of Java Semantic Analyzer Figure 4-5 Initialization of the Java Semantic Analyzer. 4.4.1 Making Preparations to Analyze There are two main steps in the process of analyzing the Java code. Details of an iteration of the first step Make Preparations for Analyzing is explained in this section. ProcessFile.java PrepareForProcess method 1. Copy Class File 2. Decompile Class 3. Parse Java File 4. Write AST in XML 5. Write Symbol Table 6. Get Package Import Info of Class and feedback this info to FindClass.java 7. Search and set locations of user-defined classes in Symbol Table. 8. Get next user-defined class name and its location to prepare for analyzing Class NameLocation CopyMoveFile.java Copy: Class is copied from Location into classes directory Location DRCompile.java Decompile: Uses JAD decompiler to convert .class files to .java files and puts them into dcjava directory. Recompile: Compiles class file in dcjava directory and stores it into rcclasses directory Compare: Compares the file lengths of .class file in classfiles directory with rcclasses directory and outputs results. FindClass.java Search: Search and specify class location in class path in directories and in jar files. JavaParser.java Parses the input java file and outputs abstract syntax tree of it. File Name Root Node of AST ObjectXMLWriter.java Visitor Class that writes AST into XML file in xmloutput ObjectSymbolTable.java Visitor Class that writes variable declarations into Symbol Table A S T Symbol Table ObjectPackageImport.java Visitor Class that get package and import declarations from AST Next Class Name And Location A S T p acka g e, im p ort in f o File Name Class From Symbol Table L ocation Figure 4-6 Eight steps that make up prepareForProcess method.

PAGE 65

52 Figure 4-6 shows the eight steps that make up prepareForProcess method of the ProcessFile class and its interaction with other classes: Step1: If the method gets .class as the value of the parameter extension, it copies the file from its location into the classfiles directory. If the method gets .java as the value of parameter extension, then it copies the file into the javafiles directory. Step 2: If .class is the value of the parameter extension, it decompiles this .class file by JAD decompiler to get the corresponding source code. This .java file can then be recompiled by javac to compare the sizes of found the .class file and recompiled the .class file. The rationale behind this process was explained in the decompiler section of Chapter 3. Step 3: The .java file in the dcjava directory or in the javafiles directory is parsed by the Java parser. Step 4: The outcome root node of the Java abstract syntax tree is then passed to the XML Writer visitor class to write the AST in XML format into a file. Step 5: After that, variable information (name, scope, type, etc.) is extracted from AST by ObjectSymbolTable visitor class. Step 6: Package and import information is also extracted by ObjectPackageImport visitor class to be given to the FindClass class to be used for next user-defined class finding process. Step 7: The SearchVariableClass class is used to identify the locations of user defined classes in the symbol table. This location information is entered in the symbol table. Step 8: After all user defined classes are searched in the class path and in the imported packages, it gets the next user defined class name and location from symbol table to prepare it to be analyzed. By these class name and location parameters prepareForProcess method is called recursively. The process of preparing classes continues until all eight steps are applied to all classes in the control flow graph. Visitor patterns are used during the fourth, fifth, and sixth steps. Details of these steps will be given in Section 4.5. 4.4.2 Analyze Source Code Following initialization, the SA analyzes the methods. Figure 4-7 shows what is being done in an iteration of the recursive analyzeMethods method of ProcessFile class.

PAGE 66

53 ProcessFile.java 1. Identify Slicing Variables according to input-output-SQL statements. 2. Get business rules that have slicing variables. 3. Get comments of business rule and methods 4. Get Called Methods from this method 5. Get SQL Statements and parse them by OracleParser class. 6. Get table, column information from this parsed SQL node by giving it to ObjectOracleParser visitor class 7. Make relations between variable semantics and columns of tables. Get the next method and its arguments to analyze. M ethod NameAnd Arguments OracleParser.java Parses the input java file and outputs abstract syntax tree of it. Root Node of SQL AST ObjectSlicingVars.java Visitor Class that identifies slicing variables. ObjectBusinesRules-Comment.java Visitor Class that finds business rules for slicing variables. Next Method Name And Arguments AST, S y mbolTable SymbolTable updated by slicing variables AST, S y mbolTable SymbolTable updated by business rules ObjectCalledMethods.java Visitor Class that finds called methods in user-defined classes. AST, S y mbolTable SymbolTable updated by business rules ObjectSQLStatements.java Visitor Class that constructs SQL methods from variables and parses them by Oracle Parser and gets table and column information and relates them to variables. AST, S y mbolTable SymbolTable updated by variable-column relations S Q L Strin g ObjectSQLParser.java Visitor Class that finds called methods in user-defined classes. table and column information Figure 4-7 Seven steps that make up analyzeMethods method. As it is shown in Figure 4-7, the analyzing source code has seven steps, which are: Step 1: Identify slicing variables by ObjectSlicingVars visitor pattern. Step 2: Extract the business rules statements that these slicing variables are used in by ObjectBusinessRuleComment visitor pattern. Step 3: Extract the comments 1 of the business rules and methods by ObjectBusinessRuleComment visitor pattern. Step 4: Extract method calls on user-defined classes and forms a link list for the called methods by ObjectCalledMethod visitor pattern. Step 5: Constructs the SQL strings by ObjectSQLStatement visitor pattern and parses them. Step 6: The AST of the SQL string is then sent to ObjectParseSQL visitor class to get table, column information. Step 7: This information is used by ObjectSQLStatement visitor pattern to make relations between slicing variables and column names. 1 We can extract comments only if we are processing .java files. When we process .class files, we do not have access to comments since they can not be reproduced by de-compilation step.

PAGE 67

54 After the seventh step is executed, the analyzeMethods method gets the next called method name and arguments, and calls itself with this method name and its arguments recursively. Figure 4-7 also shows the interaction of analyzeMethods method with the classes it uses. The details of the visitor patterns that are used in this process are provided in the following section. Note that, we first process the class files as a whole in the preparation step. Then, we only analyze the methods that are used by method calls. As it was stated in Chapter 3, this approach save effort and improve performance. We do not analyze methods that will never be called. 4.5 Functionality of Visitor Classes In this section, we define the functionality of the visitor classes. Visitor classes help to extent the functionality of our code easily. If we need a further functionality, all we need to is to write a new visitor class that covers this functionality. Visitor classes also help to organize the related functionality in the same visitor class. Visitor classes can be written by extending a default visitor class and by overriding methods of this default visitor class. The default visitor class is ObjectDepthFirst class, which implements visitor interface ObjectVisitor. When a method is not overwritten, it uses the method of the extended class, ObjectDepthFirst. Methods of the default visitor only help navigate between methods. Next, we explain the functionality of the visitor classes that is used in our project. 4.5.1 Output Abstract Syntax Tree to XML File ObjectXMLWriter is the visitor class that is used to output Abstract Syntax Tree (AST) of a Java file into an XML file. Node names of the AST form tag names of the

PAGE 68

55 XML file. All XML files are written into xmloutput directory. ObjectXMLWriter visitor is used to write the AST of SQL statements as well. 4.5.2 Get Variable and Method Declaration Information ObjectSymbolTable is the visitor class that is used to gather variable declaration information. It constructs the main file-class-method organization structure that will be used in follow-on steps of the analyzing process. This structure is shown in Figure 4-8. Parsed File 1 Parsed File 2 Parsed File 3 Class 1.1 Class 2.1 Class 2.2 Method 1.1.1 Method 1.1.2 Method 2.1.3 Method 2.2.1 Method 2.2.2 Class 3.1 Figure 4-8 Link List Structure of Traversed Method Tree of SA. In Figure 4-8, Parsed File1 is the file of the first class that was given as a parameter to SA. In general, Java files can contain more than one class definition. The Parsed File 2 shown in Figure 4-8, is an example of this type of file. It has classes Class 2.1 and Class 2.2. The ObjectSymbolTable visitor stores variable declarations in a symbol table. Locations of variables in the symbol table are specified with the help of a hash table. Method and constructor declarations are also stored in the symbol table. The formal parameter list of the method and constructors are attached to them with a nextProcElement pointer. When a method declaration is inserted into the symbol table, its scope and stack information is also saved. Scope and stack information are important when we analyze two or more different methods of a class that have variables with the

PAGE 69

56 same names. After we gather the meaning of a variable and save it into the symbol table, we must not override that meaning with the meaning of a variable that has the same name but declared in another method. Keeping scope and stack information class-wise helps us to distinguish it from other variables with the same name but in different scopes. Scope is changed by opening a new scope and closing the existing one at the beginning and end of the visitor methods. According to Java grammar, scope is changed inside the visitor method of the following AST nodes: Class Declaration, Method Declaration, Constructor Declaration, and Statement. ObjectSymbolTable visitor stores a SymbolTableElement class into symbol table that holds information for each variable and method. The information in this class is then enriched by other visitors. Table 4-2 outlines the information that is stored in SymbolTableElement. SymbolTable and SymbolTableElement are the most important class in the SA. SymbolTable class is passed to each visitor pattern that aims to extract information from code. The information held in SymbolTableElement is enhanced by each visitor pattern. 4.5.3 Get Slicing Information ObjectSlicingVars is the visitor class that is used to identify slicing variables. These are important variables in the process of semantic extraction. As previously defined in Section 3.6, slicing variables are used in input, output, and SQL statements. They are also passed to a method as a parameter. When we encounter a variable as an argument to an input, output, SQL, or user-defined method, we set the appropriate flag in the

PAGE 70

57 SymbolTableElement structure to indicate that the meaning of this variable should be investigated further. Table 4-2 Information stored for variable/method declaration in SymbolTableElement. Info Name Definition Name Name of the variable Scope Scope of the variable DeclarationNo declaration sequence number in the class InputSlicing is set true if the variable is used in an input statement OutputSlicing is set true if the variable is used in an output statement SQLSlicing is set true if the variable is used in an SQL execute statement MethodSlicing is set true if the variable is passed as a parameter to a method ResultsetSlicing is set true if the variable is used in a resultset get method UserDefinedClass is set true if type of the variable is a user defined class ClassLocation Location of the user defined class. Class is the type of the variable Category If it is variable declaration, value of category is variable, otherwise it is method or constructor depending on the declaration. Type Class of the variable Value Used to store string value of string slicing variables NextElement If there is more than one declaration with the same name but different scope, new variable is added to the end of SymbolTableElement list. NextProcDec Pointer to the list of formal parameters of the method RelatedElement If there is an assignment statement between two variables, they are related with this pointer ColumnElement if there is an assignment from resultset get method to this variable, points to the corresponding columnElement in the resultset get method StackPosition stores the stack scope info when an element of category method is defined 4.5.4 Get Business Rules and Comments ObjectBusinessRuleComment is the visitor class that extracts a list business rules and comments related to this business rules. The visitor class searches business rules inside assignment, if, and switch statements. Such a statement is interpreted as a business rule if it contains a slicing variable. The Table 4-3 provides information that is stored in the BusinessRules class.

PAGE 71

58 Slicing variables that exist in this business rule are saved in RelatedElement field of business rule structure. This visitor also saves the comments in the BusinessRule class that occur just before the potential business rules in the code. The pointer to the root of the node of the business rule in the AST is also saved. This node can be used in outputting this business rule in a desired format. Table 4-3 Information stored in BusinessRule class. Info Name Definition Type Type of the business rule, like Statement, Assignment Text Text of business rule Comment Comment that were placed right before the business rule text ClassName Class name in which business rule is MethodName Method Name in which business rule is RelatedElement The pointer to the list of variables that exists inside this business rule Node The pointer to the root of the node of the business rule in the AST Next Next business rule One business rule can reside inside another. In such a case, the business rule is inherited inside another. If the business rule is inherited by another business rule, we concatenate the current business rule (the one that is inherited) with the previous business rule (the one that inherits) and also add the slicing variables of the current rule to the previous rule. This scenario is depicted in Figure 4-9. business rule 1 inherits business rule 2. var1,var2, var3, var4, var5, and var6 are slicing variables of business rule 1, while var4, var5, and var6 are the slicing var business rule 2. iables of If (var1.equals(yes)) { var2 = var3 + 8; If (var4.equals(no)) { var5 = var6 + 7; } var3 = 0; }# }Business Rule 2 }Business Rule 1 Figure 4-9 Example of a business rule that inherits another business rule.

PAGE 72

59 The elicitation of business rules is achieved using stacks. When we encounter a potential business rule statement (if, assignment, or switch statement), we begin to store the tokens of the code in a stack. Meanwhile, if we encounter a slicing variable, we also store the slicing variable in a stack. When a new business rule is encountered before the end of the one currently under investigation, a new business rule is pushed onto the stack. Figure 4-10 illustrates the contents of the stack at the point when * in Figure 4-9 is reached. BR2 in Figure 4-10 contains the If (var4.equals(no)) {var5 = var6 + 7;} string, and BR1 in Figure 4-10 contains the If (var1.equals(yes)){var2 = var3 + 8; string. When the latter business rule has been processed, the text and slicing variables for it are added to the previous one. The content of the stacks at the point when # in Figure 4-9 is reached are shown in Figure 4-11. It can be readily seen that, the content of the VS2 stack is transferred to VS1 and the text of BR1 and BR2 are also merged. The BRText contains the If (var1.equals(yes)){var2 = var3 + 8; If (var4.equals(no)) {var5 = var6 + 7;} var3 =0; string. BR1 BR2 VS1 VS2 Var1 Var2 Var3 VS1 Stack of Variable Stacks Stack of Business Rules Stack of Variables Var4 Var5 Var6 VS2 Stack of Variables Figure 4-10 The content of the stacks at point when * in Figure 4-9 is reached.

PAGE 73

60 BRText VS1 Var1 Var2 Var3 Stack of Variable Stacks Stack of Business Rules Var4 Var5 Var6 VS1 Stack of Variables Figure 4-11 The content of the stacks at point when # in Figure 4-9 is reached Another functionality of ObjectBusinessRuleComment visitor class is that it saves comments that are written just before the method declarations in the code. These comments are saved and then passed to the method that is being analyzed. 4.5.6 Get Method Calls The visitor class ObjectCalledMethods gets the list of method calls inside a method. These methods are the ones that are invoked on user defined classes. When the visitor ObjectCalledMethods encounters a method, it adds the method to the list with its method name, class name, and argument list. The argument list is formed from the actual parameters of the method call. An argument element class that stores the properties of an argument has name, type, and value fields. Figure 4-12 outlines the structure of the method call and argument list that are gathered by ObjectCalledMethods visitor. Parsed Metho d Calle d Metho d 1 Calle d Method2 Calle d Method3 Ar g ument 1 Ar g ument2 Ar g ument 1 } Method Lis t } Argument List Figure 4-12 List of Method Calls Structure.

PAGE 74

61 4.5.7 Get Package-Import-Extend Info The ObjectPackageImport is the visitor class that is used to obtain package, imported classes, and extended class information of a Java file. This information is then used in finding the user-defined classes in the class path using the file finder class FindClass. 4.5.8 Get SQL Statements The ObjectSQLStatement is the visitor class that is used to extract SQL statements and parse them. This is one of the core visitors of the SA. While the visitor traverses the AST, it constructs the value of string variables. When a variable of type string or a string text is passed as a parameter to an SQL execute method (e.g., executeQuery(queryStr)), it parses the string with SQL parser. The SQL parser returns the AST of this SQL string. The ObjectSQLStatement visitor then uses the ObjectSQLParse visitor to get information about that SQL statement. The details of the ObjectSQLParse visitor are discussed in the next section. If the value of a variable is compared with a column in the where clause of an SQL statement, it saves information about the relation between the variable and the column. While the visitor traverses AST, if it encounters a SQL retrieve method (like getString(column name)) on a Resultset type of variable instance, it gets the related column info and relate it to variable name. If ObjectSQLStatement encounters an output method, it evaluates the string by relating possible meaning with the variable names. It relates the variables with the text in the most recent output statement. 4.5.9 Parse SQL Strings The ObjectSQLParse is the visitor class that is used to parse SQL strings and store the information about the SQL string into a ResultsetSQL class structure. Table 4-4 lists the members of the ResultsetSQL class.

PAGE 75

62 Table 4-4 Information stored in ResultsetSQL structure Info Name Definition Name Class Name + Method Name + Declaration No Type Type can be 'update', 'select', 'insert' or 'delete' String SQL string Node Root node of the AST of the SQL string Columns Pointer to column list Tables Pointer to table list The AST of an SQL select statement is given to the ObjectSQLParse visitor with an initially empty ResultsetSQL class instance. The ObjectSQLParse visitor traverses the AST of the SQL statement and extracts table, and column names. In addition, the ObjectSQLParse fills the ResultsetSQL class with the column and table information. As one can see in Figure 4-13, when a SQL statement is forwarded to ObjectSQLParse visitor, a list of column and table information is attached to the ResultsetSQL instance. The ObjectSQLParse can extract table and column information of Uptade, Insert, and Delete statements as well. ResultsetSQL String = Select A.activ_no, P.proj_name From Activity A, Project P Where A. proj_no = B. proj_no Column Element Name = proj_name No = 2 TableName = Project Column Element Name = activ_no No = 1 TableName = Activity Table Element Name = Activity No = 1 Table Element Name = Project No = 2 Figure 4-13 Example of a ResultsetSQL class.

PAGE 76

CHAPTER 5 EVALUATION OF SEMANTIC ANALYZER Several criteria can be used to evaluate our semantic analyzer. The main criteria include correctness and performance. In this chapter, we introduce our prototype test system to demonstrate how SA captures the semantics from source code correctly and within a reasonable amount of time. In Section 5.1, we show the correctness of key features of SA by using code fragments. In Section 5.2, we show the semantics extracted from an application from Construction Scheduling and discuss the correctness of these semantics. In Section 5.3, we show the performance improvement in time when compared to previous version of SA and explain how we achieved this. 5.1 Can Features of Semantic Analyzer Extract Semantics Correctly? In this section, we use code fragments to demonstrate how key features of SA can correctly extract meaning. In each subsection, we introduce a code fragment and show what SA can extract from that code fragment. Then, we explain why this extracted meaning is correct. 5.1.1 Targeting a Specific Column from the Query In this subsection, we show that SA can target a specific column from the result set of a query. The correctness of this feature is important to satisfy the eighth heuristic that is introduced in Section 3.7. When a SQL select query string is given as a parameter to executeQuery method of a Statement object instance, the tuples satisfying the selection criteria of the query are returned in a ResultSet object. The Java Database Connectivity (JDBC) Application 63

PAGE 77

64 Program Interface (API) provides several methods for ResultSet object to obtain individual column values from a tuple in the ResultSet. The parameter of a ResultSet get method can be one of the following: 1. A string: Column name from the SELECT query column list 2. An integer: Between zero and the number of columns in the query minus one. SA can accurately handle these two types of parameters of the ResultSet get methods and can specify the corresponding column name in the column list of the SQL query statement. SA stores the ResultSet information inside an instance of ResultSetSQL class. Examples of these two parameters are given in Table 5-1. Table 5-1 Examples of ResultSet get method parameters. ResultSet get method parameter as an integer: ResultSet resultSet = sqlStatement.executeQuery("SELECT p_id FROM Project"); String projNumber = resultSet.getString(1); ResultSet get method parameter as a String: resultSet = sqlStatement.executeQuery("SELECT p_id FROM Project"); String projNumber = resultSet.getString(p_id); As shown in Figure 5-1, the column list and table list are extracted from the SQL query string and a list of ColumnElement and TableElement are formed and attached to the ResultSetSQL class instance. ResultSetSQL is formed by ObjectSQLParse visitor and is introduced in Section 4.5.9. When the get method parameter is an integer, we find the (integer parameter +1)th element in the ColumnElement list. When the get method parameter is a String, we find the column by comparing the name of the parameter with the name of the elements in the ColumnElement list.

PAGE 78

65 ResultsetSQL String = Select A.activ_no, P.proj_name From Activity A, Project P Where A. proj_no = B. proj_no Column Element Name = proj_name No = 2 TableName = Project Column Element Name = activ_no No = 1 TableName = Activity Table Element Name = Activity No = 1 Table Element Name = Project No = 2 Figure 5-1 Example of a ResultsetSQL class and ColumnElement and TableElement lists. After representing the code examples in Table 5-1 in a ResultSetSQL class form as shown in Figure 5-1, SA can correctly target the specific column as explained in the previous paragraph. Correctly targeting a specific column feature is important to relate the correct column of a table with the correct output statement which will give the meaning of the column. 5.1.2 Extracting the Column Name from Mathematical Expression In this subsection, we show that SA can extract the name of the column even if it is embedded in a complex mathematical expression. The correctness of this feature is also important to satisfy the eighth heuristic that is introduced in Section 3.7. Table 5-2 Example of a SQL query that has mathematical expression in its column list. resultSet = sqlStatement.executeQuery("SELECT (activ_planned_finishdate+1) FROM Activity WHERE activ_no = 5); java.sql.Date startDateSQL = resultSet.getDate(1); Figure 5-2 gives the ResultSetSQL class representation of the query in Table 5-2. As shown in Figure 5-2, ColumnElements name field has the correct column name. As it was stated before, ResultSetSQL is formed by ObjectSQLParse visitor. ObjectSQLParse traverses the AST of SQL expression and accurately extracts the column name.

PAGE 79

66 ResultsetSQL String = SELECT (activ_planned_finishdate + 1) FROM Activity WHERE activ_no = 5 Column Element Name = activ_planned_finishdate Text = (activ_planned_finishdate + 1) No = 1 TableName = Activity Table Element Name = Activity No = 1 Figure 5-2 ResultSetSQL class representation of the query in Table5.2. Even we find a meaning related with the mathematical expression, if SA could not identify the column name from a mathematical expression, then SA would fail to relate meaning with the correct column name. If SA could not identify the column name from a mathematical expression, SA would not find a matching entry to fill with the meaning in the schema of data source that was extracted by SE. 5.1.3 Geting Query Expression from the Variable Value In this subsection, we show that SA can correctly save and retrieve the value of a string variable. The parameter given to the SQL execute method (e.g., executeQuery) can be a string type of variable as well. The string variable can hold an SQL query. The value of the variable must be correctly saved and retrieved when it is used in an SQL execute method. Table 5-3 Example of using variable in the executeQuery method. String queryString = SELECT p_id FROM Project; ResultSet resultSet = sqlStatement.executeQuery(queryString); String projNumber = resultSet.getString(1); An example of using a variable as a parameter of SQL execute method is given in Table 5-3. Note that, there can be several numbers of statements between the value assignment of variable and the SQL execute method.

PAGE 80

67 5.1.4 Concatenating Strings to Get the Query Expression In this subsection, we show that SA can correctly recognize the meaning of concatenating operator (+) and concatenate strings to get the query expression. Table 5-4 is an example of this. When query1 and query2 in Table 5-4 are declared, their initial values are stored in the value field of their SymbolTableElement in the SymbolTable. When they are used in a string expression with the concatenating operator, their values are obtained from SymbolTable and are used to form the new string. Table 5-4 Example of Concatenating String to Get the Query Expression. String query1 = "SELECT active_duration, activ_planned_startdate ; String query2 = FROM Activity + WHERE Activ_no = '5' "; String query = query1 + query2 + ResultSet resultSet = sqlStatement.executeQuery(query); Figure 5-3 illustrates how variable values in Table 5-4 are stored in SymbolTable. The value of the element query2 is formed by concatenating the strings "FROM Activity, and WHERE Activ_no = '5' ". The value of the element query is formed by concatenating the value of string variables query1 and query2. . query1 query2 query . SymbolTable S y mbolTableElementName : query1 Value : "SELECT activ_duration, activ_planned_startdate S y mbolTableElementName : query2 Value : FROM Activity WHERE Activ_no = '5' S y mbolTableElementName : query Value : "SELECT activ_duration, activ_planned_startdate FROM Activity WHERE Activ_no = '5' Figure 5-3 Illustration of String SymbolTableElements and their values.

PAGE 81

68 SA can correctly form the string expression by concatenating any number of string variables and expressions. These variables and expressions can form an SQL expression or an input/output statement that inherits meaning. Correctly forming and evaluating the SQL expression and input/output statement is important to get the most benefit from the application code. 5.1.5 Geting the Meaning of Slicing Variable from the Output Text SA can accurately relate output statements with slicing variables. The slicing variable concept is introduced in Section 3.6. SA gets the meaning of the slicing variables from the most recent output text. To achieve this, SA pushes the output text in a stack and when a slicing variable is encountered, it pops the text from the stack and relates it with that slicing variable. Table 5-4 Making relations between output statements and columns. String query = "SELECT activ_duration,active_planned_startdate FROM Activity WHERE activ_no = '"+ inputActivity + "'"; resultSet = sqlStatement.executeQuery(query); duration = resultSet.getInt(1); oldStartDate = resultSet.getString(2); System.out.println("activity no: + inputActivity); System.out.println("old start date: + oldStartDate); System.out.println("duration: + duration); In the example in Table 5-4, the meaning of the inputActivity, oldStartdate, and duration slicing variables are obtained from the most recent output text and these meanings are then related to activ_no, activ_duration, and active_planned_startdate variables. Note that inputActivity variable is used in the where clause of the query. SA also keeps track of the variables that are used in where clauses because they have potentially important information about the semantic of their correspondence columns in the where clause.

PAGE 82

69 Correctly finding the meaning of the slicing variable is important because after finding the meaning of the slicing variable, we assign this meaning to the column of a table that was already related with that variable. Correctly realizing this feature means that we can correctly realize the eighth heuristic in Section 3.7. 5.1.6 Passing Semantics from one Method to Another One of the most powerful features of SA is passing argument values and meanings from one method to another. SA conquers the meaning found in the current method with the meanings found before the current method was called. SA transfers semantics from one method to another by this feature causing it to get more accurate results. When a method is called, the values of parameters are passed from the point where the call is made to the called method. The execution continues from the called method. In the example given in Table 5-5, the SQL query information is passed to the outputProjectResultset method in the resultSet variable. Although the SQL query is in the initializeQuery method and the output statement is in the outputProjectResultset method, SA can accurately keep track of the parameters that are passed between methods and can relate Project Num: output statement with p_id column of table Project. If SA could not correctly transfer the semantics from one method to another through arguments, then SA would not be able to capture the semantics of p_id column of table Project and this semantics would have been lost. 5.1.7 Extracting the Meaning from the Title Output Slicing variables may not have output statements that identify their meaning. Instead, they may have a title output statement as shown in Table 5-6. In this case, SA shows the title to the user as a possible meaning. The title inherits semantics for the following outputs of columns. In the example given in Table 5-6, projectNo,

PAGE 83

70 workItemNo, and currentactivity variables and their corresponding columns have "proj_no workitemno activityno" output statement as a possible meaning. Note that, texts like "-------------------" and "\t" are used for formatting. They are eliminated and are not shown as a possible meaning. Correctly identifying the title of the outputs of columns and presenting this title to user helps us to get more semantic information from the application code. Table 5-5 An example of passing parameter values. Public static void initializeQuery (Statement sqlStatement,ResultSet resultSet) { String query = "SELECT p_id FROM Project"; resultSet = sqlStatement.executeQuery(query); outputProjectResultset(sqlStatement,resultSet); } public static void outputProjectResultset (Statement sqlStatement,ResultSet resultSet) { System.out.println("The following are all the projects found:"); while(resultSet.next()) { String projNumber = resultSet.getString(1); System.out.println("Project Num:" + projNumber); } resultSet.close(); } Table 5-6 Extracting the meaning from the title. query = SELECT Activ_no, Workitem_no, Proj_no FROM Activity"; resultSet = sqlStatement.executeQuery(query); System.out.println("proj_no workitemno activityno "); System.out.println("--------------------------------------"); while(resultSet.next()){ projectNo = resultSet.getString(3); System.out.println(projectNo); workItemNo = resultSet.getString(2); System.out.print("\t" + workItemNo); currentactivity = resultSet.getString(1); System.out.print("\t" + currentactivity); }

PAGE 84

71 The correctness of the above key features of SA is important to accomplish the goal of SA. SA correctly extracts meaning from code as introduced in the above examples and extracts the highest amount of semantics that is available in the source code. 5.2 Correctness Evaluation In this section, we show how SA accurately extracts the application specific meaning from source code. To show this, we use an application from Construction Scheduling. This program does a very simple re-scheduling of an activity of a construction firm. The source code can be found in Appendix G. Table 5-7 shows the list of meanings of the columns that are extracted from the Construction Scheduling Program source code. Now, we explain how SA correctly satisfies our heuristics and extracts the meanings listed in Table 5-7. The reader can notice that some of the columns have only one meaning and some of the columns have several meanings in Table 5-7. If all the output texts are the same or there is only one output text for a column of a table, then there is only one meaning assigned to that column. In this case, the column meaning has no ambiguity. In Table 5-7, the meaning of p_id column of table Project and the meaning of active_duration column of table Activity are found without any ambiguity. If more than one output statements can be associated with a column, then there is ambiguity. Activ_no, activ_planned_finishdate, and activ_planned_startdate columns of table Activity have several meanings assigned to them. For this reason, there is ambiguity in the meaning of these columns. When there is ambiguity, the list of meanings is presented to the user and an input to resolve the ambiguity is expected. The frequency of some words can give clues about the meaning of the column. For instance, the word activity has the highest frequency in the list of meanings for activity_no column of Activity table. Even if the column name

PAGE 85

72 was irrelevant, instead of Activity_no, the frequency of word activity could be a good clue to identify its meaning. Table 5-7 Extracted Meanings of the Columns from the Construction Scheduling Program Source Code. Column & Table Name: Extracted Meanings: Column Name: Activ_no Table Name: Activity Ambiguity: true 1) projno workitemno activityno startdate finishdate 2) Activity is being rescheduled to the earliest date possible 3) activity no 4) You have entered days to shift the activity 5) Activity 6) Sorry there is no slot to shift the activity 7) You can not choose the same activity 8) Sorry there is no enough slot to place the activity 9) Sorry there is no enough slot to place the activity after the activity Column Name: p_id Table Name: Project Ambiguity: false 1) Project Num Column Name: Proj_no Table Name: Activity Ambiguity: true 1) projno workitemno activityno startdate finishdate Column Name: Workitem_no Table Name: Activity Ambiguity: true 2) projno workitemno activityno startdate finishdate Column Name: activ_planned_finishdate Table Name: Activity Ambiguity: true 1) projno workitemno activityno startdate finishdate 2) The new finish date is 3) The new start date is 4) The new start date is Column Name: activ_planned_startdate Table Name: Activity Ambiguity: true 1) projno workitemno activityno startdate finishdate 2) old start date 3) You can shift this activity at most 4) oldstartdate Column Name: activ_duration Table Name: Activity Ambiguity: false 1) duration Another form of ambiguity can be seen when a meaning statement is used for more than one column. For instance, Project_no and WorkItem_No columns of table Activity have this kind of ambiguity. The code fragment that causes this kind of ambiguity is

PAGE 86

73 shown in Table 5-8. In the code fragment in Table 5-8, a title is given for the preceding outputs. SA eliminates the format outputs such as --------- and \t and assigns the title meaning "proj_no workitemno activityno startdate finishdate" to Activ_no, activ_planned_startdate, activ_planned_finishdate, Workitem_no, and Proj_no of table Activity. Table 5-8 Extracting the meaning from title of the outputs. query = "SELECT Activ_no, activ_planned_startdate, activ_planned_finishdate, Workitem_no, Proj_no FROM Activity ORDER BY activ_planned_startdate"; resultSet = sqlStatement.executeQuery(query); System.out.println("proj_no workitemno activityno startdate finishdate "); System.out.println("---------------------------------------------------"); while(resultSet.next()) { currentactivity = resultSet.getString(1); workItemNo = resultSet.getString(4); projectNo = resultSet.getString(5); System.out.print(projectNo); System.out.print("\t" + workItemNo); System.out.print("\t" + currentactivity); } resultSet.close(); The Construction Scheduling Program is also a good example of how SA extracts semantics from applications that have functionality separated into multiple files. The functionality of the scheduling program is separated into three files: ScheduleMenu.java, ScheduleList.java and ManipulateActivity.java. The analyzing process starts from the main method of ScheduleMenu.java file and dispatches to the methods in ScheduleList.java, and ManipulateActivity.java files as it encounters a method call on these classes. Table 5-9 shows a method call that is made on an instance of ScheduleList class from the main method of ScheduleMenu.java class. After SA completes analyzing

PAGE 87

74 initiliazeProjectQuery method, it continues to analyze the main method of ScheduleMenu from the next statement, if (menuOption.equals("2")) statement. Table 5-9 Code fragment inside the main method of ScheduleMenu.java If (menuOption.equals(")){ scheduleList.initiliazeProjectQuery(sqlStatement,resultSet); } if (menuOption.equals("2")){ scheduleList.listActivities(sqlStatement,resultSet);} The Construction Scheduling Program source code also verifies that SA can extract and integrate semantic from different methods. SA can transfer the semantic of a variable to a new method when it is used as an argument inside the method call. An example of this case is given in Table 5-10. In this example, the SQL query semantic is held inside the variable resultSet. When listProjects(sqlStatement,resultSet) method call is done inside the initiliazeProjectQuery method, the semantic gathered for resultSet variable is transferred to the variable resultSetProject in the listProjects method. If SA does not have this feature, it can not relate the output statement "Project Num:" to the p_id column of Project table. Table 5-10 Code fragment from ScheduleList.java shows how variable semantic is transferred from one method to another. Public static void initiliazeProjectQuery(Statement sqlStatement,ResultSet resultSet){ String query = "SELECT p_id FROM Project"; resultSet = sqlStatement.executeQuery(query); listProjects(sqlStatement,resultSet);} public static void listProjects(Statement sqlStatement,ResultSet resultSetProject) { System.out.println("The following are all the projects found:"); while(resultSetProject.next()){ String projNumber = resultSetProject.getString(1); System.out.println("Project Num:" + projNumber); } resultSetProject.close(); }

PAGE 88

75 According to our experiments with Construction Scheduling Program source code, SA can correctly satisfy the heuristics that was introduced in Section 3.7 and can correctly extract all the meanings in the user interaction statements that can be related with a column of a table. Analyzing Construction Scheduling Program source code has been a good example that validates all the features of the new SA. We have also tested SA with numerous of small code fragments to evaluate the correctness of each of the SA feature. It would be beneficial to test the new SA with several more number of large code samples that can be used to validate all the futures of the new SA in one application. 5.3 Performance Evaluation SA is a built-time component of SEEK. Although performance is not as critical as correctness, it is important to state that the performance of our new version has significantly improved when compared to the first version [2]. This is because the current version of SA introduces significantly different algorithms to extract information from source code. The current and previous versions of SA are tested on an Intel Pentium-IV PC with a 1.4 GHz processor, 256 MB of main memory, and 512KB cache memory running Windows NT. Previous version of SA executes four main steps which were explained in [2]. Step 3 and 4 are applied for each of the slicing variables. Table 5-11 gives time spent in seconds for each of these steps and for each slicing variables in step three four while analyzing Construction Scheduling program. Step 1: AST Generator: Constructs the AST for the source code Step 2: Pre-slicer: Identifies slicing variables Step 3: Code-slicer: Performs slicing and constructs a reduced AST Step 4: Analyzer: Traverses reduced AST to extract semantic information

PAGE 89

76 Table 5-11 Time spent (in seconds) in sub steps of previous version of SA. Step No Time Spent in Seconds Step 1 1 Step 2 472 Slicing Variable Name Time in seconds Step 3 & Step 4 for each slicing variables projNumber intProjNo workItemNo currentActivityNo start_Date finish_Date totalActivityNumber inputActivity oldStartDate duration inputactivity dateDiff shiftAmount input_Activity current_Activity old_Start_Date dur activityCount dateDifference 4 4 4 4 19 14 5 95 6 60 14 22 12 101 94 6 48 3 46 561 Total Time 1034 For each of the slicing variables, previous version of SA prepares and analyzes a new AST, step 3 & 4 in Table 5-11. It spends significant amount of time to construct the AST for that slicing variable and then extracts information from that AST. If the number of statements that the slicing variable participates is low (e.g., projNumber), then the time spent to analyze that slicing variable is small. If the number of statements that the slicing variable participates is high (e.g., input_Activity), then the time spent to analyze that slicing variable is large. As the number of slicing variables in source code increases, the total time spent for step 3 & 4 increases. The new SA executes two main steps which were explained in Section 4.4. Step 1: Prepare classes.

PAGE 90

77 Step 2: Analyze the methods starting from main method of the given class. Step 1 prepares all the user-defined classes that are used in the application. Then, Step 2 analyzes the methods. Table 5-12 shows time spent to prepare each of the classes in Construction Scheduling program, namely ScheduleMenu, ScheduleList, and ManipulateActivity classes. Note that, time is given in milliseconds. Table 5-12 Time spent (in milliseconds) in current version of SA. Step No Class or Method Name that is being processed Time Spent ScheduleMenu Class 8406 ScheduleList Class 2157 Step 1 Prepare Classes ManipulateActivity Class 10765 main Method of ScheduleMenu Class 219 doDatabaseInitializations Method of ScheduleMenu Class 0 getTotalActivityNumber Method of ScheduleMenu Class 813 menu Method of ScheduleMenu Class 31 initiliazeProjectQuery Method of ScheduleList Class 62 listProjects Method of ScheduleList Class 47 listActivities Method of ScheduleList Class 219 rescheduleActivity Method of ManipulateActivity Class 1516 shiftActivity Method of ManipulateActivity Class 187 Step 2 Analyze Methods changeActivity Method of ManipulateActivity Class 1063 Total 29642 The reader can notice that the current version applies Step 1 to each class and applies Step 2 to each method. In the current version of SA, the increase in the number of slicing variables slightly affects the performance, because the current SA does not construct and traverse the AST for each slicing variable. Instead, it constructs the AST for each class and traverses it for each method. While traversing the AST, the current SA considers all slicing variables and analyzes them simultaneously. The total time spent values in Table 5-11 and 5-12 show that we improved the performance of SA by a factor of 35 (1034 / 29.6).

PAGE 91

CHAPTER 6 CONCLUSION AND OPPORTUNITIES FOR FUTURE RESEARCH The SEEK project (Scalable Extraction of Enterprise Knowledge) currently under way in the Database Research and Development Center at the University of Florida has resulted in novel and comprehensive methodologies for semantic analysis of application code to assist in generating a detailed description of a legacy information system. This detailed description of the legacy system is used to overcome problems of assembling knowledge resident in numerous legacy information systems in the business network. The SEEK project aims to enable extended enterprise collaboration in complex business networks. Lack of techniques for scalable extraction of knowledge resident in participating firms in the extended enterprise is an important barrier to such collaboration. In the SEEK project, we develop methodologies and algorithms to discover and extract the detailed description of the legacy system in a flexible and scalable manner that significantly reduces human involvement. SEEK is not meant as a replacement for wrapper or mediator development toolkits. Rather, it complements existing tools by providing input about the contents and structure of the legacy source that has so far been supplied manually by domain experts [1]. The theories and methodologies proposed in this thesis provide a significant improvement to the existing semantic analyzer in SEEK. The previous version represented a comprehensive solution for mining semantic knowledge from application code [2]. This thesis adds heuristics which represent a more extensible and robust approach for extracting semantic information from legacy source. At the same time, our 78

PAGE 92

79 approach performs significantly better in terms of execution time. Furthermore, this thesis provides a generic solution for the semantic analysis problem for application code written for relational databases. Our approach uses state-of-the-art techniques to obtain the source code when it is only available in the form of object files, to get the AST for the source code, and to extract semantics from that AST. We briefly summarize the contributions made by the research described in this thesis followed by a discussion of possible enhancements that can be performed in future extensions. 6.1 Contributions The most significant contribution of our SA is to integrate and utilize state-of-the-art techniques from different research areas such as code reverse engineering, parser generation, and object oriented programming as shown in Chapter 3. Our new SA introduces a new extensible and flexible algorithm for semantic extraction. Our modifications and upgrades in the algorithm of the SA resulted in a design that is extensible in the following two ways: 1. SA can be easily extended to mine a different programming language. This can be done simply by replacing the abstract syntax tree generator module with another JavaCC produced parser. Using JavaCC parsers not only helps the AST generator to be extensible but also provides a robust parser when the grammar specification file from JavaCC repository is used. This specification was tested over thousands of code files. 2. New algorithms to extract extra information can be added easily. This means when a new heuristic is found, the functionality of this heuristic can be introduced to the SA structure by creating a new visitor pattern class. A visitor pattern that analyzes the AST of the source code can be plugged in and out to enhance the functionality of SA at any time. Moreover, our new SA algorithm eliminates analyzing unnecessary code. Source code can contain methods that are never used. The functionality inside this unused code

PAGE 93

80 can be misleading. SA extracts the control flow graph of the code and analyzes only the methods that are in the control flow graph. The design and implementation of new semantic analyzer algorithm improves temporal performance, and also provides the most accurate results as shown in Chapter 5. Traversing multiple code files to gather the overall semantics is another important feature of our new SA. Since the functionality of the legacy application is usually distributed into separate files, it is important to gather semantics of related modules and be able to combine them to obtain better feedback about the semantics of the application as a whole. The implementation of SA is done in Java. Java is an object oriented language enabling us to implement object oriented techniques. SAs object oriented structure is another contribution. We see the following benefits of using an object oriented implementation for SA: We have the chance of using visitor design patterns. A visitor design pattern is used to separate functionality of information extraction process into separate visitor classes. This makes our code flexible and extensible. Object oriented techniques like abstraction and encapsulation are used.Thus, functionality is separated and encapsulated inside separate classes which make its maintenance easier. SA uses state-of-the-art code reverse engineering techniques to get the source code back from the binary code. If the binary code is available, but the source code is misplaced, SA uses these techniques to get the text of the source code. 6.2 Future Work In this last section, we discuss possible improvements to SA that can be added to future versions. Our current semantic analyzer extracts semantics from Java code of legacy system. One possible improvement to SA can be functionality to infer semantic

PAGE 94

81 information from the code of stored procedures and triggers as well. Once we analyze the stored procedure calls from the Java code and the functionality of stored procedures, more semantic information will be gathered. Once we analyze the triggers, we can see the effect of insert, update, and delete SQL statements to other entities of the underlying data schema. A trigger is often used to check the constraints of a table. If the constraint is not satisfied with an insert, update, or delete SQL statement, then the trigger cancels the operation. If the constraint is implemented in the code of the trigger instead of implementing in the schema definition of the table, then SE will not discover it, but SA will discover and enhance the extracted schema of the data source. Another usage of the trigger is to make updates, and inserts to related tables if necessary. When we analyze the triggers, we discover relationships between entities that we may not be able to discover with extracting the schema and analyzing the application code. Operations are recorded in a transaction log in a database system. In database programming, SQL statements that must be executed as a whole are placed in the same transaction and are committed as if they are one atomic statement. Database management systems keep transaction logs to assure that these SQL statements are committed as a one atomic statement. SQL statements in the same transaction are highly related with each other and this relation inherits semantic information. Extending the SA, to analyze the transaction logs, can be another improvement. Our semantic analyzer identifies its slicing variables according to the user interaction statements inside the code. Then, it investigates the meaning of these slicing variables. Specifically, user interaction statements are input/output statements that are used to interact with the user via the standard input/output. There can be many other

PAGE 95

82 methods of user interaction. Information coming from application can be presented to the user in many ways. We can call the part of the code that presents and gathers information from the user as the presentation layer. We can also call the part of the code that inherits the functionality as the application layer. The presentation layer of legacy information system can be totally separated from the application layer. This presentation layer can be application specific and can be developed with the help of the technologies like JSP, and HTML. In such cases information exchanged between the presentation and application layers inherits semantic information. This information flow between the presentation and application layers can be investigated, and new modules to SA can be added to capture this information. When we analyze this user interaction information and relate it to the underlying schema of the legacy system, more semantics will be gathered. The number of real application source codes used to test the features of the SA was limited but we have used all the available codes. Future experiments on a large code sample have to be conducted to assert the correctness of our work.

PAGE 96

APPENDIX A GRAMMAR SPECIFICATION FILE EXAMPLE FOR JAVACC The specification file may start with a section of options to configure the type of parser JavaCC will generate. For example, IGNORE_CASE can be set to force the parser to treat upper and lowercase characters the same. Then PARSER_BEGIN statement comes. JavaCC uses the string that is passed to this statement to name the parser's class file. After the statement, any Java subroutines can be added in. A main method that instantiates the parser should also be written, so that it can be tested from the command line. This section of the file terminates with a PARSER_END statement. The last part of the file contains the token definitions and productions. An example of .jj file is provided in the Figure A-1. The parser that is generated from this grammar specification file reads an Input token. This token consists of one or more Id tokens. The Id tokens consist of a letter, followed by zero or more letters, numbers, or underscores. The parser skips blanks, tabs, carriage returns, and new lines. Each production has an empty pair of braces at the beginning. This is where Java code is placed for the production (usually variable declarations). Within the production rules, more braces can be added and Java code can be inserted that will execute when that production matches. When the below specification file is given to JavaCC, these files are created IdS.java : main method, methods for each non-terminals, debug(trace) methods, getNetToken method IdSConstants.java : interface for tokens 83

PAGE 97

84 IdSTokenManager.java : manages the token source file ParseException.java : Exceptions SimpleCharStream.java : IdSTokenManager uses Token.java : describes the input token stream TokenMgrError.java : Returns a detailed message for the Error when it is thrown by the token manager to indicate a lexical error. Table A-1 Example of .jj file. options { IGNORE_CASE=true; } PARSER_BEGIN(IdS) public class IdS { public static void main(String args[]) throws ParseException { IdS parser = new IdS(System.in); parser.Input(); } } PARSER_END(IdS) SKIP : { " | "\t" | "\n" | "\r" } TOKEN : { < Id: ["A"-"Z"] ("A"-"Z","0"-"9","_"] )* > } void Input() : {} { ( )+ }

PAGE 98

APPENDIX B COMPILER BASIC TERMS B.1 Production Rules Rules in a context free grammar is known as production. Symbols on the left hand sides of the production are known as variables, or non-terminals. Symbols that are to make up the strings derived from the grammar are known as terminals. B.2 LL and LR Grammars The two most important classes of grammars are LL and LR. LL stands for left to right, Left most derivation LR stands for left to right, Right most derivation. In both cases input is read left-to-right. LL parsers are also called top-down or predictive parsers They construct a parse tree from the root to down. LR parsers are also called bottom-up parsers They construct a parse tree from leaves up. There are several important subclasses of LR parsers, including SLR, LALR and full LR. LL(2) or LALR(1): number in parenthesis indicates how many tokens of look ahead are required to parse. B.3 Table Driven Top-Down Parsing Instead of using its procedure call chain to trace out a tree traversal, the parser maintains a stack containing a list of symbols it expects to see in the future. Initially, the parse stack contains the start symbol of the grammar. When it predicts a production, the parser pops the left-hand side symbol off the stack and pushes the right hand side symbols in reverse order. It also pops the terminal off the stack whenever it matches it against a token from the scanner. 85

PAGE 99

86 B.4 Lexical Analyzer Lexical analyzer (token manager in JavaCC) reads in a sequence of characters and produces a sequence of objects called "tokens". The rules used to break the sequence of characters into a sequence of tokens obviously depend on the language; they are supplied by the programmer as a collection of "regular expressions". B.5 The Parser The parser consumes the sequence of tokens, analyses its structure, and produces "abstract syntax tree".

PAGE 100

APPENDIX C DECOMPILED FILE EXAMPLE In this Appendix, we give an example to show how accurately Jad decompiler can convert .class files to .java files. In Table C.1, we show the original source code of ScheduleMenu.java. We compile ScheduleMenu.java and get the ScheduleMenu.class file. Then, we de-compile ScheduleMenu.class file with Jad decompiler and get another version of ScheduleMenu.java code. In Table C.2, we show the de-compiled version of ScheduleMenu.java. Table C.1 Original version of ScheduleMenu.java code. import java.sql.*; import java.util.*; import java.io.*; public class ScheduleMenu{ static String database = "jdbc:oracle:thin:@oracle.cise.ufl.edu:1521:oradb"; static String user = "****"; static String password = "******"; static int totalActivityNumber; static Connection jdbcConnection; static Statement sqlStatement; static ResultSet resultSet=null; static String query = null; public static void doDatabaseInitializations(String databaseName, String userName, String pass) throws Exception { /******* CONNECTS TO DATABASE *******/ Class.forName("oracle.jdbc.driver.OracleDriver"); jdbcConnection = DriverManager.getConnection(databaseName,userName,pass); /******* PREPARES SQL STATEMENT *******/ sqlStatement = jdbcConnection.createStatement(); } public static String readLineFromConsole() { String lineRead = ""; try { BufferedReader br = null; InputStreamReader in1 = null; in1 = new InputStreamReader(System.in); br = new BufferedReader(in1); lineRead = br.readLine(); 87

PAGE 101

88 lineRead = lineRead.trim(); }catch(Exception e){ System.out.println(e.getMessage()); } return lineRead; } public static int getTotalActivityNumber() throws Exception { /******* GET TOTAL ACTIVITY NUMBERS *******/ query = "SELECT Count(Activ_no) FROM Activity "; resultSet = sqlStatement.executeQuery(query); int activityCount = 0; while(resultSet.next()) { activityCount = resultSet.getInt(1); } resultSet.close(); return activityCount; } public static String menu() { System.out.println("***************************************"); System.out.println("Please make a selection:"); System.out.println("1. List all the projects"); System.out.println("2. List the activities"); System.out.println("3. Select an activity to reschedule into the first available slot"); System.out.println("4. Select an activity to shift"); System.out.println("5. Select an activity to change its place"); System.out.println("6. Exit Application"); System.out.println("***************************************"); System.out.println("Please enter the option number you selected: "); return readLineFromConsole(); } public static void main(String[] args) throws Exception{ String menuOption="*"; doDatabaseInitializations(database,user,password); System.out.println(menuOption); totalActivityNumber = getTotalActivityNumber(); menuOption = "1"; ScheduleList scheduleList = new ScheduleList(); ManipulateActivity manipulateSchedule = new ManipulateActivity(); while (! menuOption.equals("6")) { menuOption = menu(); if (menuOption.equals("1")) { scheduleList.listProjectNames(sqlStatement,resultSet);

PAGE 102

89 //list project names } if (menuOption.equals("2")) { scheduleList.listActivities(sqlStatement,resultSet); //list activities } if (menuOption.equals("3")) { manipulateSchedule.rescheduleActivity(sqlStatement,resultSet,jdbcConnection); //"(3) Select an activity to reschedule into the first available slot" } if (menuOption.equals("4")) { manipulateSchedule.shiftActivity(sqlStatement,resultSet,jdbcConnection); //""(4) Select an activity to shift"" } if (menuOption.equals("5")) { manipulateSchedule.changeActivity(sqlStatement,resultSet,jdbcConnection); //""(4) Select an activity to change place"" } } } //end main } Table C.2 De-compiled version of ScheduleMenu.java code. // Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://kpdus.tripod.com/jad.html // Decompiler options: packimports(3) // Source File Name: ScheduleMenu.java import java.io.*; import java.sql.*; public class ScheduleMenu { public ScheduleMenu() { } public static void doDatabaseInitializations(String s, String s1, String s2) throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver");

PAGE 103

90 jdbcConnection = DriverManager.getConnection(s, s1, s2); sqlStatement = jdbcConnection.createStatement(); } public static String readLineFromConsole() { String s = ""; try { BufferedReader bufferedreader = null; InputStreamReader inputstreamreader = null; inputstreamreader = new InputStreamReader(System.in); bufferedreader = new BufferedReader(inputstreamreader); s = bufferedreader.readLine(); s = s.trim(); } catch(Exception exception) { System.out.println(exception.getMessage()); } return s; } public static int getTotalActivityNumber() throws Exception { query = "SELECT Count(Activ_no) FROM Activity "; resultSet = sqlStatement.executeQuery(query); int i; for(i = 0; resultSet.next(); i = resultSet.getInt(1)); resultSet.close(); return i; } public static String menu() { System.out.println("***************************************"); System.out.println("Please make a selection:"); System.out.println("1. List all the projects"); System.out.println("2. List the activities"); System.out.println("3. Select an activity to reschedule into the first available slot"); System.out.println("4. Select an activity to shift"); System.out.println("5. Select an activity to change its place"); System.out.println("6. Exit Application"); System.out.println("***************************************"); System.out.println("Please enter the option number you selected: "); return readLineFromConsole(); } public static void main(String args[]) throws Exception {

PAGE 104

91 String s = "*"; doDatabaseInitializations(database, user, password); System.out.println(s); totalActivityNumber = getTotalActivityNumber(); s = "1"; ScheduleList schedulelist = new ScheduleList(); ManipulateActivity manipulateactivity = new ManipulateActivity(); while(!s.equals("6")) { s = menu(); if(s.equals("1")) ScheduleList.listProjectNames(sqlStatement, resultSet); if(s.equals("2")) ScheduleList.listActivities(sqlStatement, resultSet); if(s.equals("3")) manipulateactivity.rescheduleActivity(sqlStatement, resultSet, jdbcConnection); if(s.equals("4")) manipulateactivity.shiftActivity(sqlStatement, resultSet, jdbcConnection); if(s.equals("5")) ManipulateActivity.changeActivity(sqlStatement, resultSet, jdbcConnection); } } static String database = "jdbc:oracle:thin:@oracle.cise.ufl.edu:1521:oradb"; static String user = "****"; static String password = "******"; static int totalActivityNumber; static Connection jdbcConnection; static Statement sqlStatement; static ResultSet resultSet = null; static String query = null; }

PAGE 105

APPENDIX D VISITOR CLASS EXAMPLE In this example, the implementation of a visitor class on a heterogeneous aggregate structure will be seen. This structure defines the first production rules of java grammar. Compilation unit has Package Declaration, Import Declaration, Type Declaration and in its production rule. Several production rules of Java grammar can be seen in the Figure D-1. CompilationUnit n0->[ PackageDeclaration) ] n1->( ImportDeclaration() )* n2->( TypeDeclaration() )* n3-> Packa g eDeclaration n0->NodeToken("package") n1->Name() n2->NodeToken(";") ImportDeclaration n0->NodeToken("import") n1->Name() n2->NodeOptional ([ "." "*" ]) n3->NodeToken(";") T y peDeclaration n0->ClassDeclaration() | InterfaceDeclaration() | NodeToken(";") n0->NodeToken("") Figure D-1 Example of production rules of Java grammar. CompilationUnit, PackageDeclaration, TypeDeclaration class definition of this structure can be seen in the Table D.1. Each class has an accept method. This method returns the control back to the visitor class by calling it by giving itself as a parameter. 92

PAGE 106

93 Table D.1 Class Definitions of Example Nodes of Tree public class CompilationUnit implements Node { public NodeOptional f0; public NodeListOptional f1; public NodeListOptional f2; public NodeToken f3; public Object accept(visitor.ObjectVisitor v, Object argu) { return v.visit(this,argu); } } public class PackageDeclaration implements Node { public NodeToken f0; public Name f1; public NodeToken f2; public Object accept(visitor.ObjectVisitor v, Object argu) { return v.visit(this,argu); } } public class TypeDeclaration implements Node { public NodeChoice f0; public Object accept(visitor.ObjectVisitor v, Object argu) { return v.visit(this,argu); } } The visitor interface has visit method for each of the node in the tree. The visitor class that implements this interface has to write a method to perform functionality for each of this node. Table D.2 Visitor Interface Public interface ObjectVisitor { public Object visit(CompilationUnit n, Object argu); public Object visit(PackageDeclaration n, Object argu); public Object visit(ImportDeclaration n, Object argu); public Object visit(TypeDeclaration n, Object argu); public Object visit(ClassDeclaration n, Object argu); }

PAGE 107

94 In the table below, a visitor class can be examined. Visitor class implements the interface ObjectVisitor and writes the desired functionality inside the appropriate methods. The visitor ObjectDepthFirst only traverses the tree in dept first order. The comments above each visit method shows which field corresponds to which part of the production. Table D.3 Visitor Class Example public class ObjectDepthFirst implements ObjectVisitor { /** f0 -> [ PackageDeclaration() ] f1 -> ( ImportDeclaration() )* f2 -> ( TypeDeclaration() )* f3 -> */ public Object visit(CompilationUnit n, Object argu) { Object _ret=null; n.f0.accept(this, argu); n.f1.accept(this, argu); n.f2.accept(this, argu); n.f3.accept(this, argu); return _ret; } /** f0 -> "package" f1 -> Name() f2 -> ";" */ public Object visit(PackageDeclaration n, Object argu) { Object _ret=null; n.f0.accept(this, argu); n.f1.accept(this, argu); n.f2.accept(this, argu); return _ret; } /** f0 -> "import" f1 -> Name() f2 -> [ "." "*" ] f3 -> ";" */

PAGE 108

95 public Object visit(ImportDeclaration n, Object argu) { Object _ret=null; n.f0.accept(this, argu); n.f1.accept(this, argu); n.f2.accept(this, argu); n.f3.accept(this, argu); return _ret; } /** f0 -> ClassDeclaration() | InterfaceDeclaration() | ";" */ public Object visit(TypeDeclaration n, Object argu) { Object _ret=null; n.f0.accept(this, argu); return _ret; } }

PAGE 109

APPENDIX E JAVA GRAMMAR Java Grammar production rules can be seen below. 1 CompilationUnit = [ PackageDeclaration() ] ( ImportDeclaration() )* ( TypeDeclaration() )* PackageDeclaration = "package" Name() ";" "import" Name() [ "." "*" ] ";" ImportDeclaration TypeDeclaration = ClassDeclaration()* | InterfaceDeclaration()* | ";" ClassDeclaration = ( "abstract" | "final" | "public" | "strictfp" )* UnmodifiedClassDeclaration() UnmodifiedClassDeclaration = "class" [ "extends" Name() ] [ "implements" NameList() ] ClassBody() ClassBody = "{" ( ClassBodyDeclaration() )* "}" NestedClassDeclaration = ( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp" )* UnmodifiedClassDeclaration() ClassBodyDeclaration = Initializer() | NestedClassDeclaration() | NestedInterfaceDeclaration() | ConstructorDeclaration() | MethodDeclaration() | FieldDeclaration() MethodDeclarationLookahead = ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" | "strictfp" )* ResultType() "(" InterfaceDeclaration = ( "abstract" | "public" | "strictfp" )* UnmodifiedInterfaceDeclaration() NestedInterfaceDeclaration = ( "static" | "abstract" | "final" | "public" | "protected" | "private" | "strictfp" )* UnmodifiedInterfaceDeclaration() UnmodifiedInterfaceDeclaration = "interface" [ "extends" NameList() ] "{" ( InterfaceMemberDeclaration() )* "}" InterfaceMemberDeclaration = NestedClassDeclaration() | NestedInterfaceDeclaration() | MethodDeclaration() | FieldDeclaration() 1 Java Grammar is extracted from the .jj file of Java Grammar that is obtained from JavaCC Repository [6]. 96

PAGE 110

97 FieldDeclaration = ( "public" | "protected" | "private" | "static" | "final" | "transient" | "volatile" )* Type() VariableDeclarator() ( "," VariableDeclarator() )* ";" VariableDeclarator = VariableDeclaratorId() [ "=" VariableInitializer() ] VariableDeclaratorId = ( "[" "]" )* VariableInitializer = ArrayInitializer() | Expression() ArrayInitializer = "{" [ VariableInitializer() ( "," VariableInitializer() )* ] [ "," ] "}" MethodDeclaration = ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" | "strictfp" )* ResultType() MethodDeclarator() [ "throws" NameList() ] ( Block() | ";" ) MethodDeclarator = FormalParameters() ( "[" "]" )* FormalParameters = "(" [ FormalParameter() ( "," FormalParameter() )* ] ")" FormalParameter = [ "final" ] Type() VariableDeclaratorId() ConstructorDeclaration = [ "public" | "protected" | "private" ] FormalParameters() [ "throws" NameList() ] "{" [ ExplicitConstructorInvocation() ] ( BlockStatement() )* "}" ExplicitConstructorInvocation = "this" Arguments() ";" | [ PrimaryExpression() "." ] "super" Arguments() ";" Initializer = [ "static" ] Block() Type = ( PrimitiveType() | Name() ) ( "[" "]" )* PrimitiveType = "boolean" | "char" | "byte" | "short" | "int" | "long" | "float" | "double" ResultType = "void" | Type() Name = ( "." )* NameList = Name() ( "," Name() )* Expression = ConditionalExpression() [ AssignmentOperator() Expression() ] AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>="

PAGE 111

98 | ">>>=" | "&=" | "^=" | "|=" ConditionalExpression = ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression() ] ConditionalOrExpression = ConditionalAndExpression() ( "||" ConditionalAndExpression() )* ConditionalAndExpression = InclusiveOrExpression() ( "&&" InclusiveOrExpression() )* InclusiveOrExpression = ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )* ExclusiveOrExpression = AndExpression() ( "^" AndExpression() )* AndExpression = EqualityExpression() ( "&" EqualityExpression() )* EqualityExpression = InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )* InstanceOfExpression = RelationalExpression() [ "instanceof" Type() ] RelationalExpression = ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )* ShiftExpression = AdditiveExpression() ( ( "<<" | ">>" | ">>>" ) AdditiveExpression() )* AdditiveExpression = MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )* MultiplicativeExpression = UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )* UnaryExpression = ( "+" | "-" ) UnaryExpression() | PreIncrementExpression() | PreDecrementExpression() | UnaryExpressionNotPlusMinus() PreIncrementExpression = "++" PrimaryExpression() PreDecrementExpression = "--" PrimaryExpression() UnaryExpressionNotPlusMinus = ( "~" | "!" ) UnaryExpression() | CastExpression() | PostfixExpression() CastLookahead = "(" PrimitiveType() | "(" Name() "[" "]" | "(" Name() ")" ( "~" | "!" | "(" | | "this" | "super" | "new" | Literal() ) PostfixExpression = PrimaryExpression() [ "++" | "--" ] CastExpression = "(" Type() ")" UnaryExpression() | "(" Type() ")" UnaryExpressionNotPlusMinus() PrimaryExpression = PrimaryPrefix() ( PrimarySuffix() )* PrimaryPrefix = Literal() | "this" | "super" "."

PAGE 112

99 | "(" Expression() ")" | AllocationExpression() | ResultType() "." "class" | Name() PrimarySuffix = "." "this" | "." AllocationExpression() | "[" Expression() "]" | "." | Arguments() Literal = | | | | BooleanLiteral() | NullLiteral() BooleanLiteral = "true" | "false" NullLiteral = "null" Arguments = "(" [ ArgumentList() ] ")" ArgumentList = Expression() ( "," Expression() )* AllocationExpression = "new" PrimitiveType() ArrayDimsAndInits() | "new" Name() ( ArrayDimsAndInits() | Arguments() [ ClassBody() ] ) ArrayDimsAndInits = ( "[" Expression() "]" )+ ( "[" "]" )* | ( "[" "]" )+ ArrayInitializer() Statement = LabeledStatement() | Block() | EmptyStatement() | StatementExpression() ";" | SwitchStatement() | IfStatement() | WhileStatement() | DoStatement() | ForStatement() | BreakStatement() | ContinueStatement() | ReturnStatement() | ThrowStatement() | SynchronizedStatement() | TryStatement() | AssertStatement() LabeledStatement = ":" Statement() Block = "{" ( BlockStatement() )* "}" BlockStatement = LocalVariableDeclaration() ";"

PAGE 113

100 | Statement() | UnmodifiedClassDeclaration() | UnmodifiedInterfaceDeclaration() LocalVariableDeclaration = [ "final" ] Type() VariableDeclarator() ( "," VariableDeclarator() )* EmptyStatement = ";" StatementExpression = PreIncrementExpression() | PreDecrementExpression() | PrimaryExpression() [ "++" | "--" | AssignmentOperator() Expression() ] SwitchStatement = "switch" "(" Expression() ")" "{" ( SwitchLabel() ( BlockStatement() )* )* "}" SwitchLabel = "case" Expression() ":" | "default" ":" IfStatement = "if" "(" Expression() ")" Statement() [ "else" Statement() ] WhileStatement = "while" "(" Expression() ")" Statement() DoStatement = "do" Statement() "while" "(" Expression() ")" ";" ForStatement = "for" "(" [ ForInit() ] ";" [ Expression() ] ";" [ ForUpdate() ] ")" Statement() ForInit = LocalVariableDeclaration() | StatementExpressionList() StatementExpressionList = StatementExpression() ( "," StatementExpression() )* ForUpdate = StatementExpressionList() BreakStatement = "break" [ ] ";" ContinueStatement = "continue" [ ] ";" ReturnStatement = "return" [ Expression() ] ";" ThrowStatement = "throw" Expression() ";" SynchronizedStatement = "synchronized" "(" Expression() ")" Block() TryStatement = "try" Block() ( "catch" "(" FormalParameter() ")" Block() )* [ "finally" Block() ] AssertStatement = "assert" Expression() [ ":" Expression() ] ";

PAGE 114

APPENDIX F ORACLE SQL GRAMMAR Oracle SQL Grammar production rules can be seen below. 1 SQLAndExpr = SQLNotExpr() ( SQLNotExpr() )* SQLBetweenClause = [ ] SQLSumExpr() SQLSumExpr() SQLColRef = SQLLvalue() SQLCompareExpr = ( SQLSelect() | SQLIsClause() | SQLExistsClause() | SQLSumExpr() [ SQLCompareExprRight() ] ) SQLCompareExprRight = ( SQLLikeClause() | SQLInClause() | SQLLeftJoinClause() | SQLRightJoinClause() | SQLBetweenClause() | SQLCompareOp() SQLSumExpr() ) SQLCompareOp = ( | | | | | | ) SQLCursorArgs = "(" [ ( SQLColRef() [ SQLDataType() ] | SQLFunction() ) ( "," ( SQLColRef() [ SQLDataType() ] | SQLFunction() ) )* ] ")" SQLCursorClose = SQLCursorDeclare = "cursor" [ SQLCursorArgs() ] "is" SQLSelect() ";" SQLCursorFetch = SQLSelectCols() [ SQLSelectCols() ] SQLCursorOpen = [ SQLCursorArgs() ] SQLDataType = "integer" | "smallint" | "number" [ "(" ")" ] | ( "char" | "character" ) [ "(" ")" ] | "varchar2" [ "(" ")" ] | "boolean" SQLDelete = SQLTableList() [ SQLWhere() ] SQLExistsClause = "(" SQLSelect() ")" SQLFunction = ( SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | 1 Oracle SQL Grammar is extracted from the .jj file of Oracle SQL Grammar that is obtained from JavaCC Repository. 101

PAGE 115

102 SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | SQLFunctionArgs() | | SQLFunctionArgs() ) SQLFunctionArgs = "(" [ SQLSumExpr() ( "," SQLSumExpr() )* ] ")" SQLGroupBy = SQLOrderByList() SQLInClause = [ ] "(" SQLLValueList() ")" SQLInsert = SQLTableList() [ "(" SQLSelectCols() ")" ] "(" SQLSelectCols() ")" SQLIsClause = SQLColRef() [ ] SQLLeftJoinClause = "(+)" SQLCompareOp() SQLSumExpr() SQLLikeClause = [ ] SQLPattern() SQLLiteral = ( | | | ( | ) | | ) SQLLvalue = ( SQLLvalueTerm() | SQLLvalueTerm() | SQLLvalueTerm() | | | SQLLvalueTerm() ) SQLLvalueTerm = ( )* SQLNotExpr = [ ] SQLCompareExpr() SQLOrderBy = SQLOrderByList() SQLOrderByElem = SQLColRef() [ SQLOrderDirection() ] SQLOrderByList = SQLOrderByElem() ( "," SQLOrderByElem() )* SQLOrderDirection = ( | ) SQLOrExpr = SQLAndExpr() ( SQLAndExpr() )* SQLPattern = ( | "?" | | SQLLvalue() ) SQLProductExpr = SQLUnaryExpr() ( ( "*" | "/" ) SQLUnaryExpr() )* SQLRightJoinClause = SQLCompareOp() SQLSumExpr() "(+)" SQLSelect =
Permanent Link: http://ufdc.ufl.edu/UFE0001210/00001

Material Information

Title: Extracting semantics from legacy sources using reverse engineering of Java code with the help of visitor patterns
Physical Description: Mixed Material
Creator: Topsakal, Oguzhan ( Author, Primary )
Publication Date: 2003
Copyright Date: 2003

Record Information

Source Institution: University of Florida
Holding Location: University of Florida
Rights Management: All rights reserved by the source institution and holding location.
System ID: UFE0001210:00001

Permanent Link: http://ufdc.ufl.edu/UFE0001210/00001

Material Information

Title: Extracting semantics from legacy sources using reverse engineering of Java code with the help of visitor patterns
Physical Description: Mixed Material
Creator: Topsakal, Oguzhan ( Author, Primary )
Publication Date: 2003
Copyright Date: 2003

Record Information

Source Institution: University of Florida
Holding Location: University of Florida
Rights Management: All rights reserved by the source institution and holding location.
System ID: UFE0001210:00001


This item has the following downloads:


Full Text












EXTRACTING SEMANTICS FROM LEGACY SOURCES
USING REVERSE ENGINEERING OF JAVA CODE
WITH THE HELP OF VISITOR PATTERNS













By

OGUZHAN TOPSAKAL


A THESIS PRESENTED TO THE GRADUATE SCHOOL
OF THE UNIVERSITY OF FLORIDA IN PARTIAL FULFILLMENT
OF THE REQUIREMENTS FOR THE DEGREE OF
MASTER OF SCIENCE

UNIVERSITY OF FLORIDA


2003


































Copyright 2003

By

Oguzhan Topsakal




























To My Mother H. Nedret Topsakal
And
To My Father Sabahatdin Topsakal















ACKNOWLEDGMENTS

I would like to give my sincere thankfulness to my thesis advisor, Dr. Joachim

Hammer. His kindness, encouragement and thoughtfulness meant so much during this

thesis study. I also would like to thank Dr. Douglas Dankel and Dr. Beverly Sanders for

serving on my committee. I also would like to thank all of my colleagues in the Scalable

Extraction of Enterprise Knowledge (SEEK) project, especially Dr. Mark Schmalz,

Lucian, Ming Xi, Nikhil and Sangeetha.

I am grateful to my parents, H. Nedret Topsakal and Sabahatdin Topsakal; to my

brother, Metehan Topsakal; and to my sister-in-law, Sibel Topsakal. They were always

there when I needed them; and they support me in whatever I do.

I also would like to thank all of my friends, my special treasures, for affecting my

life positively. There are some friends who have showed their care the most in the past

two years. H. Levent Akyil and Saskia Kameron are the ones who encouraged me the

most in pursuing advanced study in the U.S.; and supported me in every aspect during my

stay in U.S. My dear friend, Evren Dilbaz was always with me although he is thousands

of miles away. Members of Hayallerimiz team, Bahri Okuroglu and Oguzhan

Poyrazoglu, have always amazed me with their friendship. A. Koksal Hocaoglu, Nihat

Kasap and Aylin Yilmaz are the new treasures I have gained in Gainesville.

I would like to acknowledge the National Science Foundation for supporting this

research under grant numbers CMS-0075407 and CMS-0122193.
















TABLE OF CONTENTS
page

A C K N O W L E D G M E N T S ................................................................................................. iv

L IST O F TA B LE S ......... ............ .............................. .. .. ....... .............. viii

LIST OF FIGURES ............................... ... ...... ... ................. .x

ABSTRACT ........ .............. ............. .. ...... .......... .......... xii

CHAPTER

1 IN TR OD U CTION ............................................... .. ......................... ..

1.1 M motivation .............................................. 2
1.2 Solution A pproaches......................................... .................................. 3
1.3 C challenges .............................................. 4
1 .4 C o n trib u tio n s ................... .... ................................ ...... ........ .......... .. ....
1.5 O organization of T hesis........................................................................... .... ... 6

2 RELA TED RESEARCH .......................................................... ..............8

2.1 C ode R everse Engineering ........................................... ........................... 9
2.1.1 W hat is a D ecom piler? ........................................ ......................... 9
2.1.2 H history of D ecom pilers .................... .... ................ ............... ... 10
2.1.3 Why Successful Decompiling is Possible in Java.............................. 10
2.1.4 Purpose of Decompilation .............. ............ ............. .. ............. 11
2.1.5 Exam ples of D ecom pilers.................... ............. ......... ... .............. 11
2 .1.5.1 M ocha ............ .................................. .. ............... ............. 11
2 .1 .5 .2 Jad ................................................................... 12
2 .2 P arser G generation .......................................................................... ...... 12
2.2.1 Com piler-Com piler Tools ............................................ ............... 13
2.2.2 JavaCC and its Features ........................... .............. ............... 13
2.2.3 The Grammar Specification File of JavaCC ........... ................... 16
2.2.4 Java Tree Builder (JTB ) ........................................ ....... ............... 16
2.3 V isitor D esign Pattern................................ ........ ................ ............... 19
2 .3 .1 D esig n P attern s ................... ..... .............................. .. ................ .. 19
2.3.2 Features of Visitor Design Pattern ............. ..........................................19
2.3.3 A analogy for V visitor Pattern .......................................... ............... 20
2.3.4 Double Dispatching in Visitor Patterns......... ...... ........ ............... 21









2.4 State-of-the-art in Extracting Knowledge from Application Code....................22
2.4.1 Lexical and Syntactic A analysis .................................... ............... 22
2.4.2 Control Flow A nalysis....................................... .......................... 22
2.4.3 Program Slicing ....................................... ............ .. ........ .. ........ .... 23
2.4.4 Pattern M watching .................................. .....................................23
2.5 Business Rules Extraction ........................................ ........................... 23
2 .5.1 B u siness R ules............. .............................. .......... .... .. ........... 24
2.5.2 Categories of Business Rules ............................................................... 24
2.5.3 Where Are Business Rules Implemented in Information Systems .........25
2.5.4 Extracting Business Rules .................................. ..... ................... 26
2.5.5 Importance of Business Rule Extraction from Program Code ...............26

3 SEMANTIC ANALYSIS ALGORITHM ........................................... .............27

3 .1 In tro d u ctio n ............... .. ............... ................ ............................................... 2 7
3.2 Objective of Semantic Analysis..................................................30
3.3 Components of the Semantic Analyzer .....................................................31
3.3.1 Decompiler ............. ...... .... ...............31
3.3.2 Abstract Syntax Tree Generator .................................... .................. 32
3.3.3 Information Extractor ....... ...........................................33
3.4 Extensibility of the Semantic Analyzer............... ...........................................34
3.5 Extracting Semantics from Multiple Files ..................................................... 35
3.6 Finding the Class Source Code Files..... .......... ...................................... 36
3 .6 Slicing V ariables.......... ................................................................. ..... .... .. 37
3.7 H euristics U sed ................ ................... ..................... .. ........ .... 38

4 IMPLEMENTATION OF THE JAVA SEMANTIC ANALYZER ........................44

4 .1 P package Structure ............4.. .. ...... .. ........ .... .. .... .. .................. ... 45
4.2 Using the Java Tree Builder To Augment the Grammar Specification File......48
4.3 G generate Parser by JavaC C ........................................ .......... ............... 49
4.4 Execution Steps of Java Semantic Analyzer ...................................................50
4.4.1 M making Preparations to Analyze .................................. ............... 51
4.4.2 A nalyze Source C ode ........................................ ......................... 52
4.5 Functionality of Visitor Classes............... ............................... ... ............ 54
4.5.1 Output Abstract Syntax Tree to XML File.........................................54
4.5.2 Get Variable and Method Declaration Information.............................55
4.5.3 Get Slicing Information........... ...... .................... ...............56
4.5.4 Get Business Rules and Comments.......................... ............... 57
4.5.6 Get M ethod Calls........................................................... 60
4.5.7 Get Package-Im port-Extend Info .................................... ............... 61
4.5.8 G et SQ L Statem ents ........................................ .......................... 61
4.5.9 P arse SQ L Strings............. .... ............................ ...... ........ ......... 61









5 EVALUATION OF SEMANTIC ANALYZER ....................................................63

5.1 Can Features of Semantic Analyzer Extract Semantics Correctly? ................. 63
5.1.1 Targeting a Specific Column from the Query ......................................63
5.1.2 Extracting the Column Name from Mathematical Expression...............65
5.1.3 Geting Query Expression from the Variable Value .............................66
5.1.4 Concatenating Strings to Get the Query Expression..............................67
5.1.5 Geting the Meaning of Slicing Variable from the Output Text..............68
5.1.6 Passing Semantics from one Method to Another ..................................69
5.1.7 Extracting the Meaning from the Title Output ........... ..............69
5.2 Correctness Evaluation ............ ..... ................................. 71
5.3 Perform ance Evaluation.......................................................... ............... 75

6 CONCLUSION AND OPPORTUNITIES FOR FUTURE RESEARCH..................78

6 .1 C o n trib u tio n s ........................................................................... ................ .. 7 9
6.2 F future W ork .....................................................................80

APPENDIX

A GRAMMAR SPECIFICATION FILE EXAMPLE FOR JAVACC ........................83

B C O M PILER B A SIC TER M S .......................................................... .....................85

B .1 P ro du action R u les ..................................................................... .................... 8 5
B.2 LL and LR Grammars .............. ... ................................. 85
B.3 Table Driven Top-Down Parsing ....................................... ...............85
B .4 L exical A nalyzer ....... ................................................ .. ... ... .... .. ... .. 86
B .5 T h e P a rse r ................................................................................................... 8 6

C DECOM PILED FILE EXAM PLE ........................................ ........................ 87

D VISITOR CLASS EXAM PLE ............................................................................92

E JA V A G R A M M A R ............................ ....................................... ............. ........... 96

F ORACLE SQL GRAM M AR ......................................................... ............... 101

G CONSTRUCTION SCHEDULING PROGRAM ...................................................104

L IST O F R E FE R E N C E S ........................................................................ ................... 115

B IO G R A PH IC A L SK E TCH .............................................................. .....................117
















LIST OF TABLES


Table pge

2-1 Automatically generated tree node interface and classes............... ...................17

4-1 JavaCC generated parser files. ............................................................................ 49

4-2 Information stored for variable/method declaration in SymbolTableElement .........57

4-3 Information stored in BusinessRule class. .................................... .................58

4-4 Information stored in ResultsetSQL structure.......................... ... ............... 62

5-1 Examples of ResultSet get method parameters. ............................................. 64

5-2 Example of a SQL query that has mathematical expression in its column list........65

5-3 Example of using variable in the executeQuery method ..................................66

5-4 Example of Concatenating String to Get the Query Expression............................67

5-4 Making relations between output statements and columns................... ................68

5-5 An example of passing parameter values. ...................................... ............... 70

5-6 Extracting the m meaning from the title ............................ ............... .... ........... 70

5-7 Extracted Meanings of the Columns from the Construction Scheduling Program
Source C ode. .........................................................................72

5-8 Extracting the meaning from title of the outputs...................... ...............73

5-9 Code fragment inside the main method of ScheduleMenu.java.............................74

5-10 Code fragment from ScheduleList.java shows how variable semantic is
transferred from one method to another. ........................................ ............... 74

5-11 Time spent (in seconds) in sub steps of previous version of SA..............................76

5-12 Time spent (in milliseconds) in current version of SA. .........................................77

A -1 Exam ple of .jj file ................... ............. .... ........... ..................84









C.1 Original version of ScheduleMenu.java code. ................................. ...............87

C.2 De-compiled version of ScheduleMenu.java code............................................89

D.1 Class Definitions of Example Nodes of Tree...................................... ..................93

D .2 V isitor Interface .......... ....................................................................... ....... .. ....... .. 9 3

D .3 V visitor C lass E xam ple .............................................................................. .... ........94

G 1 Code of ScheduleM enu.java. .......................................................... ............... 104

G .2 Code of ScheduleList.java ........................................................ ............... 106

G.3 Code of ManipulateActivity.j ava. ................................................................... 107
















LIST OF FIGURES


Figure p

3-1 High-level view of the SEEK Architecture................. ............... .................27

3-2 Sem antic Analyzer Com ponents. ....................................................................... 31

3-3 Checking the success of decompiling process. .............................. ............... .32

3-4 Two main steps of Information Extraction. .................................................33

3-5 Traversing betw een class files........................................... ........................... 36

3-6 F ile F in der ........................................................................... 37

4-1 Architectural overview of the SA prototype and related components ...................44

4-2 Java Semantic Analyzer Packages Structure 1................................. ............... 46

4-3 Java Semantic Analyzer Packages Structure 2 ................................ ............... 47

4-4 Input and outputs of the JTB tool ............................................................ ........... 49

4-5 Initialization of the Java Semantic Analyzer.......... ....................................... 51

4-6 Eight steps that make up prepareForProcess method ....................... ............... 51

4-7 Seven steps that make up analyzeMethods method. ..............................................53

4-8 Link List Structure of Traversed Method Tree of SA...........................................55

4-9 Example of a business rule that inherits another business rule .............................58

4-10 The content of the stacks at point when "*" in Figure 4-9 is reached....................59

4-11 The content of the stacks at point when '#' in Figure 4-9 is reached ...................60

4-12 List of M ethod Calls Structure. ........................................ ........................... 60

4-13 Example of a ResultsetSQL class........................................................................62

5-1 Example of a Rei,,n1heiQL class and ColumnElement and TableElement lists......65









5-2 ResultSetSQL class representation of the query in Table5.2................................66

5-3 Illustration of String SymbolTableElements and their values. ................................67

D-1 Example of production rules of Java grammar. ....................................................92















Abstract of Thesis Presented to the Graduate School
of the University of Florida in Partial Fulfillment of the
Requirements for the Degree of Master of Science

EXTRACTING SEMANTICS FROM LEGACY SOURCES
USING REVERSE ENGINEERING OF JAVA CODE
WITH THE HELP OF VISITOR PATTERNS

By

Oguzhan Topsakal

August 2003

Chair: Joachim Hammer
Major Department: Computer and Information Science and Engineering

As the need increase for enterprises to participate in large business networks (e.g.,

supply chains), the need to optimize these networks to ensure profitability also increases.

However, because of the heterogeneities of the underlying legacy information systems,

existing integration techniques fall short of enabling the automated sharing of data among

participating enterprises. Current integration techniques require manual effort and

significant programmatic set-up. This necessitates the development of more automated

solutions to enable scalable extraction of knowledge resident in legacy systems of a

business network, to support efficient sharing. Given that an application is a rich source

for semantic information including business rules, we developed algorithms and

methodologies to extract semantic knowledge from the legacy application code.

Our novel methodology integrates and improves existing techniques including

program slicing, program dependence graphs, pattern matching, and design patterns. Our









techniques advance the state-of-the art in many ways, most importantly to bring a generic

approach that can be applied to any language code.

Semantic knowledge extracted from the legacy application code contains

information about the application-specific meaning of entities and their attributes as well

as business rules and constraints. Once extracted, this semantic knowledge is important to

the schema matching and wrapper generation processes.

This thesis presents an overview of our approach. Evidence to demonstrate the

extraction power and features of this approach is presented using a prototype developed

in the context of the Scalable Extraction of Enterprise Knowledge (SEEK) project at the

Database Research and Development Center at the University of Florida.














CHAPTER 1
INTRODUCTION

In today's business markets, many factors increase the competition such as

customization of products, demand on rapid delivery, and decrease in profit. To survive

in this competitive environment, efficient collaborative production in a business network

is required. An enterprise or business network is the collaboration of several firms to

achieve a common goal. The success of a business network is highly dependent upon

coordination among participants. Decision and integration support tools are needed to

improve the ability of a participant in a business network to coordinate, plan, and respond

to dynamically changing conditions. Because of the heterogeneity of the legacy

information systems of the participants, data and knowledge integration among systems

in a business network require a great deal of programmatic setup with limited code

reusability. Therefore, there is a need to develop a toolkit that can semi-automatically

discover enterprise knowledge from sources; and use this knowledge to configure itself

and act as software between the legacy sources. The Scalable Extraction of Enterprise

Knowledge1 (SEEK) project underway in the Database Research and Development

Center at the University of Florida is directed at developing methodologies to overcome

some of the problems of assembling knowledge in numerous legacy information systems

[1,2].




1 This project is supported by National Science Foundation under grant numbers CMS-0075407 and CMS-
0122193.









1.1 Motivation

A legacy source is defined as a complex stand-alone system with poor or

nonexistent documentation for the data and application code or other components of the

information system. A typical enterprise network has contractors and subcontractors that

use such legacy sources to manage their data. The data present in these legacy sources is

an important input to making decisions at the project level. Legacy systems of

participants of enterprise network usually have a high degree of physical and semantic

differentiations for the reasons stated below. These differences cause many problems for

accessing and retrieving data from the underlying legacy source to provide input to

decision support tools. The problems of providing information for decision support tools

[1] can be stated as follows.

* There is a difference between various internal data storage, retrieval, and
representation methods. Some firms might use professional database management
systems while some others might use simple flat files to store and represent their
data. There are many interfaces including SQL or other proprietary languages that a
firm may use to manipulate its data. Because of such high degrees of physical
heterogeneity, the effort to retrieve even similar information from every firm in the
supply chain requires extensive work on the data stored in each system.

* There is semantic heterogeneity among firms. Even though the supply chain
consists of firms working in the closely related domains, there is a difference in the
internal terminology. This kind of heterogeneity presents at various levels in the
legacy information source including the application code that may encode business
rules.

* Another challenge in accessing the firm's data efficiently and accurately is
safeguarding the data against loss and unauthorized usage. Participating firms in
the supply chain may want to restrict the sharing of strategic knowledge including
sensitive data or business rules. Therefore, it is important to develop third-party
tools that assure the privacy of the concerned firm and still extract useful
knowledge.

* The frequent need of human intervention in the existing solutions is another major
problem for efficient cooperation. This limits automation of the process which
makes it costly and inefficient.









Thus, it is necessary to build extensible data access and extraction technology that

automates the knowledge extraction process.

1.2 Solution Approaches

The role of the SEEK system is to act as an intermediary between the legacy data

and the decision support tool. In general, SEEK [1-3] operates as a three-step process:

Step 1: SEEK generates a detailed description of the legacy source including

application-specific meanings of the entities, relationships, and business rules. We

collectively refer to this information as enterprise knowledge. Extracting enterprise

knowledge is a build-time process which is achieved by the data reverse engineering

(DRE) component of SEEK. The Schema Extractor (SE), which is a sub-component of

DRE, extracts the underlying database conceptual schema while another sub-component

of DRE, the Semantic Analyzer (SA), extracts application specific meanings of the

entities, attributes, and the business rules of the enterprise.

Step 2: The semantically enhanced legacy source schema must be mapped onto the

domain model (DM) used by the applications that want to access the legacy source. This

is done using a schema mapping process that produces the mapping rules between the

legacy source schema and the application domain model.

Step 3: The extracted legacy schema and the mapping rules provide the input to the

wrapper generator, which produces the source wrapper. The source wrapper at run-time

translates queries from the application domain model to the legacy source schema.

In this thesis we focus exclusively on the build-time component which is described

in Step 1. Specifically, we focus on developing robust and extensible techniques to

extract application-specific meanings from code written for a legacy database. To get a

comprehensive understanding of the source data and how it is represented, we augment









the schema information extracted by the SE with application-specific meanings

discovered by the SA. Let us briefly illustrate our approach using a very simple example

from the Construction Scheduling domain. Let us assume that when we extract the

schema from the existing legacy source database using SE, we find that it contains a table

named Proj which has an attribute named id. Without any further knowledge, we

would probably not be able to understand the full meaning of these two schema items.

This is where semantic analysis comes in. Let us assume we also have access to the

application code that uses the database and upon further investigation, SA encounters

output statements of the form: "Please Enter Project Number." Using program

comprehension techniques described later in this thesis, SA can trace this and other

output statements back to the corresponding items in the database where the values are

eventually stored. So, if SA can trace the output statement above top id of Proj table, we

can conclude that Proj stores information about projects and that id contains project

numbers. Describing the details of how SA works is the focus of this thesis. Specifically,

the research describe here extends some of the heuristics for semantic extraction

developed previously [2] and produces a more robust, extensible infrastructure for

semantic extraction with improved accuracy and performance.

1.3 Challenges

Semantic analysis can be defined as the application of techniques to one or more

source code files, to extract semantic information to provide a complete understanding of

the enterprise's business model. There are numerous challenges in the process of

extracting semantic information from source code files with respect to the objectives of

SEEK, which include the following:









* The functionality of the enterprise information system could be separated across
several files. Thus, careful integration of the semantic information should be
achieved.

* To gather information from multiple files, first the location of the file in the
classpath or inside the imported packages should be specified.

* The SA may not have access or permissions to all the source code files. The
accuracy and the correctness of the semantic information generated should not be
affected even if partial or incomplete semantic information is extracted.

* High-level object oriented language features such as inheritance and method
overloading increases the complexity of the SA.

* Source code and the underlying database design could be modified because of the
changing business needs. Attributes with non-descriptive, even misleading names
may be added to relations. The SA should correctly discover the application-
specific meanings behind this attributes.

* Existing source code of a legacy system may not reflect the functionality of the
running application. The source code might have been displaced or the version
information of it may not be accurate. A way of using an application's binary code
should be determined to get the latest functionality of the system.

* The semantic analyzer must be robust and must be capable of analyzing any source
code of the target language.

* The semantic analyzer could be easily configured to accept other language source
codes as an input.

* The semantic analysis approach should be generic enough to accept implementation
of new heuristics to extract more information from the source code.

* Semantic analyzer should be easily maintained when an improvement is desired to
be made on the existing functionality.

* Although the time performance is not a primary concern, SA should finish the
analysis in a reasonable time period.

* SA should be able to parse any SQL statement, obtaining information from it.

1.4 Contributions

SA has brought the following contributions, which correspond to the challenges


listed above:









* SA prototype can accurately integrate the information gathered from multiple files.

* Current SA can correctly find the location of the desired file in the classpath or
inside the imported packages even if it is inside a compressedjar or zip files.

* The output of current SA still provides potentially valuable information for schema
matching.

* High level object oriented language features like method overloading are
successfully handled by SA.

* SA can correctly discover the application specific meanings of attributes even if the
attributes names are non-descriptive or misleading.

* SA uses state-of-the-art code reverse engineering techniques to get the source code
back from the binary code if the source code is misplaced.

* SA can parse and analyze any source code of Java language.

* SA can be easily extended to analyze other language source code inputs.

* SA can be extended to cover new heuristics.

* SA uses dynamic link list structures not to limit its capacity.

* SA's object oriented structure provides abstraction and encapsulation of the
functionality which makes the maintenance easier.

* SA's time complexity has significantly decreased. It extracts the semantics with the
same accuracy in a shorter period of time when compared to the previous version.

* Current version of SA can not only extract meaning from SQL Select statements,
but also extract semantics from Update, Insert, and Delete statements.

1.5 Organization of Thesis

Chapter 2 presents an overview of the related research in the field of business rules,

abstract syntax tree generator tools and design patterns. Chapter 3 provides a description

of the approach for extracting semantics from the legacy code. Chapter 4 is dedicated to

describing the implementation details of semantic analyzer. Chapter 5 highlights the

power of the SA in terms of what kind of semantics it can capture. Finally, Chapter 6






7


concludes the thesis with a summary of our accomplishments as well as issues to be

considered by future research projects.















CHAPTER 2
RELATED RESEARCH

In this chapter, we introduce the related research topics of our semantic analyzer.

We have combined and used various techniques from different research areas to produce

a novel methodology for extracting semantic information from legacy information

sources.

The research areas mainly related with our semantic analyzer are code reverse

engineering, parser generation, design patterns, business rule extraction, and state-of-

the-art knowledge extraction techniques like program slicing and pattern matching. We

not only base our work on these research areas, but also use state-of-the-art tools that are

outcomes of these research areas as well. We introduce these research areas and tools in

the order they are used in the implementation of semantic analyzer component of SEEK

prototype. First, a code reverse engineering tool, Java decompiler, is introduced. Second,

a parser generator tool, Java Compiler Compiler (JavaCC), is introduced. Introduction of

the Java Tree Builder (JTB) tool, which is highly related with JavaCC, follows this

section. Next, the Visitor Design Pattern, which has an important role in the structure of

our approach, is introduced. The Section about lexical and syntactic analysis, control

flow graph, program slicing and pattern matching techniques that are use in extracting

semantic information follows. Last, we introduce the concept of business rules and the

possible locations that they could be found in an information system.









2.1 Code Reverse Engineering

Source code is the input to our semantic analyzer. This is useful in situations where

source code is misplaced or we can not be sure which source code was used to produce

the running code in the legacy system. In such a case, we need a way to translate the

running code back into source code by using code reverse engineering techniques. This

section introduces the decompiler concept and the tool that we use to get .java source

code files from .class files.

2.1.1 What is a Decompiler?

A compiler translates source code into machine code which the computer can

interpret as actions or steps that the programmer wants it to perform

In this translation process, a lexical analyzer tokenizes the source code. The

tokens are then passed to the language parser which matches one or more tokens to a

series of rules and translates these tokens into intermediate code or into machine code.

Any source code that does not match a compiler's rules is rejected.

Most compilers perform much pre- and post-processing. The pre-processor

prepares the source code for the lexical analysis by omitting all unnecessary information,

such as the programmer's comments and adding in any standard or included header files

or packages. A typical post-processor stage is code optimization, where the compiler

parses or scans the code, reorders it, and removes any redundancies to increase the

efficiency and speed of the code.


1 "Decompiling Java" Book by Godfrey Nolan, McGraw-Hill, 1998, 358 pages.









A decompiler translates the machine code or intermediate code back into source

code. This transformation rarely results in original source code because of the pre- and

post-processing stages.

2.1.2 History of Decompilers

The earliest example of a decompiler was written for the Algol-like language

Neliac ("Navy Electronics Laboratory International ALGOL Compiler") in 1960. Its

primary function was to convert non-Neliac compiled programs into Neliac compatible

binaries. The first real Java decompiler was written at IBM by Daniel Ford2. Mocha, the

most famous Java decompiler was written by Hanpeter Van Vliet3

2.1.3 Why Successful Decompiling is Possible in Java

Decompiling Java code requires a deep understanding of the Java byte code and the

Java Virtual Machine (JVM) The current design of the Java Virtual Machine is

independent of the Java Development Kit or JDK. It means that the language may change

but the JVM specification is fixed. Decompilation can be done because the JVM is a

simple stack machine with no registers and a limited number of high-level instructions or

byte codes, making it easy to understand. The JVM requires the compiler to pass on

much information such as variable and method names, which would otherwise not be

available. The JVM's restricted execution environment and straightforward architecture

as well as the high-level nature of many of its instructions help decompilers.







2 Ford D, 'Jive: A Java Decompiler', at IBM, May 1996.

3 Hanpeter V, CINet article on August 23, 1996.









Adding a new method in C++ means that all classes that reference that class need to

be recompiled. This is known as the fragile superclass problem4. Java gets around this

problem by putting all the necessary symbolic information into the class file. The JVM

then takes care of all the linking and final name resolution, loading all the required

classes including any externally referenced fields and methods on the fly. This delayed

linking or dynamic loading, possibly more than anything else, is why Java is so amenable

decompilation.

2.1.4 Purpose of Decompilation

Decompilation is often used for retrieving lost source code, learning Java,

understanding someone's algorithms or techniques, fixing and debugging class-files, and

pretty printing. Our reason for Java decompilation is to get the .java source code from our

own .class files, when we are not sure about whether .java source code files have the

latest functionality of the legacy system.

2.1.5 Examples of Decompilers

There are several examples for decompilers. Here, we briefly introduce the first

Java decompiler, Mocha, as well as the Jad decompiler that we have used in our project

to decompile class files.

2.1.5.1 Mocha

Mocha is the first publicly available decompiler which was written by Hanpeter

Van Vliet. He also wrote an obfuscator5 called Crema that attempted to protect Java

source code. The source code for both Crema and Mocha were sold to Borland. After

4 Definition of the Fragile Superclass Problem can be found in the white paper "The Java Language
Environment" by James Gosling and Henry McGilton, May 1996.

5 An Obfuscator removes all clues that might have given by programmer when naming variables, methods,
and parameters by altering the names into unintelligible names or even into control characters.









that, Borland released JBuilder with a built in obfuscator. Borland claims that JBuilder's

obfuscator safeguards Java code from decompilation by replacing ASCII variable names

with control characters. JBuilder comes with an API decompiler, which shows the public

methods and their parameters. The same thing can be achieved using thejavap6 command

in JDK.

2.1.5.2 Jad

Jad is the decompiler that we selected from among a number of decompilers because of
its features [4]:
* Jad is a 100% pure C++ program and it works several times faster than other
decompilers written in Java.
* Jad does not use the Java runtime for its functioning; therefore no special setup,
like changes to the classpath variable, is required.
* Jad gives full support for inner and anonymous classes.
* Jad automatically converts identifiers garbled by Java obfuscators into valid ones.
* Jad is free for non-commercial use.

Jad can be used for the following reasons:
* For recovering lost source codes;
* For exploring the sources of Java runtime libraries;
* As a Java dis-assembler;
* As a Java source code cleaner and beautifier.

Like every decompiler, Jad has some limitations. While decompiling classes which
contain inner classes, Jad cannot reliably sort out the extra arguments added to class
constructors by Java compiler. Currently Jad makes no use of the Java class hierarchy
information. Consequently, Jad always choosesjava.lang.Object as a common super
class of two different classes and inserts auxiliary casts where necessary.
2.2 Parser Generation

For programmers, writing a parser for a grammar has always been an error-prone

task. Especially when we deal with a grammar like Java that has so many productions, it

is also a time-consuming task to get a parser for that grammar. Therefore, there has been

a lot of research on automatically generating a compiler from a formal specification of a


6 javap: Java profiler outputs ASCII representations of a class file's byte code









programming language. Our focus in this thesis is extracting valuable information from

legacy source code. For this reason, we choose to use one of this state-of-the-art parser

generation tools to get our Java and SQL parsers, instead of writing our parsers from

scratch. In this section, Java Compiler Compiler (JavaCC) tool, which is used to generate

our parsers, is introduced.

2.2.1 Compiler-Compiler Tools

Research on automatic generation of compiler from a formal specification of a

programming language brought us so-called compiler-compiler tools such as Yacc,

Bison, ANTLR, and JavaCC. These tools play a key role in the software development

process of compilers and have made their construction much easier.

Some of these well-known compiler-compiler tools are:

* Lex & Yacc: Lex builds lexical analyzers from regular expressions. Yacc converts
a grammar specification into a table-driven compiler that could produce code when
it had successfully parsed productions from that grammar.

* Flex & Bison: They are Free Software Foundation's GNU project produced
improved versions of lex and yacc for use on platforms that did not run a derivative
of the Unix operating system.

* DFA and ANTLR (Components of PCCTS7): They provide the same functions as
Lex and Yacc. However, the grammars that ANTLR accepts are LL(k) grammars
as opposed to the LALR grammars used by Yacc.

2.2.2 JavaCC and its Features

JavaCC (Java Compiler Compiler) is the most popular parser generator for use with

Java applications [5]. It is a tool that reads a grammar specification and converts it to a

Java program that can recognize matches to the grammar according to that specification.


PCCTS: The Purdue Compiler Construction Tool Set was developed at Purdue University.









JavaCC was first released by Sun with the name JACK. The latest version was

released by Metamata Inc. WebGain8 was the caretaker company of it for a while.

Currently, JavaCC can be obtained from Sun Microsystem's Web site9

In addition to the parser generator itself, JavaCC provides other standard

capabilities related to parser generation such as tree building (via a tool called JJTree),

actions, debugging, etc. JavaCC does not have any runtime libraries (such as JAR files).

The only files that are needed for the parser are those generated by JavaCC.

The parser, which is generated by JavaCC, is a top-down LL(1) parser10 with a

variable amount of look-ahead. JavaCC gives the ability to define LL(k11) grammars as

well. Lexical specifications can define tokens not to be case sensitive either at the global

level for the entire lexical specification or on an individual lexical specification basis.

The lexical analyzer of the JavaCC-generated parser has a feature for keeping

comments when they are defined as special tokens. Special tokens are ignored during

parsing, but these tokens are available (unlike skipped items, such as white spaces) for

processing by the tools. In our implementation, we used this feature to gather comments

associated with business rules and methods. Figure 2-1 below illustrates how special

tokens are handled in a JavaCC parser. In Figure 2-1, S1, S2, and S3 devote special

tokens, while Tl, T2, and T3 devote the real tokens. If there were not a feature for

keeping special tokens, S1, S2, and S3 would be skipped during parsing the code. As

shown in Figure 2-1, Token class has a specialToken member to point the special token

8 hllp \\ .webgain.com

9 http://javacc.dev.java.net/

10 Definitions of basic compiler terms can be found in Appendix B

1 k: number of look-ahead.











that resides just before itself inside the code. T2 token, which is "class", has two special

tokens (comments) (S l: "open to public and S2: "* special token */ ) that are

connected to its specialToken pointer. The left-hand side of Figure 2-1, is the figurative

representation of the code that is on the right-hand side.

Class Token{
Int kind;
--- next ---- next ---- String Image;
T ---------------- T2 ----------------> T3 .. Token next;
--- --- --- Token specialToken;}

--- next ---- / ---- public /open to public
S1 -- S2 <- S3 <- /* special token*/ class /*this is a sample*/ Samplel{
-- --- public Samplel() {}

.next
---- S1 : open to public
S2 : special token
.specialToken S3 : this is a sample
<---- T : public
T2 : class
T3: Samplel

Figure 2-1 Special tokens in JavaCC



As shown in Figure 2-2, JavaCC processes specification file (.jj extension) and

output the Java files that has the code of the parser that can process the languages that are

according to the grammar in the specification file. Parser Java files are both listed in

Figure 2-2 and their functionality is described in Section 4.3.


Parser Java Files
-ParserName.java
-ParserNameConstants.java
Grammar -ParserNameTokenManager.java
Specification 10 JavaCC -ParseException.java __ Java
.jj file -SimpleCharStream.java Compiler
-ParserNameTokenManager
-Token.java
-TokenMgrError.java


Figure 2-2 Input and output of JavaCC










Once the parser code is generated, it is compiled with the Java compiler (javac) to

get the parser. The outcome code is used to parse the desired grammar, see Figure 2-3.

Parser Java Files Java Compiler Parser Class Files ava ParserName FileName Abstract Syntax Tree
avac ParserName.java AST
AST

Figure 2-3 Compiling the Parser Generated by JavaCC and Using It to Get AST.

2.2.3 The Grammar Specification File of JavaCC

There are three major components in the grammar specification file.

* Definitions of terminal tokens (or terminals), e.g., words that are expected in the
input.
* Definitions ofproduction rules (or productions), e.g., rules about how tokens
combine to form legal statements in the language.
* Java code to tie everything together and perform actions when certain productions
occur.

Grammar specification files12 for some grammars such as Java, C ++, C, SQL,

XML, HTML, Visual Basic, and XQuery can be found at the JavaCC grammar repository

Web site at UCLA [6].

2.2.4 Java Tree Builder (JTB)

In this subsection Java Tree Builder tool is introduced. We build our semantic

analyzer structure according to the visitor pattern technique. Rationale behind the usage

of visitor patterns is explained in the following section and in Chapter 3. JTB essentially

takes a grammar specification file as an input and changes this specification file so that

JavaCC can use this specification file to generate parsers according to visitor pattern

structure. JTB, written at Purdue University, is used with the JavaCC parser generator

tool [7]. It takes a plain JavaCC grammar file as input and automatically generates the

following:


12 An example of a grammar specification file can be found in Appendix A









* A JavaCC grammar with the proper annotations building the syntax tree during
parsing. (The file jtb.out.jj)
* A set of syntax tree classes based on the productions in the grammar, utilizing the
Visitor design pattern. (Files in syntaxtree directory/package)
* Visitor and ObjectVisitor interface, DepthFit 'ifirTit,,r and ObjectDepthFirst
visitors (Files in visitor directory/package)

The inputs and outputs of JTB are shown in Figure 2-4. The syntaxtree and visitor

package outputs (Figure 2-4) are explained in the following paragraphs.


EBNF
EBNF Grammar with
EBNF Ebd Java
grammar JTB Tool Embedded Jv
grammar JTB Tool Java Code Compiler
(jtb.out.jj file) Compiler
JavaCC

Syntax Tree Node Classes
(in syntaxtree package)


Default Visitors and
Interfaces
(in visitor package)

Figure 2-4: Inputs and Outputs of JTB Tool.

The syntaxtree directory/package contains syntax tree node classes generated

based on the production rules in JavaCC grammar. Each production has its own class.

Syntax directory also contains eight special node classes like "Node", "NodeChoice",

"NodeOptional", etc. Table 2-1 below specifies a list of these special nodes.

Table 2-1 Automatically generated tree node interface and classes
Node Node interface that all tree nodes implement.
NodeListInterface List interface that NodeList, NodeListOptional, and
NodeSeqeunce implement.
NodeChoice Represents a grammar choice such as (A | B)
NodeList Represents a list such as ( A)+
NodeListOptional Represents an optional list such as (A)*
NodeOptional Represents an optional such as [ A ] or ( A)?
NodeSequence Represents a nested sequence of nodes
NodeToken Represents a token string such as "package"










The generated classes include accept methods with the visitor interface as a formal

parameter. This parameter is used to pass the name of the class back to the visitor through

dynamic binding. Each accept method takes a visitor as an actual parameter and invokes

the visit method of that visitor having the node class as an actual parameter to determine

the appropriate visit method. [8]

Separating the generated tree node classes into their own package greatly simplifies

file organization. When the grammar is stable and not subject to change, once these

classes are generated and compiled, it is not necessary to deal with them again. All of the

changes and additions are done to the visitor classes when a new functionality is

introduced or an existing functionality is changed.

The visitor directory/package contains the visitor interfaces, visitor and

ObjectVisi tor, and their default implementations, DepthFirs tVisi tor and

ObjectDepthFirst. 13

The Visitor interface contains one visit method declaration per production in the

grammar, plus one visit method declaration for each of the automatically generated

special node classes. The default visitor, Depl/hFiil \irrinr, class implements the visitor

interface and it simply visits each node of the tree. The JTB puts the navigation control

into the visit methods of the Visitor [9]. JTB generates default navigation behavior in the

implementation of the default visitor, DeplihFil \T \ilr or ObjectDepthFirst. A visitor

that wants to use this route to process operations on specific nodes of tree extends the

default visitor and overrides the method related to those specific nodes14


13 An example of visitor class implementation can be seen in Appendix D.

14 An example of a visitor class can be found in the Appendix D.









Operations on abstract syntax trees can then be defined separately from the abstract

syntax classes in visitor classes that rely on the generated accept methods. The separation

of operation and structure is crucial in this class of tools to avoid editing and recompiling

generated code [9].

2.3 Visitor Design Pattern

Our goal is to build semantic information extraction techniques that can be applied

to any source code and can be extended with new algorithms. Visitor design pattern is the

key object oriented technique to reach this goal. In this section, we introduce the Visitor

Design Pattern and its features.

2.3.1 Design Patterns

Design Patterns [10] are general solutions to design problem occurring repeatedly

in many projects. The Design Patterns can be listed in three categories:

* Creational Patterns: Abstract Factory, Builder, Factory Method, Prototype, and
Singleton.
* Structural Pattern: Adapter, Bridge, Composite, Decorator, Flyweight, and
Proxy.
* Behavioral Patterns: Chain of Responsibility, Command, Interpreter, Iterator,
Mediator, Memento, Observer, State, Strategy, Template Method, and Visitor.

2.3.2 Features of Visitor Design Pattern

A Visitor design pattern is a behavioral pattern which is used to encapsulate the

functionality that is desired to be performed on the elements of a data structure. It gives

the flexibility to change the operation being performed on a structure without the need to

change the classes of the elements on which the operation is performed. Visitors make it

easy to add operations. New operations over the object structure can be defined simply by

adding a new visitor. In contrast, if the functionality is spread over many classes, each









class must be changed to define a new operation15. The idea behind a visitor pattern is to

insert an accept method in each class. The accept method passes control back to the

visitor which acts as a repository for the new methods16. Visitor classes localize related

behavior in the same visitor and unrelated sets of behavior are partitioned in their own

visitor subclasses.

Using visitor patterns, each new operation can be added separately and the member

classes are independent of the operations that apply to them. If the classes defining the

object structure rarely change, but new operations over the structure are often defined, a

visitor design pattern is the perfect choice. Since object structure classes do not change,

we do not need to recompile them when new functionality is added.

2.3.3 Analogy for Visitor Pattern

It is often difficult to understand design patterns. To explain concepts like design

patterns, analogies from real life are useful. To increase the reader's understanding of

visitor pattern, we introduce the following analogy.

Let us suppose that our concrete, invariant structure is the digestive system of

human-body and our visitor is a computerized pill. Let us further assume, we would like

to get information from our digestive system by using the pill as an information carrier.

When the pill is swallowed, it visits the organs of our digestive system and sends

information about those organs to the outside world. In this way, no surgery is needed to

put devices inside each organ to send information to the outside world. The pill sends

information about the organs while it is traversing through the digestive system. The

15 Comparison of possible approaches (Instanceof and Type Casts, Dedicated Methods and The Visitor
Pattern) for performing operations on node objects in a heterogeneous aggregate structure are discussed in
detail in [5].
16 An example of a visitor pattern implementation can be found in Appendix D.








information that is send is processed in the outside world. Figure 2-5 may help you to

imagine this analogy.



)





A-





A B
Figure 2-5 Analogy for visitor pattern. A) Human digestive system (Concrete structure)
B) Pill (Visitor Structure).

2.3.4 Double Dispatching in Visitor Patterns

The visitor pattern mechanism provides double dispatching for the selection of the

functionality that will be performed on a specific node. This means that the call made to

the method that inherits the functionality for a specific node depends both upon the type

of the visitor and of the data structure of the node. This is achieved as follows: Each node

in the data structure has an accept method that deals with the abstract visitor. When a

node accepts a visitor, it makes a call to the visitor which includes the node's class. The

visitor will then execute its algorithm for that element. The double dispatching technique

completely replaces the need for conditional statements.









2.4 State-of-the-art in Extracting Knowledge from Application Code

In this section, we introduce several techniques for extracting information from

source code. The problem of extracting knowledge from application code has been

investigated in several research areas such as lexical and syntactic analysis, control flow

analysis, program slicing, and pattern matching. These areas are described in the previous

work about semantic analysis applied to SEEK project [2]. We briefly describe these

techniques, since they are used by our semantic analysis approach.

2.4.1 Lexical and Syntactic Analysis

Analysis of source code requires conversion to a form that can easily be processed

by a program. An abstract Syntax Tree (AST) is a type of representation of source code

that facilitates the usage of tree traversal algorithms. Lexical and syntactic analysis of a

source code, in accordance to the context free grammar of the underlying language,

generates an AST. Grammars themselves are described in a stylized notation called

Backus-Naur Form [11] in which the program parts are defined by rules and in terms of

their constituents. An AST is used to show how a natural language sentence is broken up

into its constituents. The parser that is generated by JavaCC produces AST of a source

code. After the AST is produced, it is ready to be analyzed by visitor patterns.

2.4.2 Control Flow Analysis

After we obtain the AST, it is used for Control Flow Analysis [12]. There are two

major types of CFA; Inter-procedural and Intra-procedural analysis. Inter-procedural

analysis determines the calling relationship among program units while intra-procedural

analysis determines the order in which statements are executed within these program

units. Together they construct a Control Flow Graph (CFG). In our approach we









construct the CFG and use the calling relationships on CFG between methods to traverse

between classes.

2.4.3 Program Slicing

Program slicing was introduced by Weiser [13] and has supported various program

comprehension techniques. Weiser defines the slice of a program for a particular variable

at a particular line in the source code as "that part of the code that is responsible for

giving a value to the variable at that point in the code". The idea behind slicing is to

retrieve the code segment that has a direct impact on variables of interest. Starting at a

given point in the program, program slicing automatically retrieves all relevant code

statements containing control and/or data flow dependencies.

2.4.4 Pattern Matching

Pattern matching identifies interesting code patterns and their dependencies. For

example, conditional control structures such as if ithr ele or case statements may

encode business knowledge, whereas data type declarations and class or structure

definitions can provide valuable information about the names, data types, and structure of

concepts represented in an underlying database. A code pattern recognizer performs the

matching of patterns from the templates against patterns in the source code.

2.5 Business Rules Extraction

In this last section of Chapter 2, we investigate the research on business rules.

Extracting business rules embedded in information systems is an important issue in

understanding the functionality of the information system. Before attempting to solve the

problem of extracting business rules, we define what a business rule is, what kinds of

business rules typically exist, and how they are encoded in the information systems.









2.5.1 Business Rules

Business rules represent core business practices and policies, and they determine

what is possible or desirable in running a business [14]. A well-known definition states

that: "A business rule is a statement that defines or constrains some aspect of the

business. It is intended to assert business structure or to control or influence the behavior

of the business [15]. "

2.5.2 Categories of Business Rules

Business rule may be implemented differently in different parts of a system and

require different techniques to extract them. For this reason, it is beneficial to know the

categories of business rules and how they could be implemented in an information

system. For example [14], [15] provide two possible ways to categorize business rules.

Using the approach suggested in [14], we can distinguish the following classes of

business rules:

1. Structural business rules: Structural business rules are statements about the

data objects belonging to an organization. Structural business rules can be further divided

into following categories:

* Definitions
Example: Anyone placing an order i/ih us is a customer.
* Relations between objects
Example: Customers are identified by their address, postcode, and contact.
* Derivation statements
Example: The total cost of the rental is calculated from the sum of insurance amount and
rental amount.

2. Behavioral business rules: Behavioral business rules are statements about

dynamic aspects of a business. They specify what can or will be done to data objects in

response to events. The actions taken in response to the events may result in a state

change for the data objects affected by the business rules.









Example: When an insurance claim is made, a claim reference number is allocated.

3. Constraint business rules: Constraint business rules are statements that bring

limitations on the operation of the business rules. Constraint business rules define the

conditions under which a business can operate.

Example: A customer must have at least one account, but no more than three.

2.5.3 Where Are Business Rules Implemented in Information Systems

Categories of business rules that are stated in the previous section can be

implemented in various parts of an information system. It is beneficial to identify what

we are looking for before we look for it. If we know what kind of business rule we can

find in the subparts of the information system, then we can construct our search

algorithms according to the category of the business rule for which we are looking.

Therefore, we define which business rule categories could be implemented in which part

of the information system.

Structural business rules: Definitions which are also a part of structural business

rules are trying to be supported by the ontology. Relations which are also structural

business rules are generally defined by the data model and implemented in the schema.

Derivation business rules are implemented as program code.

Behavioral business rules: Behavioral business rules often implement more

complex business logic than can be defined through a data model, and they are usually

implemented as procedural programs.

Constraint business rules: Constraint business rules may be implemented in

various parts of an information system. In older systems, constraint business rules tend to

be implemented as program code. In newer systems, they are also implemented in the

schema.









2.5.4 Extracting Business Rules

The aim of extracting business rules is to understand the functionality of

information system. There are mainly four inputs to our methodology for business rule

extraction. These are:

* Schema: It is the main input for data understanding, and it provides structural and
some constraint information about data.
* Data: The data stored in a database may also be examined for data understanding
purposes. This is because data may contain certain properties that are not specified
in the schema. Also business rules that were extracted from data can be used to
verify the business rules that were extracted from other inputs (namely, schema or
programs).
* Programs: Program code associated with a database system is another type of
input for data understanding. A database system may include application programs,
stored procedures, or user interface forms. These programs contain clues about data
structures and constraints. These clues, when used in conjunction with schema/data,
could potentially increase data understanding.
* Transactions: Operations are recorded in a transaction log in a database system. A
transaction log may be used as an input for data understanding. The sequence of
operations on a database, and the relationship among operations that take place in
one transaction, can be beneficial to understand the functionality of the information
system.

2.5.5 Importance of Business Rule Extraction from Program Code

Over time, business rules evolve and the software that encodes them is also

changed and maintained. As the information system becomes large and ages, the changes

in business functionality are reflected in program code, without changing the

corresponding documentation, or without changing any other part of the information

system. Thus, the business organization often trusts the code more than any other

documents. Therefore, extracting business rules from program code becomes more

important for a better understanding of the legacy information systems. Information

gathered from the business rules inside the program code are then used to semantically

enhance the schema of the information system.















CHAPTER 3
SEMANTIC ANALYSIS ALGORITHM

3.1 Introduction

A conceptual overview of the SEEK knowledge extraction architecture is shown in

Figure 3-1 [1]. SEEK applies Data Reverse Engineering (DRE) and Schema Matching

(SM) processes to legacy database(s), to produce a source wrapper for a legacy source.

This source wrapper will be used by another component (not shown in Figure 3-1) to

communicate and exchange information with the legacy source. It is assumed that the

legacy source uses a database management system for storing and managing its enterprise

data or knowledge.


Application

Domain Domain
Model Ontology


Legacy Source II

Figure 3-1 High-level view of the SEEK Architecture.









First, SEEK generates a detailed description of the legacy source by extracting

enterprise knowledge from it. The extracted enterprise knowledge forms a knowledge

base that serves as the input for subsequent steps. In particular, the DRE module shown

in Figure 3-1 connects to the underlying DBMS to extract schema information (most data

sources support at least some form of Call-Level Interface such as JDBC). The schema

information from the database is semantically enhanced using clues extracted by the

semantic analyzer from available application code, business reports and, in the future,

perhaps other electronically available information that could encode business data such as

e-mail correspondence, corporate memos, etc. It has been the experience, through visits

with representatives from the construction and manufacturing domains, that such

application code exists and can be made available electronically [1].

Second, the semantically enhanced legacy source schema must be mapped into the

domain model (DM) used by the applications) that wants) to access the legacy source.

This is done using a schema mapping process that produces the mapping rules between

the legacy source schema and the application domain model. In addition to the domain

model, the schema matcher also needs access to the domain ontology (DO) that describes

the domain model. Finally, the extracted legacy schema and the mapping rules provide

the input to the wrapper generator (not shown), which produces the source wrapper.

The three preceding steps can be formalized as follows [1]. At a high level, let a

legacy source L be denoted by the tuple L = (DBL, SL, DL, QL), where DBL denotes the

legacy database, SL denotes its schema, DL the data, and QL a set of queries that can be

answered by DBL. Note, the legacy database need not be a relational database, but can









include text, flat file databases, or hierarchically formatted information. SL is expressed

by the data model DML.

We also define an application via the tuple A = (SA, QA, DA), where SA denotes

the schema used by the application and QA denotes a collection of queries written against

that schema. The symbol DA denotes data that is expressed in the context of the

application. We assume that the application schema is described by a domain model and

its corresponding ontology (as shown in Figure 3-1). For simplicity, we further assume

that the application query format is specific to a given application domain but invariant

across legacy sources for that domain. Let a legacy source wrapper W be comprised of a

query transformation (3-1) and a data transformation (3-2) where the Q and D are

constrained by the corresponding schemas.

fWQ A QL (3-1)
fD : DL -DA (3-2)

The SEEK knowledge extraction process shown in Figure 3-1 can now be stated as

follows. Given SA and QA for an application that attempts to access legacy database

DBL whose schema SL is unknown, and assuming that we have access to the legacy

database DBL as well as to application code CL that accesses DBL, we first infer SL by

analyzing DBL and CL, then use SL to infer a set of mapping rules M between SL and

SA, are used by a wrapper generator WGen to produce (fwQ,fwD). In short:

DRE: (DBL, CL) SL (3-3)
SM : (SL, SA) M (3-4)
WGen: (QA, M) (fwQ,wD) (3-5)









Thus, the DRE algorithm (3-1) is comprised of schema extraction (SE) and

semantic analysis (SA). This thesis concentrates on the semantic analysis process by

analyzing application code CL to provide vital clues for inferring SL. The

implementation and experimental evaluation of the DRE algorithm have been described

in detail in [1]. The following section focuses on the semantic analyzer approach.

3.2 Objective of Semantic Analysis

The main purpose of semantic analysis is to understand the meaning of database

repository. In the process of semantic analysis, we extract information that can be used to

enhance the schema of the legacy source (SL). This SL will then be used to produce

mapping rules between SL and the applications (SA) that want to access the legacy

source. Our input to the semantic analysis process can be any kind of code (CL) that

inherits functionality that operates on the legacy database (DBL). This code can be

application code, as well as triggers or stored procedures inside the corresponding

database. Our current prototype works on application code and extracts semantics out of

that by using state-of-the-art techniques in code reverse engineering, abstract syntax tree

generation and object oriented programming. Our prototype is easily extensible to

analyze any programming language, trigger codes, and stored-procedure code that exist

inside legacy databases.

Our current semantic analyzer is configured to extract information from Java code.

We choose the Java programming language because it is becoming the dominating

programming language in the enterprise information systems. Also, Java promises to be

the programming language that inherits semantics of future legacy systems. In the next









section you will find detailed explanation of the main components of our Java semantic

analyzer.

3.3 Components of the Semantic Analyzer

The semantic analyzer (Figure 3-2) has three main components.

* Decompiler,
* Abstract syntax tree generator
* Information extractor.

Let us give a detailed description of the techniques and rationale used to form each

of these components.


Abstract
Java File A Syntax Information

Class File De-compiler Tree Extractor
Generator


Figure 3-2 Semantic Analyzer Components.

3.3.1 Decompiler

Legacy information systems often have poor or outdate documentation. Application

code is changed over time and documentation becomes inconsistent with the functionality

of the code. In such a case, the most reliable source of semantic information of the legacy

system becomes the application source code. There can be situations where source code

could be misplaced, or the versions of source code could be disorganized. In that case, we

can not be sure as to which source code used to produce the running code on the legacy

system and which source code was has the latest functionality of the legacy system. In

this situation, the only reliable information source may be the running application, .class

files. We can recover Java source code (Java) files by the decompiler component of

semantic analyzer. As it is illustrated in Figure 3-2, using decompiler is optional. If we










are sure that .java files reflect the latest functionality of the legacy system, we can skip

the decompiler stage.

How can we be sure that the original source code and the de-compiled source code

are the same? There is a way to test this. We can recompile the .java file of decompiled

.class file with "javac" and check if the sizes of the original class file and the recompiled

class files are the same. The approximation of the length of the sizes of these two files

will give us a clue about how the decompiling process is successful. The Figure 3-3

illustrates this test.



Class File
found and
copied

Class File Check whether they are equal in size or not? Recompiled
Directory Class File
Directory
JAD
decompiler
de-omiller Decompiled javac
Class Decompiler I Java File Class Recompiler
Directory

Figure 3-3 Checking the success of decompiling process.

3.3.2 Abstract Syntax Tree Generator

Our second component is the abstract syntax tree generator. The essence of the

abstract syntax tree (AST) in program comprehension is introduced in Chapter 2. We use

JavaCC tool to automatically generate AST generator programs. Detail description of

JavaCC tool and the idea behind using this tool is given in Chapter 2. The AST generator

parserr) that is produced by JavaCC was tested over thousands ofj ava program code.

This makes our AST generation process robust and error-free.









3.3.3 Information Extractor

The information extractor component, which is shown in Figure 3-2, is composed

of several visitor classes. These visitor classes traverse on the AST of the application

code to extract the desired information. A visitor pattern lets programmer to encapsulate

related behavior in the same visitor and separate the unrelated ones into other visitors.

Our information extractor contains visitor patterns to extract variable information, to

identify the potential value of variables, to extract the flow of program code, to extract

the business rules, to extract the comments inside the code, to extract the SQL statements,

and to write the AST in an XML file. If we need any new operation over the object

structure, it can be defined simply by adding a new visitor. Detailed descriptions and

implementations of visitor patterns are explained in Chapter 2 and Chapter 4.

There are two main steps in the algorithm that extract semantic information. In the

first step, control flow graph (CFG) is extracted, declaration information of each variable

and method are written into symbol table and AST of the program code is written into an

XML file. In the second step, we identify the slicing variables and get the business rules,

comments, SQL statement, and relate meanings of the variables with the table columns.

These steps are illustrated in Figure 3-4 and are explained in detail in Section 4.4.

Prepare Classes: Analyze Methods:
AST Form Symbol Table Symbol Table Extract Slicing Variable Semantic
SForm Control Flow Graph Extract Business Rules and Comments Info
CFG Process SQL statements

Figure 3-4 Two main steps of Information Extraction.

In the first step, information about all variables is gathered and the AST of each

method is saved. In the second step, we do not analyze the class as whole but we analyze









only the methods in the class that are used by method calls. By this approach, we save

work and improve performance.

3.4 Extensibility of the Semantic Analyzer

The objective of semantic analysis is to develop techniques for extracting

information from legacy systems. The input of the semantic analysis process can be a

trigger code, a stored procedure, or a java code. More generally, the input can be any

code that expresses semantic information about the legacy source on which it operates.

For this reason our techniques in semantic analysis should be extensible to any

programming language platform.

Extensibility of the semantic analyzer is achieved because JavaCC provides an

AST generator that can easily be plugged in and out. Abstraction of AST generator from

the information extractor increases the extensibility of semantic analyzer. If the

functionality of information extraction and AST generation are fully separated from each

other, then the extensibility of semantic analyzer to other languages will be much easier.

This separation of functionality of these two components is supported by visitor patterns.

Visitor patterns provide the flexibility to change the operation being performed on a

structure without the need for changing the classes of the elements on which the

operation is performed. By using visitor patterns, we do not embed the functionality of

the information extraction inside the classes of AST generator. This separation lets us to

focus on the information extraction algorithms regardless of the programming language

that is being analyzed. To get a structure for Visitor pattern usage we use the JTB tool [7]

to augment our structure to be used by visitor patterns. A detailed description and

implementation of JTB is given in Chapter 2 and Chapter 4.









3.5 Extracting Semantics from Multiple Files

The current version of the SA prototype can extract semantics from multiple class

files by starting from an initial driver program file and analyzing all program files in the

control flow graph. The functionality of typical enterprise applications spreads over

multiple files. Therefore, one must extract semantics from multiple files and combine

them for a better understanding of legacy source.

Figure 3-5 gives an example of how functionality could be separated into different

files. In this example, we start from the main method of Class] source file. Inside the

main method, method of Class2 class is invoked. This means, we need to examine

method of Class2. To examine it, our File Finder finds the location of the source code

file of Class2. Whenever a method is invoked on another class, this class source file is

found and process continues from this class file.

As we have mentioned before, there are two main steps in information extraction.

In the first step, we find all the class files that will be analyzed and prepare the control

flow graph by finding out inter- and intra-procedural relationships. In the second step, we

analyze the methods in the order they are called starting from the main method of the

driver class. These steps are explained in detail in Section 4.4.

It can be readily observed in Figure 3-5 that all the methods of a class file may not

be used. For this reason, our information extractor only analyzes the methods that are

used in the control flow. In the example Figure 3-5, we do not analyze method] of

Class], method] of Class2, and method of Class3. Analyzing the code, method by

method, helps us to improve not only the temporal performance of semantic analyzer, but

also its correctness. Unused code (methods) inside classes may lead to incorrect,

misleading information.






































Figure 3-5 Traversing between class files

3.6 Finding the Class Source Code Files

The Semantic Analyzer follows the same logic as the Java Virtual Machine (JVM)

to find a class source code file. When we run a Java application, the JVM first searches

for the class that was given as a parameter. JVM searches for this class file in the

directories that are stated in the environment variable ClassPath. When JVM finds the

class file, it starts executing it from its main method. When a method is invoked on an

instance of a class, JVM continues its execution inside that method of the specified class.

JVM finds this class by using both the ClassPath information and package import

information of the class that is currently being executed.









The File Finder module of the SA imitates the same logic to find the files that is

analyzed. File Finder module first gets the ClassPath information. As we traverse

through the classes, the current class's package/class import information is given to the

File Finder. When a new class file is searched, File Finder uses both ClassPath and

import information to find the location of the searched file. As it is illustrated in Figure 3-

6, ClassPath information is initially given to File Finder module. While we traverse

between classes, each class package and import information is feed backed to the File

Finder. When a class is to be analyzed, its name is given to File Finder and its source

code file location is found by the File Finder. File Finder can correctly find the location

even if it is inside a compressedjar or zip file.

CLASSPATH-
Package Location
Import Info File of File
Finder -- --
File Name
to Search

Figure 3-6 File Finder

3.6 Slicing Variables

The semantic analysis algorithm is based on several observations based on the

general nature of legacy application code. Database application code always has

embedded queries. The data retrieved or manipulated by queries is displayed to the end

user. Both the queries and the output statements contain rich semantic information [2].

The SEEK SA aims at augmenting entities and attributes in the database schema with

their application specific meanings. It is reasonable to state that the variables that appear

in input/output or on database statements should be traced throughout the application

code. We will call these variables slicing variables [2]. No matter how large the number









of slicing variables is, we can extract the semantics by a single pass through the AST. In

each input-output statement we check if the variable in the statement is a slicing variable

or not. If it is a slicing variable, we associate the meaning that was gathered thus far with

that slicing variable. The single pass does not cause any information loss because of the

data structure used, but it decreases the run-time complexity of the algorithm.

3.7 Heuristics Used

In this section, we describe the heuristics used in extracting information from

input/output statements.

Heuristicl: Application code generally has input-output statements that display the

results of queries executed on the underlying database.

Typically, output statements display one or more variables and/or contain one or

more format strings. A format string is defined as a sequence of alphanumeric characters

and escape characters within quotes. An escape character is a backlash character and

followed by a sequence of alphanumeric characters (e.g., \n, \t, \r etc), which in

combination indicate how to align and format the output.

System.out.println(" i Activity Name: \t"+ v);

In the example above, the string i" Activity Name: in the statement represents the

format string. The escape sequence specifies that the output should begin on a new

line.

Heuristic 2: The escape characters in format string do not include any semantic

meaning, so we can eliminate them. In the example below; '\n' and 't' have no semantic

meaning.

System.out.println(" i Activity Name: \t"+ v);









Heuristic 3: The set of slicing variables includes variables that appear in input,

output, or database statements. This is the set of variables that provide the maximum

semantic knowledge about the underlying legacy database.

Heuristic 4: The format string in an input-output statement describes the displayed

slicing variable that comes after this format string.

System.out.println(" i Activity Name: \t"+ v);

In the example above, the semantic of the variable v exists inside the format string

i" I Activity Name: \t".

Heuristic 5: The format string that contains semantic information and the variable

may not be in the same statement.

System.out.println(" I Activity Name: ");

System. out.print(v);

Let us refer to the first output statement with the format string as sl and the second

output statement that actually outputs the value of the variable as s2. Notice that, sl and

s2 can be separated by an arbitrary number of statements. The format string sl gives

clues about the application meaning of v in output s2.

Heuristic 6: There may be an arbitrary number of format strings in different

statements that inherits semantics, before we encounter an output of slicing variable.

Concatenation of the format strings before the slicing variable will give more clues about

the variable semantic.

System.out.println(" I Project: ");

System.out.println(" i Activity Name: ");

System. out.print(v);









In the example above, variable v is described by both n Project: and / Activity

Name: format strings. Let us call the first output statement with the format string as sl,

the second output statement with the format string as s2, and the second output statement

that actually outputs the value of the variable s3. Notice that, sl, s2, and s3 can be

separated by an arbitrary number of statements. In such a case, all the format string

should be concatenated to form the format string that gives clues about the application

meaning of v.

Heuristic 7: There may not be any output statement that has format string before

the output statement of variable. The semantic information of variable may be given

before the output statement of another statement. In the example below, the semantic of

variables vl, v2, and v3 are all inherited inside the format string of first output statement.

System.out.println(" i Project \t Activity \t Work Item");

System.out.print("\t" + vl);

System.out.print("\t" + v2);

System.out.print("\t" + v3);

A classic example of this situation in database application code is the set of

statements that display the results of a SELECT query in a matrix format. The matrix title

and the column headers contain important clues about the application specific meanings

of variables displayed in the individual columns of the matrix.



Heuristic 8: If a statement s assigns a value to variable v, and s retrieves a value of

a column c of table t from the result set of a query q, we can associate v's semantics with

column c of table t.









resultset] = s.executeQuery("Select number from Activ");

no = resultsetl.getString(1);

System. out.println("Activity no: + no);

In the example above, "no" variable is associated with the semantic "Activity no"

It is also associated with first column of the query which is "number ". So the column

"number" can be associated with the semantic "Activity no ".

Heuristic 9: If a variable is used in the where clause of a SQL statement, then this

variable's application meaning can be associated with the column in the where clause.

query = "SELECTactiv FROMActivity WHERE activ no = '"+input+ "';

S'IuhN.St = sqlStatement.executeQuery(query);

System. out.println("Activity no: + input);

The example above shows an example of how a variable can be used in the where

clause of a SELECT condition. In this example, the input variable's meaning can be

associated with the meaning of activ no column. This heuristic can be used for

UPDATE, DELETE, and INSERT conditions as well. The where clause of any SQL

statement can give clues of variable-column relations.

Heuristic 10: If a variable is used to set the value of a column in the UPDATE

SQL statement, then this variable's application meaning can be associated with that

column. In the example below, the application specific meaning of name variable can be

associated with the column active name.

updateSQL = "UPDATE Activity SET active name = '"+name+"' WHERE

active no='"+first + '",;

sqlStatement. execute Update(updateSQL);









Heuristic 11: Business logic is encoded either as assignment statements or

conditional statements like i then el.e, switch..case, etc. or a combination of them.

Mathematical formulae translate into assignment statements while decision logic

translates into conditional statements [2].

If slicing variable v is part of an assignment statement s then statement s represents

a business rule involving variable v. The assignment, in the below example, is a potential

business rule.

slicingVarl = varl + var2;

Heuristic 12: If slicing variable v appears in the condition expression of an

if /ith el7e or switch..case or any other conditional statement s, then s represents a

business rule involving variable v. In the example below, variable "NoOfPurchases" is a

slicing variable.

if (NoOfPurchases > 50) {

totalAmount = totalAmount 0.9;

}

Heuristic 13: Another source of information could be comments inside the code.

General policy of writing comment is to write them right before the statement with what

it is related. We assume that comments about business rules, if written, exist just before

the business rule. In example below, there is a comment right before the business rule.

//if number ofpurchases exceeds 50, make a 10% discount on the total prize

if (NoOfPurchases > 50) {

totalAmount = totalAmount 0.9;

}









Heuristic 14: If there is a comment about the functionality of a method, general

policy of writing this comment is to write it right before the method declaration. We

assume that comments about method functionality, if written, exist just before the method

declaration. In the example below, the comment about the method is placed right before

its declaration.

/**

Method: voidparseClassPath(

parses CLASSPA TH string and fills the classPart array

*/

public void parseClassPath(

{String tempPath = classPath;















CHAPTER 4
IMPLEMENTATION OF THE JAVA SEMANTIC ANALYZER

As illustrated in Figure 4-1, the Schema Extractor (SE) and Semantic Analyzer

(SA) are embedded inside the data reverse engineering (DRE) module of the SEEK

prototype. The SE connects to the underlying DBMS to extract schema information and

has been implemented by my previous colleague in SEEK [1],[2]. The schema

information from the database is semantically enhanced using clues extracted by the SA.

We have integrated the current Java SA code with the SE code as well, but we do not

describe the integration details herein. Instead, in this chapter, we focus on the

implementation details of the current Java SA prototype. Legacy application code is the

input of SA, whose output consists of semantic descriptions for the legacy source schema

extracted by DRE. In addition, SA elicits business rules describing some of the enterprise

knowledge that is implicitly embedded in the application code.


Srevise,validate
4


Data Reverse Engineering (RE)
Information

Legacy DB Schema Semantic Legacy
Extractor Analyzer
(SE) (SA) Application
Code
Embedded

QuFigure 4-1 Architectural overview of the SA prototype and related components.

Figure 4-1 Architectural overview of the SA prototype and related components.









The SA prototype is implemented using the Java SDK 1.4 from Sun Microsystems.

The Jad vl.5.8 decompiler is used to convert class files to Java source files. Java Tree

Builder (JTB) vl.2.2 and JavaCC vl.1 are used to generate Java and SQL parsers.

4.1 Package Structure

The SEEK prototype code is placed in the seek package. Like other module codes

in the SEEK prototype, the SA module code resides in the seek package. The code for the

SA, SE, and the analysis module (AM) reside in seek.sa, seek.se, and seek.am

respectively. This package structure helps us to separate the functionality of each module

from one another and to encapsulate similar functionality within the same package.

Java classes in the SA package are further divided into sub-packages according to

their functionality. These packages are: seekstructures, seekvisitors, syntaxtree, visitor,

and parsers and their content are described below:

The package seekstructures contains files that were written for analyzing the Java

code. The package seekvisitors contains visitor classes that were written to traverse the

abstract syntax tree of Java code and SQL statements. The package "syntaxtree" contains

classes that were created by JTB, and each class in this package corresponds to a non-

terminal in the production rules of Java and SQL grammars. The package "visitor"

contains JTB created base visitor classes. The package "parsers" contains Java and SQL

parser files. These package structures are shown in Figures 4.2 and 4.3. The classes inside

the packages syntaxtree, visitor, andparsers are automatically created by JTB and

JavaCC tools and augmented to fit into seek package structure. The classes inside the

packages seekstructures and seekvisitors are manually written classes to fulfill the goals

of SA module. The syntaxtree, visitor, and parsers packages have 141, eight and 13

classes respectively. The classes inside these packages will remain the same as long as












the Java and SQL grammars do not change. The seekstructures and seekvisitors packages


have 25 and nine classes respectively and are subject to change as we add new


functionality to SA module.



0 z


I


I i


Analyzer Packages Structure 1.


S Solution 'SEEK' (1 project)
EB- I SEEK

El seek
E.- Q sa
m SeekJava.java
1 classilles
I L- dcjava
SE- L- documents
SE- LU jad
S-- javafiles
[I.. B parsers
ASCII_UCodeESC_CharStream. java
3avaParser.java
3 avaParserConstants.java
JavaParserTokenManager.java
OracleParser.java
OracleParserConstants.java
OracleParserTokenManagerjava
ParseExceptionjava
-Token.java
STokenMgrError.java
I rcclasses
L- seekstructures
I L seekvisitors
I .- 1L syntaxtree
a E. L testjava
L- visitor
I xmloutput
S se
e Analysis.java
Encoder.java
Extractor.java
Inference.java
TreeTest.java
userlp.java
11 adapter
B -. I- att
B-+ 3 database
L ri entity
Li incdep
E ]-- I relationships
+.. L table


Figure 4-2 Java Semantic


A1


Solution 'SEEK' (1 project)
SEEK

B- 0 seek
B sa
SI- SeekJava.java
S ..... C classfiles
7--- 3 dcjava
.. 3- documents
I- Jjad
S 1-- 3 javafiles
+: parsers
: i.... rcclasses
I; 12 seekstructures
1+ 3 _seekvisitors
B syntaxtree
SAdditiveExpression. ava
SAllocationExpression.java
SAndExpression.java
SArgumentList.]ava
SArguments.java
SArrayDimsAndInits.java
SArrayInitializer. java
AssertStatementjava
AssignmentOperator.java
SBlock.java
SBlockStatement.java
S.. BooleanLiteral.java
SBreakStatement.]ava
S CastExpression.java
CastLookahead.java
SClassBody.]ava
SClassBodyDeclarationjava
ClassDeclaration.java
SCompilationUnit.java
SConditionalAndExpression.java
SConditionalExpression.java
SConditionalOrExpression.]ava
SConstructorDeclarationjava
ContinueStatement.java
DoStatement.]ava
EmptyStatement.java
S .... EqualityExpression.java
S ExclusiveOrExpression.java


~








47



The entire package structure is depicted in Figures 4-2 and 4-3. In Figure 4-2, some


of the automatically generated classes of parsers and syntaxtree packages can be seen.


Figure 4-3 shows some of the classes of seekvisitors and seekstructures that we have


written.


i


- 2 SEEK






UJi*i


l ii i.'7'.l-
l .j.:rji








i : ..'r



rI- I : :II i





I P1 i ji, .-r: -
*: i.l l rir.:.- i Is s



















rI, ..:...I T,. l i : i :





I :.r l I.ir,,l -


Figure 4-3 Java Semantic Analyzer Packages Structure 2.


As it can be noticed in Figure 4-2 and Figure 4-3 there are other packages in the


Java SA package, namely, classfiles, javafiles, dcjava, rcclasses, and xmloutput. They are


n ': 6H8 M

SEEK





-I ,:l ~,
I- .J.:I : : .i


LJ .ri-





h* 1lJ-- il i ; : ji.









ti- r .L i 1 h h_,".,
l i' r.:.I i.

| i-, L r.-ir .. :. :.
.:.l- :r : I l- h.l.:.-r I* :
L i to':, rI 1

Sm ir..









the directories in which we keep the inputs and outputs of SA. The directory "classfiles "

stores .class files that are being analyzed. The directory "javafiles" stores .java files that

are being analyzed. The directory "rcclasses" stores recompiled classes. The directory

"dcjava" stores .j ava files that were generated by decompiling classes by JAD

decompiler. The directory "xmloutput" stores output files of Java semantic analyzer

which contains abstract syntax tree of parsed classes and SQL statements.

4.2 Using the Java Tree Builder To Augment the Grammar Specification File

Implementation started with the augmentation of the grammar specification file

with the Java Tree Builder (JTB). As explained in the Chapter 2 and 3, to have a more

robust parser, the JavaCC parser generator technology is used. To utilize the benefits of

visitor patterns, JTB technology is used to add desired Java code inside the grammar

specification file. When the grammar specification file is given to the JTB, a new

grammar specification file with visitor patterns is produced. Details of JavaCC, JTB, and

visitor patterns are described in Chapter 2.

The grammar specification file (.jj file) for Java that was obtained from JavaCC

repository [6] is given as an input to JTB 1.2.2. The outcomes are the Java files in the

syntaxtree and visitor directories and also the new grammar specification file,jtb.out.jj.

Figure 4-4 illustrates the input and outputs of the JTB tool. JTB produces the Java classes

in the syntaxtree directory according to production rules in the grammar. Each Java class

also has an "accept" method to be used by visitors. Visitor Java classes that are created in

the visitor directory have a method that corresponds to each of the Java classes inside

syntaxtree package. Each of the Java classes are modified to put them into appropriate

seek packages, syntaxtree classes into the seek.sa.syntaxtree, and visitor classes into

seek.sa.visitor packages. This is done by adding "Package seek.sa.syntaxtree; line at the









beginning of the all Java class files in the syntaxtree directory and "Package

seek.sa.visitor; line at the beginning of all Java class files in the visitor directory.


EBNF Grammar with Embedded Java Code
(jtb.out.jj file)
EBNF JTB Syntax Tree Node Classes
grammar Tool (in syntaxtree package)
Default Visitors and Interfaces
(in visitor package)

Figure 4-4 Input and outputs of the JTB tool.

4.3 Generate Parser by JavaCC

The output of the JTB tool, the grammar specification file, is input to JavaCC.

JavaCC generates the parser files that will accept grammar according to the input

specification file. The parser files are listed in Table 4-1.

Table 4-1 JavaCC generated parser files.
ParserName.java Has main method, methods for each non-terminals,
debug(trace) methods, getNetToken method.
ParserNameConstants.java Interface for tokens
ParserNameTokenManager.java Manages the token source file
ParseException.java Exceptions
SimpleCharStream.j ava ParserNameTokenManager uses
Token.java Describes the input token stream
TokenMgrError.java Returns a detailed message for the Error when it is
thrown by the token manager to indicate a lexical
error.


For the SA component of the SEEK prototype, two parsers are created, namely a

Java and an SQL parsers. Both parsers use the same SimpleCharStream, Token,

TokenMsgError, and ParseException classes and they have their own ParserName,

ParserNameConstants, and ParserNameTokenManager classes. These parser files are

placed in the parsers directory for a better package organization. To put them in the









proper package structure, the "Package \eek tlA t \'e ,i" line is placed at the beginning of

each file.

4.4 Execution Steps of Java Semantic Analyzer

The driver class for the semantic analyzer is the SADriver class. The SADriver

accepts the name of the source code file as an argument. The analyzing process starts

with this source code file. The SADriver invokes the recursive processFile method of the

ProcessFile class with its initial parameters. The parameters of the processFile method

are class name, method name, and arguments of method. Initially, parameters of the

processFile are sourcefile name as class name, main as a method name, and String[] as

the argument of the main method. It is assumed that the class name parameter that is

given to the SADriver is the name of the stand-alone Java class, which has the main

method. Starting from this stand-alone file, all user-defined classes on the control flow

graph are traversed during the analyzing process.

As it is illustrated in Figure 4-5, the SADriver.java takes Class Name as a

parameter and invokes the ProcessFile method on ProcessFile class with the parameters

Class Name, Method Name (main), and Arguments (String[]).The ProcessFile method

executes two main steps:

* Step 1: The ProcessFile method makes preparations necessary for analyzing the
source code. Starting from Class Name and main method of that class,
ProcessFile.java finds the files that are going to be analyzed with the help of the
FindClass.java. Then, it copies them into proper directories and extracts the control
flow graph by traversing the source code classes.

* Step 2: The ProcessFile.java starts analyzing the methods in the control flow
graph. These two steps are shown in bold face in the ProcessFile.java box of
Figure 4-5 and are described in the following sections.















Initialization of
Java Semantic Analyzer


Class Name
Method Name
Arguments


FindClass.java Class File Name
*Get Class Path Info
*Search Class Path
for Class File Name Class File Location


Figure 4-5 Initialization of the Java Semantic Analyzer.


4.4.1 Making Preparations to Analyze


There are two main steps in the process of analyzing the Java code. Details of an


iteration of the first step "Make Preparations for Analyzing" is explained in this section.


---------------------


CopyMoveFile.java Locaton

Copy: Class is copied from Location 1
into classes directory

2
DRCompile.java File Name

Decompile: Uses JAD decompiler to 3
convert .class files to java files and
puts them into dcjava directory.
Recompile: Compiles class file in
Sdcjava directory and stores it into
rcclasses directory 5
Compare: Compares the file lengths
of.class file in classfiles directory with
rcclasses directory and outputs results 6
o
Class From
Symbol Table
FindClass.java S l
Search: Search and specify class 7
location in class path in directories and Loc
in jar files. Loca

Next Class Name And Location
----------------------t


Class Name
Location I
ProcessFile.java
PrepareForProcess
method
. Copy Class File


. Decompile Class


. Parse Java File


. Write AST in XML


. Write Symbol Table


. Get Package Import Info
f Class and feedback this
nfo to FindClass.java


. Search and set locations
f user-defined classes in
symbol Table.

. Get next user-defined
lass name and its location
o prepare for analyzing


File Name
JavaParser.java

Parses the mputjava
file and outputs abstract
Root Node
R Node syntax tree of it
ofAST

ObjectXMLWriter.java

Visitor Class that writes AST
into XML file m xmloutput

AST
ObjectSymbolTable.java

Visitor Class that writes
Symbol variable declarations into
Table Symbol Table
Table

AST

ObjectPackageImport.java

Visitor Class that get package and
import declarations from AST


package, import info


Figure 4-6 Eight steps that make up prepareForProcess method.


Class Name


SADriver.java


ProcessFile.java


1. Make Preparations to analyze
2. Analyze
* Report Analysis









Figure 4-6 shows the eight steps that make up prepareForProcess method of the

ProcessFile class and its interaction with other classes:

* Stepl: If the method gets ".class" as the value of the parameter extension, it copies
the file from its location into the classfiles directory. If the method gets ".java" as
the value of parameter extension, then it copies the file into thejavafiles directory.
* Step 2: If ".class" is the value of the parameter extension, it decompiles this
".class" file by JAD decompiler to get the corresponding source code. This ".java"
file can then be recompiled byjavac to compare the sizes of found the ".class" file
and recompiled the ".class" file. The rationale behind this process was explained in
the decompiler section of Chapter 3.
* Step 3: The "java" file in the dcjava directory or in thejavafiles directory is parsed
by the Java parser.
* Step 4: The outcome root node of the Java abstract syntax tree is then passed to the
XML Writer visitor class to write the AST in XML format into a file.
* Step 5: After that, variable information (name, scope, type, etc.) is extracted from
AST by ObjectSymbolTable visitor class.
* Step 6: Package and import information is also extracted by ObjectPackagelmport
visitor class to be given to the FindClass class to be used for next user-defined
class finding process.
* Step 7: The SearchVariableClass class is used to identify the locations of user
defined classes in the symbol table. This location information is entered in the
symbol table.
* Step 8: After all user defined classes are searched in the class path and in the
imported packages, it gets the next user defined class name and location from
symbol table to prepare it to be analyzed. By these class name and location
parameters prepareForProcess method is called recursively.

The process of preparing classes continues until all eight steps are applied to all

classes in the control flow graph. Visitor patterns are used during the fourth, fifth, and

sixth steps. Details of these steps will be given in Section 4.5.

4.4.2 Analyze Source Code

Following initialization, the SA analyzes the methods. Figure 4-7 shows what is

being done in an iteration of the recursive analyzeMethods method of ProcessFile class.











- - ---- MethodName
SAndArguments

ProcessFile.java

1. Identify Slicing Variables
according to input-output-SQL
statements.
2. Get business rules that have
slicing variables.
3. Get comments of business rule
and methods
4. Get Called Methods from this
method
5. Get SQL Statements and parse
them by OracleParser class.
6. Get table, column information
from this parsed SQL node by
giving it to ObjectOracleParser
visitor class
7. Make relations between variable
semantics and columns oftables.


Get the next method and its
arguments to analyze.
I NextMethodNameAndArguments


AST, SymbolTable ObjectSlicingVars.java

Visitor Class that identifies slicing
variables.
SymbolTable updated by variables.
shcing variables

AST, SymbolTable ObjectBusinesRules-
Comment.java

SymbolTable updated by Visitor Class that finds business
business rules rules for slicing variables.

AST, SymbolTable ObjectCalledMethods.java

Visitor Class that finds called
SymbolTable updated by methods in user-defined classes.
SymbolTable updated by
business rules

AST, SymbolTable ObjectSQLStatements.java

Visitor Class that constructs SQL
meo uded c methods from variables and parses
Solu eate them by Oracle Parser and gets table
and column information and relates
them to variables.

Root Node SQL String
table and column ofSQL
information

ObjectSQLParser.java OracleParser.java

Visitor Class that finds called Parses the input java
methods in user-defined classes. file and outputs abstract
syntax tree of it.


Figure 4-7 Seven steps that make up analyzeMethods method.


As it is shown in Figure 4-7, the analyzing source code has seven steps, which are:


* Step 1: Identify slicing variables by Object/hl. iig'ars visitor pattern.
* Step 2: Extract the business rules statements that these slicing variables are used in
by ObjectBusinessRuleComment visitor pattern.
* Step 3: Extract the comments1 of the business rules and methods by
ObjectBusinessRuleComment visitor pattern.
* Step 4: Extract method calls on user-defined classes and forms a link list for the
called methods by ObjectCalledMethod visitor pattern.
* Step 5: Constructs the SQL strings by ObjectSQLStatement visitor pattern and
parses them.
* Step 6: The AST of the SQL string is then sent to ObjectParseSQL visitor class to
get table, column information.
* Step 7: This information is used by ObjectSQLStatement visitor pattern to make
relations between slicing variables and column names.


1 We can extract comments only if we are processing .java files. When we process .class files, we do not
have access to comments since they can not be reproduced by de-compilation step.










After the seventh step is executed, the analyzeMethods method gets the next called

method name and arguments, and calls itself with this method name and its arguments

recursively. Figure 4-7 also shows the interaction of analyzeMethods method with the

classes it uses. The details of the visitor patterns that are used in this process are provided

in the following section.

Note that, we first process the class files as a whole in the preparation step. Then,

we only analyze the methods that are used by method calls. As it was stated in Chapter 3,

this approach save effort and improve performance. We do not analyze methods that will

never be called.

4.5 Functionality of Visitor Classes

In this section, we define the functionality of the visitor classes. Visitor classes help

to extent the functionality of our code easily. If we need a further functionality, all we

need to is to write a new visitor class that covers this functionality. Visitor classes also

help to organize the related functionality in the same visitor class.

Visitor classes can be written by extending a default visitor class and by overriding

methods of this default visitor class. The default visitor class is ObjectDepthFirst class,

which implements visitor interface ObjectVisitor. When a method is not overwritten, it

uses the method of the extended class, ObjectDepthFirst. Methods of the default visitor

only help navigate between methods. Next, we explain the functionality of the visitor

classes that is used in our project.

4.5.1 Output Abstract Syntax Tree to XML File

ObjectXMLWriter is the visitor class that is used to output Abstract Syntax Tree

(AST) of a Java file into an XML file. Node names of the AST form tag names of the









XML file. All XML files are written into xmloutput directory. ObjectXMLWriter visitor is

used to write the AST of SQL statements as well.

4.5.2 Get Variable and Method Declaration Information

ObjectSymbolTable is the visitor class that is used to gather variable declaration

information. It constructs the main file-class-method organization structure that will be

used in follow-on steps of the analyzing process. This structure is shown in Figure 4-8.











Method 1.1.1 Method 1.1.2 Method 2.2.1 Method 2.2.2


Figure 4-8 Link List Structure of Traversed Method Tree of SA.
In Figure 4-8, ParsedaFile is the file of the first class that was given as a


parameter to SA. In general, Java files can contain more than one class definition. The
ParsedFile 2 shown in Figure 4-8, is an example of this type of file. It has classes Class

2.1 and Class 2.2.

The ObjectSymbolTable visitor stores variable declarations in a symbol table.

Locations of variables in the symbol table are specified with the help of a hash table.

Method and constructor declarations are also stored in the symbol table. The formal

parameter list of the method and constructors are attached to them with a


nextProcElement pointer. When a method declaration is inserted into the symbol table, its

scope and stack information is also saved. Scope and stack information are important

when we analyze two or more different methods of a class that have variables with the









same names. After we gather the meaning of a variable and save it into the symbol table,

we must not override that meaning with the meaning of a variable that has the same name

but declared in another method. Keeping scope and stack information class-wise helps us

to distinguish it from other variables with the same name but in different scopes. Scope is

changed by opening a new scope and closing the existing one at the beginning and end of

the visitor methods. According to Java grammar, scope is changed inside the visitor

method of the following AST nodes:

* Class Declaration,
* Method Declaration,
* Constructor Declaration, and
* Statement.

ObjectSymbolTable visitor stores a SymbolTableElement class into symbol table

that holds information for each variable and method. The information in this class is then

enriched by other visitors. Table 4-2 outlines the information that is stored in

SymbolTableElement.

SymbolTable and SymbolTableElement are the most important class in the SA.

SymbolTable class is passed to each visitor pattern that aims to extract information from

code. The information held in SymbolTableElement is enhanced by each visitor pattern.

4.5.3 Get Slicing Information

Ol/je, tili ilngVars is the visitor class that is used to identify slicing variables. These

are important variables in the process of semantic extraction. As previously defined in

Section 3.6, slicing variables are used in input, output, and SQL statements. They are also

passed to a method as a parameter. When we encounter a variable as an argument to an

input, output, SQL, or user-defined method, we set the appropriate flag in the









SymbolTableElement structure to indicate that the meaning of this variable should be

investigated further.

Table 4-2 Information stored for variable/method declaration in SymbolTableElement.
Info Name Definition
Name Name of the variable
Scope Scope of the variable
DeclarationNo declaration sequence number in the class
InputSlicing is set true if the variable is used in an input statement
OutputSlicing is set true if the variable is used in an output statement
SQLSlicing is set true if the variable is used in an SQL execute statement
MethodSlicing is set true if the variable is passed as a parameter to a method
ResultsetSlicing is set true if the variable is used in a resultset get method
UserDefinedClass is set true if type of the variable is a user defined class
ClassLocation Location of the user defined class. Class is the type of the variable
Category If it is variable declaration, value of category is 'variable', otherwise
it is 'method' or 'constructor' depending on the declaration.
Type Class of the variable
Value Used to store string value of string slicing variables
NextElement If there is more than one declaration with the same name but
different scope, new variable is added to the end of
SymbolTableElement list.
NextProcDec Pointer to the list of formal parameters of the method
RelatedElement If there is an assignment statement between two variables, they are
related with this pointer
ColumnElement if there is an assignment from resultset get method to this variable,
points to the corresponding columnElement in the resultset get
method
StackPosition stores the stack scope info when an element of category method is
defined


4.5.4 Get Business Rules and Comments

ObjectBusinessRuleComment is the visitor class that extracts a list business rules

and comments related to this business rules. The visitor class searches business rules

inside assignment, if and switch statements. Such a statement is interpreted as a business

rule if it contains a slicing variable. The Table 4-3 provides information that is stored in


the BusinessRules class.









Slicing variables that exist in this business rule are saved in RelatedElement field of

business rule structure. This visitor also saves the comments in the BusinessRule class

that occur just before the potential business rules in the code. The pointer to the root of

the node of the business rule in the AST is also saved. This node can be used in

outputting this business rule in a desired format.

Table 4-3 Information stored in BusinessRule class.
Info Name Definition
Type Type of the business rule, like Statement, Assignment
Text Text of business rule
Comment Comment that were placed right before the business rule text
ClassName Class name in which business rule is
MethodName Method Name in which business rule is
RelatedElement The pointer to the list of variables that exists inside this business rule
Node The pointer to the root of the node of the business rule in the AST
Next Next business rule


One business rule can reside inside another. In such a case, the business rule is

inherited inside another. If the business rule is inherited by another business rule, we

concatenate the current business rule (the one that is inherited) with the previous business

rule (the one that inherits) and also add the slicing variables of the current rule to the

previous rule. This scenario is depicted in Figure 4-9. business rule 1 inherits business

rule 2. varl,var2, var3, var4, var5, and var6 are slicing variables of business rule 1,

while var4, var5, and var6 are the slicing variables of business rule 2.

If (varl.equals('yes'))
{ var2 = var3 + 8;
If (var4.equals('no')) 4
{
var5 = var6 + 7;
1*
var3 = 0; Business
# Rule 2
Business
Rule 1

Figure 4-9 Example of a business rule that inherits another business rule.







59


The elicitation of business rules is achieved using stacks. When we encounter a

potential business rule statement (if, assignment, or switch %\i'tume/), we begin to store

the tokens of the code in a stack. Meanwhile, if we encounter a slicing variable, we also

store the slicing variable in a stack. When a new business rule is encountered before the

end of the one currently under investigation, a new business rule is pushed onto the stack.

Figure 4-10 illustrates the contents of the stack at the point when "*" in Figure 4-9 is

reached. BR2 in Figure 4-10 contains the "If (var4.equals('no')) var5 = var6 + 7;} "'

string, and BR1 in Figure 4-10 contains the "If (varl.equals('yes )){var2 = var3 + 8; "

string. When the latter business rule has been processed, the text and slicing variables for

it are added to the previous one. The content of the stacks at the point when "#" in Figure

4-9 is reached are shown in Figure 4-11. It can be readily seen that, the content of the VS2

stack is transferred to VS1 and the text of BR1 and BR2 are also merged. The BRText

contains the "If (varl.equals('yes ))var2 = var3 + 8; If (var4.equals('no')) var5 = var6

+7;} var3 =0; string.




Var3 Var6

BR2 VS2 Var2 Var5

BR1 VS1 Varl Var4

VS1 VS2
Stack of Stack of VS2
Business Variable Stack of Stack of
Rules Stacks Variables Variables


Figure 4-10 The content of the stacks at point when "*" in Figure 4-9 is reached.







60





Var3 Var6

Var2 Var5

BRText VS1 Varl Var4

VS1
Stack of Stack of VS1
Business Variable
Rules Stacks Stack of Variables
Rules Stacks


Figure 4-11 The content of the stacks at point when '#' in Figure 4-9 is reached

Another functionality of ObjectBusinessRuleComment visitor class is that it saves

comments that are written just before the method declarations in the code. These

comments are saved and then passed to the method that is being analyzed.

4.5.6 Get Method Calls

The visitor class ObjectCalledMethods gets the list of method calls inside a

method. These methods are the ones that are invoked on user defined classes. When the

visitor ObjectCalledMethods encounters a method, it adds the method to the list with its

method name, class name, and argument list. The argument list is formed from the actual

parameters of the method call. An argument element class that stores the properties of an

argument has name, type, and value fields. Figure 4-12 outlines the structure of the

method call and argument list that are gathered by ObjectCalledMethods visitor.


Parsed Method


CalledMethod 1 CalledMethod 2 CalledMethod 3 } Method List


SArgument 1 Argument 21 \ Argument 1 } Argument List


Figure 4-12 List of Method Calls Structure.









4.5.7 Get Package-Import-Extend Info

The ObjectPackageImport is the visitor class that is used to obtain package,

imported classes, and extended class information of a Java file. This information is then

used in finding the user-defined classes in the class path using the file finder class

FindClass.

4.5.8 Get SQL Statements

The ObjectSQLStatement is the visitor class that is used to extract SQL statements

and parse them. This is one of the core visitors of the SA. While the visitor traverses the

AST, it constructs the value of string variables. When a variable of type string or a string

text is passed as a parameter to an SQL execute method (e.g., executeQuery(queryStr)), it

parses the string with SQL parser. The SQL parser returns the AST of this SQL string.

The ObjectSQLStatement visitor then uses the ObjectSQLParse visitor to get information

about that SQL statement. The details of the ObjectSQLParse visitor are discussed in the

next section. If the value of a variable is compared with a column in the where clause of

an SQL statement, it saves information about the relation between the variable and the

column. While the visitor traverses AST, if it encounters a SQL retrieve method (like

getString("column name ")) on a Resultset type of variable instance, it gets the related

column info and relate it to variable name. If ObjectSQLStatement encounters an output

method, it evaluates the string by relating possible meaning with the variable names. It

relates the variables with the text in the most recent output statement.

4.5.9 Parse SQL Strings

The ObjectSQLParse is the visitor class that is used to parse SQL strings and store

the information about the SQL string into a ReithletiQL class structure. Table 4-4 lists

the members of the Re iulhne.,QL class.










Table 4-4 Information stored in ResultsetSQL structure
Info Name Definition
Name Class Name + Method Name + Declaration No
Type Type can be 'update', 'select', 'insert' or 'delete'
String SQL string
Node Root node of the AST of the SQL string
Columns Pointer to column list
Tables Pointer to table list


The AST of an SQL select statement is given to the ObjectSQLParse visitor with

an initially empty Re,,\nti\iQL class instance. The ObjectSQLParse visitor traverses the

AST of the SQL statement and extracts table, and column names. In addition, the

ObjectSQLParse fills the Re,,ti1hetQL class with the column and table information. As

one can see in Figure 4-13, when a SQL statement is forwarded to ObjectSQLParse

visitor, a list of column and table information is attached to the Re,,l\nieiQL instance.

The ObjectSQLParse can extract table and column information of Uptade, Insert, and

Delete statements as well.


ResultsetSQL
String = "Select A.activno, P.projname From Activity A, Project P Where A. proj_no = B. projno"


Column Element Column Element
Name = activ_no Name = proj_name
No = No = 2
TableName = Activity TableName = Project

Table Element Table Element
Name = Activity Name = Project
No = 1 No = 2


Figure 4-13 Example of a ResultsetSQL class.














CHAPTER 5
EVALUATION OF SEMANTIC ANALYZER

Several criteria can be used to evaluate our semantic analyzer. The main criteria

include correctness and performance. In this chapter, we introduce our prototype test

system to demonstrate how SA captures the semantics from source code correctly and

within a reasonable amount of time. In Section 5.1, we show the correctness of key

features of SA by using code fragments. In Section 5.2, we show the semantics extracted

from an application from Construction Scheduling and discuss the correctness of these

semantics. In Section 5.3, we show the performance improvement in time when

compared to previous version of SA and explain how we achieved this.

5.1 Can Features of Semantic Analyzer Extract Semantics Correctly?

In this section, we use code fragments to demonstrate how key features of SA can

correctly extract meaning. In each subsection, we introduce a code fragment and show

what SA can extract from that code fragment. Then, we explain why this extracted

meaning is correct.

5.1.1 Targeting a Specific Column from the Query

In this subsection, we show that SA can target a specific column from the result set

of a query. The correctness of this feature is important to satisfy the eighth heuristic that

is introduced in Section 3.7.

When a SQL select query string is given as a parameter to executeQuery method of

a Statement object instance, the tuples satisfying the selection criteria of the query are

returned in a Re',,iuht object. The Java Database Connectivity (JDBC) Application









Program Interface (API) provides several methods for ResultSet object to obtain

individual column values from a tuple in the ResultSet. The parameter of a ResultSet get

method can be one of the following:

1. A string: Column name from the SELECT query column list
2. An integer: Between zero and the number of columns in the query minus one.


SA can accurately handle these two types of parameters of the Retili.et get

methods and can specify the corresponding column name in the column list of the SQL

query statement. SA stores the RettliSet information inside an instance ofRe,,l\n.StSQL

class. Examples of these two parameters are given in Table 5-1.

Table 5-1 Examples of ResultSet get method parameters.
ResultSet get method parameter as an integer:
ResultSet resultSet = sqlStatement.executeQuery("SELECTpid FROM Project");
String projNumber = resultSet.getString(1);
ResultSet get method parameter as a String:
resultSet = sql Statement. executeQuery("SELECTpid FROM Project");
String projNumber = resultSet.getString('pid');


As shown in Figure 5-1, the column list and table list are extracted from the SQL

query string and a list of ColumnElement and TableElement are formed and attached to

the Reili.SetSQL class instance. Reini./StSQL is formed by ObjectSQLParse visitor and

is introduced in Section 4.5.9. When the "get method" parameter is an integer, we find

the (integer parameter +])th element in the ColumnElement list. When the "get method"

parameter is a String, we find the column by comparing the name of the parameter with

the name of the elements in the ColumnElement list.











ResultsetSQL
String = "Select A.activ no, P.proj name From Activity A, Project P Where A. proj no = B. proj no"

Column Element Column Element
Name activev no Name = proj_name
No= No =2
TableName = Activity TableName = Project

Table Element Table Element
Name = Activity Name = Project
No 1 No 2

Figure 5-1 Example of a Retih'ei.SQL class and ColumnElement and TableElement lists.

After representing the code examples in Table 5-1 in a ResultSetSQL class form as

shown in Figure 5-1, SA can correctly target the specific column as explained in the

previous paragraph. Correctly targeting a specific column feature is important to relate

the correct column of a table with the correct output statement which will give the

meaning of the column.

5.1.2 Extracting the Column Name from Mathematical Expression

In this subsection, we show that SA can extract the name of the column even if it is

embedded in a complex mathematical expression. The correctness of this feature is also

important to satisfy the eighth heuristic that is introduced in Section 3.7.

Table 5-2 Example of a SQL query that has mathematical expression in its column list.
resultSet = sqlStatement. executeQuery("SELECT (activpflannedfinishdate 1)
FROMActivity WHERE activ no = 5");
java.sql.Date startDateSQL = resultSet.getDate(1);


Figure 5-2 gives the Reni.SetSQL class representation of the query in Table 5-2.

As shown in Figure 5-2, ColumnElement's name field has the correct column name. As it

was stated before, RenliNSetSQL is formed by ObjectSQLParse visitor. ObjectSQLParse

traverses the AST of SQL expression and accurately extracts the column name.










ResultsetSQL
String = "SELECT (activ_plannedfinishdate + 1) FROM Activity WHERE activno = 5"


Column Element
Name = activ_plannedfinishdate
Text = (activ_plannedfinishdate + 1)
No= 1
TableName = Activity

STable Element
Name = Activity
No= 1

Figure 5-2 ResultSetSQL class representation of the query in Table5.2.

Even we find a meaning related with the mathematical expression, if SA could not

identify the column name from a mathematical expression, then SA would fail to relate

meaning with the correct column name. If SA could not identify the column name from a

mathematical expression, SA would not find a matching entry to fill with the meaning in

the schema of data source that was extracted by SE.

5.1.3 Geting Query Expression from the Variable Value

In this subsection, we show that SA can correctly save and retrieve the value of a

string variable. The parameter given to the "SQL execute method" (e.g., executeQuery)

can be a string type of variable as well. The string variable can hold an SQL query. The

value of the variable must be correctly saved and retrieved when it is used in an SQL

execute method.

Table 5-3 Example of using variable in the executeQuery method.
String queryString = "SELECTpidFROMProject";
ResultSet resultSet = sqlStatement.executeQuery(queryString);
String projNumber = resultSet.getString(1);


An example of using a variable as a parameter of "SQL execute method" is given

in Table 5-3. Note that, there can be several numbers of statements between the value

assignment of variable and the SQL execute method.










5.1.4 Concatenating Strings to Get the Query Expression

In this subsection, we show that SA can correctly recognize the meaning of

concatenating operator (+) and concatenate strings to get the query expression. Table 5-4

is an example of this. When query] and query2 in Table 5-4 are declared, their initial

values are stored in the value field of their SymbolTableElement in the SymbolTable.

When they are used in a string expression with the concatenating operator, their values

are obtained from SymbolTable and are used to form the new string.

Table 5-4 Example of Concatenating String to Get the Query Expression.
String query = "SELECT active_duration, activ_planned_startdate ";
String query2 = FROM Activity + WHERE Activno = '5' ";
String query = query 1 + query2 +
ResultSet resultSet = sqlStatement.executeQuery(query);


Figure 5-3 illustrates how variable values in Table 5-4 are stored in SymbolTable.

The value of the element query2 is formed by concatenating the strings "FROM

Activity", and "WHEREActiv no = '5' ". The value of the element query is formed by

concatenating the value of string variables query] and query2.


SymbolTable
SymbolTableElement
Name queryl
.... Value : "SELECT activ duration, activplanned startdate "

queryl W R SymbolTableElement
query2 Name : query2
-qury I Value : FROM Activity WHERE Activ no = '5' "
query

SymbolTableElement
Name: query
Value : "SELECT activ duration, activplanned startdate
FROM Activity WHERE Activ no = '5' "


Figure 5-3 Illustration of String SymbolTableElements and their values.









SA can correctly form the string expression by concatenating any number of string

variables and expressions. These variables and expressions can form an SQL expression

or an input/output statement that inherits meaning. Correctly forming and evaluating the

SQL expression and input/output statement is important to get the most benefit from the

application code.

5.1.5 Geting the Meaning of Slicing Variable from the Output Text

SA can accurately relate output statements with slicing variables. The slicing

variable concept is introduced in Section 3.6. SA gets the meaning of the slicing variables

from the most recent output text. To achieve this, SA pushes the output text in a stack and

when a slicing variable is encountered, it pops the text from the stack and relates it with

that slicing variable.

Table 5-4 Making relations between output statements and columns.
String query = "SELECT activ_duration,activeplanned_startdate FROM Activity
WHERE activno = '"+ inputActivity + '"
resultSet = sqlStatement.executeQuery(query);
duration = resultSet.getInt(l);
oldStartDate = resultSet.getString(2);
System.out. println(" activity no: + inputActivity);
System.out.println("old start date: + oldStartDate);
System.out.println("duration: + duration);


In the example in Table 5-4, the meaning of the inputActivity, oldStartdate, and

duration slicing variables are obtained from the most recent output text and these

meanings are then related to activ no, activ duration, and active planned startdate

variables. Note that inputActivity variable is used in the where clause of the query. SA

also keeps track of the variables that are used in where clauses because they have

potentially important information about the semantic of their correspondence columns in

the where clause.









Correctly finding the meaning of the slicing variable is important because after

finding the meaning of the slicing variable, we assign this meaning to the column of a

table that was already related with that variable. Correctly realizing this feature means

that we can correctly realize the eighth heuristic in Section 3.7.

5.1.6 Passing Semantics from one Method to Another

One of the most powerful features of SA is passing argument values and meanings

from one method to another. SA conquers the meaning found in the current method with

the meanings found before the current method was called. SA transfers semantics from

one method to another by this feature causing it to get more accurate results. When a

method is called, the values of parameters are passed from the point where the call is

made to the called method. The execution continues from the called method.

In the example given in Table 5-5, the SQL query information is passed to the

outputProjectResultset method in the ei.lihet variable. Although the SQL query is in the

initializeQuery method and the output statement is in the outputProjectResultset method,

SA can accurately keep track of the parameters that are passed between methods and can

relate "Project Num: output statement with pid column of table Project. If SA could

not correctly transfer the semantics from one method to another through arguments, then

SA would not be able to capture the semantics of p_id column of table Project and this

semantics would have been lost.

5.1.7 Extracting the Meaning from the Title Output

Slicing variables may not have output statements that identify their meaning.

Instead, they may have a title output statement as shown in Table 5-6. In this case, SA

shows the title to the user as a possible meaning. The title inherits semantics for the

following outputs of columns. In the example given in Table 5-6, projectNo,









workItemNo, and currentactivity variables and their corresponding columns have

"proj no workitemno activityno" output statement as a possible meaning. Note that, texts

like "-------------------" and "\t" are used for formatting. They are eliminated and are not

shown as a possible meaning. Correctly identifying the title of the outputs of columns and

presenting this title to user helps us to get more semantic information from the

application code.

Table 5-5 An example of passing parameter values.
Public static void initializeQuery (Statement sqlStatement,ResultSet resultSet)
{
String query = "SELECT p_id FROM Project";
resultSet = sqlStatement. executeQuery(query);
outputProjectResultset(sqlStatement,resultSet);
}

public static void outputProjectResultset (Statement sqlStatement,ResultSet resultSet)
{
System.out.println("The following are all the projects found:");
while(resultSet.next))
{
String projNumber = resultSet.getString(1);
System.out.println("Proj ect Num:" + projNumber);
}
resultSet. close;
i


Table 5-6 Extracting the meaning from the title.
query = "SELECT Activno, Workitemno, Projno FROM Activity";
resultSet = sqlStatement.executeQuery(query);
System.out.println("projno workitemno activityno ");
System. out.println("---------------------------------");
while(resultSet.next() {
proj ectNo = resultSet.getString(3);
System.out.println(proj ectNo);
workItemNo = resultSet.getString(2);
System.out.print("\t" + workItemNo);
currentactivity = resultSet.getString(1);
System.out.print("\t" + currentactivity);









The correctness of the above key features of SA is important to accomplish the goal

of SA. SA correctly extracts meaning from code as introduced in the above examples and

extracts the highest amount of semantics that is available in the source code.

5.2 Correctness Evaluation

In this section, we show how SA accurately extracts the application specific

meaning from source code. To show this, we use an application from Construction

Scheduling. This program does a very simple re-scheduling of an activity of a

construction firm. The source code can be found in Appendix G. Table 5-7 shows the list

of meanings of the columns that are extracted from the Construction Scheduling Program

source code. Now, we explain how SA correctly satisfies our heuristics and extracts the

meanings listed in Table 5-7.

The reader can notice that some of the columns have only one meaning and some

of the columns have several meanings in Table 5-7. If all the output texts are the same or

there is only one output text for a column of a table, then there is only one meaning

assigned to that column. In this case, the column meaning has no ambiguity. In Table 5-7,

the meaning ofp id column of table Project and the meaning of active duration column

of table Activity are found without any ambiguity. If more than one output statements can

be associated with a column, then there is ambiguity. Activ no, activgplannedfinishdate,

and activplanned startdate columns of table Activity have several meanings assigned to

them. For this reason, there is ambiguity in the meaning of these columns.

When there is ambiguity, the list of meanings is presented to the user and an input

to resolve the ambiguity is expected. The frequency of some words can give clues about

the meaning of the column. For instance, the word activity has the highest frequency in

the list of meanings for activity no column of Activity table. Even if the column name









was irrelevant, instead of Activity no, the frequency of word activity could be a good clue

to identify its meaning.

Table 5-7 Extracted Meanings of the Columns from the Construction Scheduling
Program Source Code.


Column & Table Name:
Column Name: Activ no
Table Name: Activity
Ambiguity: true


Extracted Meanings:
1) projno workitemno activityno startdate finishdate
2) Activity is being rescheduled to the earliest date
possible
3) activity no
4) You have entered days to shift the activity
5) Activity
6) Sorry there is no slot to shift the activity
7) You can not choose the same activity
8) Sorry there is no enough slot to place the activity
9) Sorry there is no enough slot to place the activity after
the activity


Column Name: p_id 1) Project Num
Table Name: Project
Ambiguity: false
Column Name: Projno 1) projno workitemno activityno startdate finishdate
Table Name: Activity
Ambiguity: true
Column Name: Workitemno 2) projno workitemno activityno startdate finishdate
Table Name: Activity
Ambiguity: true
Column Name: 1) projno workitemno activityno startdate finishdate
activ_planned_finishdate 2) The new finish date is
Table Name: Activity 3) The new start date is
Ambiguity: true 4) The new start date is
Column Name: 1) projno workitemno activityno startdate finishdate
activ_planned_startdate 2) old start date
Table Name: Activity 3) You can shift this activity at most
Ambiguity: true 4) oldstartdate
Column Name: activduration 1) duration
Table Name: Activity
Ambiguity: false


Another form of ambiguity can be seen when a meaning statement is used for more

than one column. For instance, Project no and Workltem No columns of table Activity

have this kind of ambiguity. The code fragment that causes this kind of ambiguity is









shown in Table 5-8. In the code fragment in Table 5-8, a title is given for the preceding

outputs. SA eliminates the format outputs such as "---------" and "\t" and assigns the title

meaning "proj no workitemno activityno startdatefinishdate" to Activ no,

activplanned startdate, activplanned finishdate, Workitem no, and Proj no of table

Activity.

Table 5-8 Extracting the meaning from title of the outputs.
query = "SELECT Activno, activ_planned_startdate, activ_plannedfinishdate,
Workitemno, Projno FROM Activity ORDER BY activ_planned_startdate";
resultSet = sqlStatement. executeQuery(query);
System.out.println("projno workitemno activityno startdate finishdate ");
System. out.println("-------------------------------------- ");
while(resultSet.next))
{
currentactivity = resultSet.getString(1);
workItemNo = resultSet.getString(4);
proj ectNo = resultSet.getString(5);
System.out.print(proj ectNo);
System.out.print("\t" + workItemNo);
System.out.print("\t" + currentactivity);
}
resultSet. close();


The Construction Scheduling Program is also a good example of how SA extracts

semantics from applications that have functionality separated into multiple files. The

functionality of the scheduling program is separated into three files: ScheduleMenu.java,

ScheduleList.java and ManipulateActivity.java. The analyzing process starts from the

main method of ScheduleMenu.java file and dispatches to the methods in

ScheduleList.java, and ManipulateActivity.java files as it encounters a method call on

these classes. Table 5-9 shows a method call that is made on an instance of ScheduleList

class from the main method of ScheduleMenu.java class. After SA completes analyzing









initiliazeProjectQuery method, it continues to analyze the main method of ScheduleMenu

from the next statement, if (menuOption.equals("2")) statement.

Table 5-9 Code fragment inside the main method of ScheduleMenu.iava
If (menuOption. equals(" 1")) {
scheduleList.initiliazeProj ectQuery(sql Statement,resultSet); }
if (menuOption.equals("2")){
scheduleList.listActivities(sqlStatement,resultSet); }


The Construction Scheduling Program source code also verifies that SA can extract

and integrate semantic from different methods. SA can transfer the semantic of a variable

to a new method when it is used as an argument inside the method call. An example of

this case is given in Table 5-10. In this example, the SQL query semantic is held inside

the variable ei'nuhl t. When listProjects(sqlStatement, ieIili,.t) method call is done

inside the initiliazeProjectQuery method, the semantic gathered for eti \nl et variable is

transferred to the variable IetnleStProject in the listProjects method. If SA does not have

this feature, it can not relate the output statement "Project Num:" to the p id column of

Project table.

Table 5-10 Code fragment from ScheduleList.java shows how variable semantic is
transferred from one method to another.
Public static void initiliazeProjectQuery(Statement sqlStatement,ResultSet resultSet){
String query = "SELECT p_id FROM Project";
resultSet = sqlStatement. executeQuery(query);
li stProj ects(sql Statement,resultSet); }
public static void listProjects(Statement sqlStatement,ResultSet resultSetProject) {
System.out.println("The following are all the projects found:");
while(resultSetProj ect.next()) {
String projNumber = resultSetProject.getString(l);
System. out.println("Proj ect Num:" + projNumber);
}
resultSetProj ect.close();









According to our experiments with Construction Scheduling Program source code,

SA can correctly satisfy the heuristics that was introduced in Section 3.7 and can

correctly extract all the meanings in the user interaction statements that can be related

with a column of a table. Analyzing Construction Scheduling Program source code has

been a good example that validates all the features of the new SA. We have also tested

SA with numerous of small code fragments to evaluate the correctness of each of the SA

feature. It would be beneficial to test the new SA with several more number of large code

samples that can be used to validate all the futures of the new SA in one application.

5.3 Performance Evaluation

SA is a built-time component of SEEK. Although performance is not as critical as

correctness, it is important to state that the performance of our new version has

significantly improved when compared to the first version [2]. This is because the current

version of SA introduces significantly different algorithms to extract information from

source code. The current and previous versions of SA are tested on an Intel Pentium-IV

PC with a 1.4 GHz processor, 256 MB of main memory, and 512KB cache memory

running Windows NT.

Previous version of SA executes four main steps which were explained in [2]. Step

3 and 4 are applied for each of the slicing variables. Table 5-11 gives time spent in

seconds for each of these steps and for each slicing variables in step three four while

analyzing Construction Scheduling program.

* Step 1: AST Generator: Constructs the AST for the source code
* Step 2: Pre-slicer: Identifies slicing variables
* Step 3: Code-slicer: Performs slicing and constructs a reduced AST
* Step 4: Analyzer: Traverses reduced AST to extract semantic information









Table 5-11 Time spent (in seconds) in sub steps of previous version of SA.
Step No Time Spent in Seconds
Step 1 1
Step 2 472
Step 3 & Slicing Variable Name Time in seconds 561
Step 4 for projNumber 4
each slicing intProjNo 4
variables workItemNo 4
currentActivityNo 4
start Date 19
finish Date 14
totalActivityNumber 5
inputActivity 95
oldStartDate 6
duration 60
inputactivity 14
dateDiff 22
shiftAmount 12
input Activity 101
current Activity 94
old Start Date 6
dur 48
activityCount 3
dateDifference 46
Total Time 1034


For each of the slicing variables, previous version of SA prepares and analyzes a

new AST, step 3 & 4 in Table 5-11. It spends significant amount of time to construct the

AST for that slicing variable and then extracts information from that AST. If the number

of statements that the slicing variable participates is low (e.g., projNumber), then the time

spent to analyze that slicing variable is small. If the number of statements that the slicing

variable participates is high (e.g., input Activity), then the time spent to analyze that

slicing variable is large. As the number of slicing variables in source code increases, the

total time spent for step 3 & 4 increases.

The new SA executes two main steps which were explained in Section 4.4.

S Step 1: Prepare classes.









S Step 2: Analyze the methods starting from main method of the given class.

Step 1 prepares all the user-defined classes that are used in the application. Then,

Step 2 analyzes the methods. Table 5-12 shows time spent to prepare each of the classes

in Construction Scheduling program, namely ScheduleMenu, ScheduleList, and

ManipulateActivity classes. Note that, time is given in milliseconds.

Table 5-12 Time spent (in milliseconds) in current version of SA.
Step No Class or Method Name that is being processed Time Spent
Step 1 ScheduleMenu Class 8406
Prepare ScheduleList Class 2157
Classes ManipulateActivity Class 10765
Step 2 main Method of ScheduleMenu Class 219
doDatabaselnitializations Method of ScheduleMenu Class 0
Analyze getTotalActivityNumber Method of ScheduleMenu Class 813
Methods menu Method of ScheduleMenu Class 31
initiliazeProjectQuery Method of ScheduleList Class 62
listProjects Method of ScheduleList Class 47
listActivities Method of ScheduleList Class 219
rescheduleActivity Method of ManipulateActivity Class 1516
shiftActivity Method of ManipulateActivity Class 187
changeActivity Method of ManipulateActivity Class 1063
Total 29642


The reader can notice that the current version applies Step 1 to each class and

applies Step 2 to each method. In the current version of SA, the increase in the number of

slicing variables slightly affects the performance, because the current SA does not

construct and traverse the AST for each slicing variable. Instead, it constructs the AST

for each class and traverses it for each method. While traversing the AST, the current SA

considers all slicing variables and analyzes them simultaneously. The total time spent

values in Table 5-11 and 5-12 show that we improved the performance of SA by a factor

of 35 (1034 / 29.6).














CHAPTER 6
CONCLUSION AND OPPORTUNITIES FOR FUTURE RESEARCH

The SEEK project (Scalable Extraction of Enterprise Knowledge) currently under

way in the Database Research and Development Center at the University of Florida has

resulted in novel and comprehensive methodologies for semantic analysis of application

code to assist in generating a detailed description of a legacy information system. This

detailed description of the legacy system is used to overcome problems of assembling

knowledge resident in numerous legacy information systems in the business network. The

SEEK project aims to enable extended enterprise collaboration in complex business

networks. Lack of techniques for scalable extraction of knowledge resident in

participating firms in the extended enterprise is an important barrier to such

collaboration. In the SEEK project, we develop methodologies and algorithms to discover

and extract the detailed description of the legacy system in a flexible and scalable manner

that significantly reduces human involvement. SEEK is not meant as a replacement for

wrapper or mediator development toolkits. Rather, it complements existing tools by

providing input about the contents and structure of the legacy source that has so far been

supplied manually by domain experts [1].

The theories and methodologies proposed in this thesis provide a significant

improvement to the existing semantic analyzer in SEEK. The previous version

represented a comprehensive solution for mining semantic knowledge from application

code [2]. This thesis adds heuristics which represent a more extensible and robust

approach for extracting semantic information from legacy source. At the same time, our









approach performs significantly better in terms of execution time. Furthermore, this

thesis provides a generic solution for the semantic analysis problem for application code

written for relational databases. Our approach uses state-of-the-art techniques to obtain

the source code when it is only available in the form of object files, to get the AST for the

source code, and to extract semantics from that AST. We briefly summarize the

contributions made by the research described in this thesis followed by a discussion of

possible enhancements that can be performed in future extensions.

6.1 Contributions

The most significant contribution of our SA is to integrate and utilize state-of-the-

art techniques from different research areas such as code reverse engineering, parser

generation, and object oriented programming as shown in Chapter 3.

Our new SA introduces a new extensible and flexible algorithm for semantic

extraction. Our modifications and upgrades in the algorithm of the SA resulted in a

design that is extensible in the following two ways:

1. SA can be easily extended to mine a different programming language. This can be
done simply by replacing the abstract syntax tree generator module with another
JavaCC produced parser. Using JavaCC parsers not only helps the AST generator
to be extensible but also provides a robust parser when the grammar specification
file from JavaCC repository is used. This specification was tested over thousands of
code files.

2. New algorithms to extract extra information can be added easily. This means when
a new heuristic is found, the functionality of this heuristic can be introduced to the
SA structure by creating a new visitor pattern class. A visitor pattern that analyzes
the AST of the source code can be plugged in and out to enhance the functionality
of SA at any time.

Moreover, our new SA algorithm eliminates analyzing unnecessary code. Source

code can contain methods that are never used. The functionality inside this unused code









can be misleading. SA extracts the control flow graph of the code and analyzes only the

methods that are in the control flow graph.

The design and implementation of new semantic analyzer algorithm improves

temporal performance, and also provides the most accurate results as shown in Chapter 5.

Traversing multiple code files to gather the overall semantics is another important

feature of our new SA. Since the functionality of the legacy application is usually

distributed into separate files, it is important to gather semantics of related modules and

be able to combine them to obtain better feedback about the semantics of the application

as a whole.

The implementation of SA is done in Java. Java is an object oriented language

enabling us to implement object oriented techniques. SA's object oriented structure is

another contribution. We see the following benefits of using an object oriented

implementation for SA:

* We have the chance of using visitor design patterns. A visitor design pattern is used
to separate functionality of information extraction process into separate visitor
classes. This makes our code flexible and extensible.

* Object oriented techniques like abstraction and encapsulation are used.Thus,
functionality is separated and encapsulated inside separate classes which make its
maintenance easier.

SA uses state-of-the-art code reverse engineering techniques to get the source code

back from the binary code. If the binary code is available, but the source code is

misplaced, SA uses these techniques to get the text of the source code.

6.2 Future Work

In this last section, we discuss possible improvements to SA that can be added to

future versions. Our current semantic analyzer extracts semantics from Java code of

legacy system. One possible improvement to SA can be functionality to infer semantic









information from the code of stored procedures and triggers as well. Once we analyze the

stored procedure calls from the Java code and the functionality of stored procedures,

more semantic information will be gathered. Once we analyze the triggers, we can see the

effect of insert, update, and delete SQL statements to other entities of the underlying data

schema. A trigger is often used to check the constraints of a table. If the constraint is not

satisfied with an insert, update, or delete SQL statement, then the trigger cancels the

operation. If the constraint is implemented in the code of the trigger instead of

implementing in the schema definition of the table, then SE will not discover it, but SA

will discover and enhance the extracted schema of the data source. Another usage of the

trigger is to make updates, and inserts to related tables if necessary. When we analyze the

triggers, we discover relationships between entities that we may not be able to discover

with extracting the schema and analyzing the application code.

Operations are recorded in a transaction log in a database system. In database

programming, SQL statements that must be executed as a whole are placed in the same

transaction and are committed as if they are one atomic statement. Database management

systems keep transaction logs to assure that these SQL statements are committed as a one

atomic statement. SQL statements in the same transaction are highly related with each

other and this relation inherits semantic information. Extending the SA, to analyze the

transaction logs, can be another improvement.

Our semantic analyzer identifies its slicing variables according to the user

interaction statements inside the code. Then, it investigates the meaning of these slicing

variables. Specifically, user interaction statements are input/output statements that are

used to interact with the user via the standard input/output. There can be many other









methods of user interaction. Information coming from application can be presented to the

user in many ways. We can call the part of the code that presents and gathers information

from the user as thepresentation layer. We can also call the part of the code that inherits

the functionality as the application layer. The presentation layer of legacy information

system can be totally separated from the application layer. This presentation layer can be

application specific and can be developed with the help of the technologies like JSP, and

HTML. In such cases information exchanged between the presentation and application

layers inherits semantic information. This information flow between the presentation and

application layers can be investigated, and new modules to SA can be added to capture

this information. When we analyze this user interaction information and relate it to the

underlying schema of the legacy system, more semantics will be gathered.

The number of real application source codes used to test the features of the SA was

limited but we have used all the available codes. Future experiments on a large code

sample have to be conducted to assert the correctness of our work.














APPENDIX A
GRAMMAR SPECIFICATION FILE EXAMPLE FOR JAVACC

The specification file may start with a section of options to configure the type of

parser JavaCC will generate. For example, IGNORE_CASE can be set to force the parser

to treat upper and lowercase characters the same.

Then PARSERBEGIN statement comes. JavaCC uses the string that is passed to

this statement to name the parser's class file. After the statement, any Java subroutines

can be added in. A main method that instantiates the parser should also be written, so that

it can be tested from the command line. This section of the file terminates with a

PARSER END statement.

The last part of the file contains the token definitions and productions.

An example of .jj file is provided in the Figure A-1. The parser that is generated

from this grammar specification file reads an Input token. This token consists of one or

more Id tokens. The Id tokens consist of a letter, followed by zero or more letters,

numbers, or underscores. The parser skips blanks, tabs, carriage returns, and new lines.

Each production has an empty pair of braces at the beginning. This is where Java

code is placed for the production (usually variable declarations). Within the production

rules, more braces can be added and Java code can be inserted that will execute when that

production matches.

When the below specification file is given to JavaCC, these files are created

* IdS.java : main method, methods for each non-terminals, debug(trace) methods,
getNetToken method
* IdSConstants.java : interface for tokens









* IdSTokenManager.java : manages the token source file
* ParseException.java : Exceptions
* SimpleCharStream.j ava : IdSTokenManager uses
* Token.java : describes the input token stream
* TokenMgrError.java : Returns a detailed message for the Error when it is thrown
by the token manager to indicate a lexical error.

Table A-i Example of .jj file.
options {
IGNORE CASE=true;
}
PARSER BEGIN(IdS)
public class IdS {
public static void main(String args[]) throws ParseException {
IdS parser = new IdS(System.in);
parser.Input();
}
}
PARSER END(IdS)
SKIP:
{

I "\t"
S"\n"
S"\r"
}
TOKEN:
{
< Id: ["A"-"Z"] ("A"-"Z","O"-"9","_"])* >
}
void Input( :
{}
{
( )+














APPENDIX B
COMPILER BASIC TERMS

B.1 Production Rules

Rules in a context free grammar is known as production. Symbols on the left hand

sides of the production are known as variables, or non-terminals. Symbols that are to

make up the strings derived from the grammar are known as terminals.

B.2 LL and LR Grammars

The two most important classes of grammars are LL and LR. LL stands for left to

right, Left -most derivation LR stands for left to right, Right most derivation. In both

cases input is read left-to-right. LL parsers are also called top-down or predictive parsers.

They construct a parse tree from the root to down. LR parsers are also called bottom-up

parsers. They construct a parse tree from leaves up. There are several important

subclasses of LR parsers, including SLR, LALR and full LR. LL(2) or LALR(1): number

in parenthesis indicates how many tokens of look ahead are required to parse.

B.3 Table Driven Top-Down Parsing

Instead of using its procedure call chain to trace out a tree traversal, the parser

maintains a stack containing a list of symbols it expects to see in the future. Initially, the

parse stack contains the start symbol of the grammar. When it predicts a production, the

parser pops the left-hand side symbol off the stack and pushes the right hand side

symbols in reverse order. It also pops the terminal off the stack whenever it matches it

against a token from the scanner.






86


B.4 Lexical Analyzer

Lexical analyzer ('token manager' in JavaCC) reads in a sequence of characters and

produces a sequence of objects called "tokens". The rules used to break the sequence of

characters into a sequence of tokens obviously depend on the language; they are supplied

by the programmer as a collection of "regular expressions".

B.5 The Parser

The parser consumes the sequence of tokens, analyses its structure, and produces

"abstract syntax tree".














APPENDIX C
DECOMPILED FILE EXAMPLE

In this Appendix, we give an example to show how accurately Jad decompiler can

convert .class files to java files. In Table C.1, we show the original source code of

ScheduleMenu.java. We compile ScheduleMenu.java and get the ScheduleMenu.class

file. Then, we de-compile ScheduleMenu.class file with Jad decompiler and get another

version of ScheduleMenu.java code. In Table C.2, we show the de-compiled version of

ScheduleMenu.java.

Table C.1 Original version of ScheduleMenu.j ava code.
import java. sql.*;
import java.util.*;
import java.io.*;
public class ScheduleMenu{
static String database = "jdbc:oracle:thin:@oracle.cise.ufl.edu: 1521:oradb";
static String user = "****"; static String password ="******";
static int totalActivityNumber;
static Connection jdbcConnection; static Statement sqlStatement;
static ResultSet resultSet=null; static String query = null;
public static void doDatabaselnitializations(String databaseName, String userName,
String pass) throws Exception {
/******* CONNECTS TO DATABASE *******/
Class.forName("oracle.jdbc.driver. OracleDriver");
jdbcConnection = DriverManager.getConnection(databaseName,userName,pass);
/******* PREPARES SQL STATEMENT *******/
sqlStatement = j dbcConnection.create Statement();
}
public static String readLineFromConsoleo
{
String lineRead = "";
try {
BufferedReader br = null;
InputStreamReader inl = null;
inl = new InputStreamReader(System.in);
br = new BufferedReader(inl);
lineRead = br.readLine0;