Skip to main content
summaryrefslogtreecommitdiffstats
blob: 04f21a0b4bac8b448e8a9bcf72106c13c8b15db7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
/**
 *                                                                            
 * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 *                                                                            
 * All rights reserved. This program and the accompanying materials           
 * are made available under the terms of the Eclipse Public License 2.0        
 * which accompanies this distribution, and is available at                  
 * https://www.eclipse.org/legal/epl-2.0/                                 
 *                                 
 * SPDX-License-Identifier: EPL-2.0                                 
 *                                                                            
 * Contributors:   
 * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
 * 
 * 
 *  This copyright notice shows up in the generated Java code
 *
 */
 
package org.eclipse.osbp.xtext.datainterchange.jvmmodel

import com.vaadin.shared.ui.label.ContentMode
import com.vaadin.ui.Button
import com.vaadin.ui.Button.ClickEvent
import com.vaadin.ui.Button.ClickListener
import com.vaadin.ui.Component
import com.vaadin.ui.HorizontalLayout
import com.vaadin.ui.Label
import com.vaadin.ui.NativeButton
import com.vaadin.ui.Panel
import com.vaadin.ui.ProgressBar
import com.vaadin.ui.UI
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.PrintWriter
import java.io.StringReader
import java.io.StringWriter
import java.net.MalformedURLException
import java.net.URI
import java.net.URISyntaxException
import java.net.URL
import java.nio.file.FileAlreadyExistsException
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
import java.text.MessageFormat
import java.util.Arrays
import java.util.Date
import java.util.HashMap
import java.util.List
import java.util.Map
import java.util.MissingResourceException
import java.util.Properties
import java.util.UUID
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.persistence.EntityManager
import javax.persistence.EntityTransaction
import javax.persistence.TypedQuery
import javax.persistence.criteria.CriteriaBuilder
import javax.persistence.criteria.CriteriaQuery
import javax.persistence.criteria.JoinType
import javax.persistence.criteria.Root
import javax.validation.ConstraintViolation
import javax.validation.ConstraintViolationException
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerConfigurationException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource
import org.apache.commons.lang.StringEscapeUtils
import org.apache.log4j.lf5.util.StreamUtils
import org.eclipse.core.resources.ResourcesPlugin
import org.eclipse.core.runtime.IPath
import org.eclipse.e4.core.di.extensions.EventUtils
import org.eclipse.e4.core.services.events.IEventBroker
import org.eclipse.emf.common.util.EList
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.util.EcoreUtil
import org.eclipse.osbp.blob.service.BlobService
import org.eclipse.osbp.blob.service.BlobTypingAPI
import org.eclipse.osbp.datainterchange.api.IDataInterchange
import org.eclipse.osbp.dsl.entity.xtext.extensions.EntityTypesBuilder
import org.eclipse.osbp.dsl.entity.xtext.extensions.ModelExtensions
import org.eclipse.osbp.dsl.semantic.common.types.LAnnotationTarget
import org.eclipse.osbp.dsl.semantic.common.types.LAttribute
import org.eclipse.osbp.dsl.semantic.common.types.LDataType
import org.eclipse.osbp.dsl.semantic.common.types.LFeature
import org.eclipse.osbp.dsl.semantic.common.types.LReference
import org.eclipse.osbp.dsl.semantic.entity.LBean
import org.eclipse.osbp.dsl.semantic.entity.LBeanAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntity
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.osbp.eventbroker.EventBrokerMsg
import org.eclipse.osbp.preferences.ProductConfiguration
import org.eclipse.osbp.runtime.common.annotations.CreateAt
import org.eclipse.osbp.runtime.common.annotations.CreateBy
import org.eclipse.osbp.runtime.common.annotations.Dirty
import org.eclipse.osbp.runtime.common.annotations.UpdateAt
import org.eclipse.osbp.runtime.common.annotations.UpdateBy
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent
import org.eclipse.osbp.runtime.common.event.EventDispatcherEvent.EventDispatcherCommand
import org.eclipse.osbp.ui.api.datamart.IDataMart.EType
import org.eclipse.osbp.utils.entityhelper.DataType
import org.eclipse.osbp.xtext.addons.EObjectHelper
import org.eclipse.osbp.xtext.basic.generator.BasicDslGeneratorUtils
import org.eclipse.osbp.xtext.datainterchange.DataInterchange
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeBean
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeBlobMapping
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeEntityExpression
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeExportHide
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFile
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileCSV
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileEDI
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileFixed
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFileXML
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFixedColumnMapping
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeFormat
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookup
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupFilterCondition
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupFilterOperandProperty
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeLookupFilterOperandString
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeMapping
import org.eclipse.osbp.xtext.datainterchange.DataInterchangePackage
import org.eclipse.osbp.xtext.datainterchange.DataInterchangePredefinedExpression
import org.eclipse.osbp.xtext.datainterchange.DataInterchangeValueMapping
import org.eclipse.osbp.xtext.datainterchange.EntityManagerMode
import org.eclipse.osbp.xtext.datainterchange.common.WorkerThreadRunnable
import org.eclipse.osbp.xtext.entitymock.common.IEntityImportInitializationListener
import org.eclipse.osbp.xtext.i18n.DSLOutputConfigurationProvider
import org.eclipse.osbp.xtext.i18n.I18NModelGenerator
import org.eclipse.persistence.config.PersistenceUnitProperties
import org.eclipse.persistence.config.PessimisticLock
import org.eclipse.persistence.config.QueryHints
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.naming.QualifiedName
import org.eclipse.xtext.xbase.compiler.GeneratorConfig
import org.eclipse.xtext.xbase.compiler.ImportManager
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.osgi.framework.Bundle
import org.osgi.framework.BundleContext
import org.osgi.framework.FrameworkUtil
import org.osgi.service.event.Event
import org.osgi.service.event.EventHandler
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.w3c.dom.Document
import org.w3c.dom.Element
import org.xml.sax.SAXException

class ParameterValue {
	var public HashMap<String,String> modifiers = <String,String>newHashMap() 
	var public String value
}

class DataDSLModelGenerator  extends I18NModelGenerator {
	@Inject extension IQualifiedNameProvider
	@Inject extension ModelExtensions
	@Inject extension EntityTypesBuilder
	@Inject extension BasicDslGeneratorUtils

	@Inject
	@Extension
	private DataType dtType;

	val static protected CAPTION__REPFIX_I18NKEY_EXPORT = "export"
	val static protected CAPTION__REPFIX_I18NKEY_IMPORT = "import"
	
	var public static String pckgName = null
	val DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	val transformerFactory = TransformerFactory.newInstance()
	var Transformer transformer = null
	var db = dbf.newDocumentBuilder()
    var domImpl = db.DOMImplementation
	
	def String generateKey(String name, QualifiedName packageName) {
		var pattern = "(\\W)"
		if (name !== null) {
			var newName = name.replaceAll(pattern ,"_").toLowerCase
			System.out.println(newName)
			if (packageName !== null) {
				return packageName.toString.concat(".").concat(newName)
			}
			else {
				return newName
			}
		}
		return null
	}

	def void generatePckgName(DataInterchangePackage pkg, IJvmDeclaredTypeAcceptor acceptor) {
		pckgName = pkg.name
	}
	
	override doGenerate(Resource input, IFileSystemAccess fsa) {
		addTranslatables('''«CAPTION__REPFIX_I18NKEY_EXPORT»,«CAPTION__REPFIX_I18NKEY_IMPORT»''')

        // identation for pretty xml output
        transformerFactory.setAttribute("indent-number", 4);
	    transformer = transformerFactory.newTransformer()
		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes") 
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8")
        transformer.setOutputProperty(OutputKeys.STANDALONE, "yes")
        transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml")

		EcoreUtil.getAllContents(EObjectHelper.getSemanticElement(input), false).filter(typeof(DataInterchangePackage)).forEach[
			fsa.generatePathConfig(it)
		]
		EcoreUtil.getAllContents(EObjectHelper.getSemanticElement(input), false).filter(typeof(DataInterchange)).forEach[
			// create all smooks config files
			fsa.generateImportConfigStub(it)
			fsa.generateExportConfigStub(it)
		]
		super.doGenerate(input, fsa)
	}
	
	def void generatePathConfig(IFileSystemAccess fsa, DataInterchangePackage dataInterchangePkg) {
        var dir = new File('''«System.getProperty("user.home")»/.osbee''')
        if(!dir.exists) {
        	dir.mkdir
        }
        dataInterchangePkg.groups.forEach[
	        var file = new File('''«System.getProperty("user.home")»/.osbee/«it.name»Config.xml''');
	        file.setWritable(true, false);
	        if(!file.exists) {
	        	file.createNewFile
			    val properties = new Properties();
		        it.datInts.forEach[
		        	properties.put('''«it.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL)
		        	properties.put('''«it.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL)
		        ]
		        var fileOutput = new FileOutputStream(file);
				properties.storeToXML(fileOutput, "dataInterchange file URLs");
				fileOutput.close
		    }
		    else {
		    	var fileInput = new FileInputStream(file);
		    	val properties = new Properties();
				properties.loadFromXML(fileInput)
				fileInput.close
		        it.datInts.forEach[
		        	if(!properties.containsKey('''«it.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString)){
			        	properties.put('''«it.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL)		        		
		        	}
		        	if(!properties.containsKey('''«it.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString)){
			        	properties.put('''«it.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()»'''.toString, it.produceAppropiateInterchangeURL)		        		
		        	}
		        ]
		        var fileOutput = new FileOutputStream(file);
				properties.storeToXML(fileOutput, "dataInterchange file URLs");
				fileOutput.close
		    }
        ]
	}
	
	/**
	 * Generates the right file url for both absolute and relative paths.
	 */
	def String produceAppropiateInterchangeURL(DataInterchange interchange) {
		var givenurl = interchange.fileURL
		var filename = interchange.dataInterchangeFileName
		var directory = interchange.getDataInterchangeDirectoryUrlPath

		try {
			var url = new URL(givenurl)	
			if(url.protocol.equals("file")){
				// for relative path 
				if(!Paths.get(directory).absolute){
					var projectname = interchange.eResource.URI.segment(1)
					var location = findProjectFileOrFolderLocation(projectname, directory, false)
					givenurl = location.append(filename).toString
				}
			}
		}
		catch (Exception e1) {
			if(e1.getMessage().startsWith("unknown protocol") || e1.getMessage().startsWith("no protocol")) {
				try{
					// check for relative path
					if(!Paths.get(directory).absolute){
						var projectname = interchange.eResource.URI.segment(1)
						var location = findProjectFileOrFolderLocation(projectname, directory, false)
						givenurl = location.append(filename).toString
					}
				}
				catch (Exception e2) {}
			}
		}
		// if the path is absolute or from another protocol like http, ftp ...
		return givenurl
	}
	
	/**
	 * Returns the path of the given file name or directory name.  
	  */
	def IPath findProjectFileOrFolderLocation(String projectname, String fname, boolean isFile) {
		if(projectname !== null && !projectname.empty && fname !== null && !fname.empty){
			var project = ResourcesPlugin.workspace.root.getProject(projectname);
			if(isFile){
				return project.getFile(fname).location
			}
			return project.getFolder(fname).location
		}
		return null
	}
	
	
	def String getFileURL(DataInterchange dataInterchange) {
		switch(dataInterchange.fileEndpoint) {
			DataInterchangeFileXML: return (dataInterchange.fileEndpoint as DataInterchangeFileXML).fileURL 
			DataInterchangeFileCSV: return (dataInterchange.fileEndpoint as DataInterchangeFileCSV).fileURL 
			DataInterchangeFileEDI: return (dataInterchange.fileEndpoint as DataInterchangeFileEDI).fileURL 
			DataInterchangeFileFixed: return (dataInterchange.fileEndpoint as DataInterchangeFileFixed).fileURL 
		}
		return ""
	}
	
	/**
	* Gives the file path of a data interchange unit  without its file name.
	*/
	def String getDataInterchangeDirectoryUrlPath(DataInterchange  interchange){
		var modelurl = ""
		if(interchange !== null){
			var index = interchange.fileURL.lastIndexOf("/")
			if( index !== -1) {
				modelurl = interchange.fileURL.substring(0, index + 1)
			}else{
				index = interchange.fileURL.lastIndexOf("\\")
				if(index !== -1){
					modelurl = interchange.fileURL.substring(0, index + 1)	
				}						
			}
		}
		return modelurl
	}
    
    /**
	 * Gives the file name of a data interchange unit.
	 */
	def String getDataInterchangeFileName(DataInterchange  interchange){
		var filename = ""
		if(interchange !== null){
			var index = interchange.fileURL.lastIndexOf("/")
			if( index !== -1) {
				filename = interchange.fileURL.substring(index + 1, interchange.fileURL.length)
			}else{
				index = interchange.fileURL.lastIndexOf("\\")
				if(index !== -1){
					filename = interchange.fileURL.substring(index + 1, interchange.fileURL.length)	
				}						
			}
		}
		return filename
	}
	
	def getUrl(DataInterchange di) {
		switch(di.fileEndpoint) {
			DataInterchangeFileXML:
				return (di.fileEndpoint as DataInterchangeFileXML).fileURL
			DataInterchangeFileCSV:
				return (di.fileEndpoint as DataInterchangeFileCSV).fileURL
			DataInterchangeFileEDI:
				return (di.fileEndpoint as DataInterchangeFileEDI).fileURL
			DataInterchangeFileFixed:
				return (di.fileEndpoint as DataInterchangeFileFixed).fileURL
		}
	}

	def void generateExportConfigStub(IFileSystemAccess fsa, DataInterchange dataInterchange) {
		var body = ""
		dbf.namespaceAware = true
        var document = domImpl.createDocument("http://www.milyn.org/xsd/smooks-1.1.xsd", "smooks-resource-list", null)

		var config = document.createElement("resource-config")
		var selector = document.createAttribute("selector")
		selector.textContent = "global-parameters"
		config.attributeNode = selector
		var pEl = document.createElement("param")
		var name = document.createAttribute("name")
		name.textContent = "stream.filter.type"
		pEl.attributeNode = name
		var value = document.createTextNode("SAX")
		pEl.appendChild(value)
		config.appendChild(pEl)
		document.documentElement.appendChild(config)

		var cartridges = <String,String>newHashMap()
		cartridges.put("xmlns:jb", "http://www.milyn.org/xsd/smooks/javabean-1.4.xsd")
		switch (dataInterchange.fileEndpoint) {
			DataInterchangeFileCSV: {
				var delimiter = ""
				var quote = ""
				cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd")
				var csv = dataInterchange.fileEndpoint as DataInterchangeFileCSV
				if(csv.delimiter !== null) {
					delimiter = StringEscapeUtils.unescapeHtml(csv.delimiter)
				}
				if(csv.quoteCharacter !== null) {
					quote = StringEscapeUtils.unescapeHtml(csv.quoteCharacter)
				}
				dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, delimiter, quote)
			}
			DataInterchangeFileXML: {
				cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd")
				dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, null, null)
			}
			DataInterchangeFileEDI: {
			}
			DataInterchangeFileFixed: {
				cartridges.put("xmlns:ftl", "http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd")
				dataInterchange.generateExportConfig(document, dataInterchange.fileEndpoint, null, null)
			}
		}
		for(cdg:cartridges.keySet) {
			document.documentElement.setAttributeNS("http://www.w3.org/2000/xmlns/", cdg, cartridges.get(cdg))			
		}

        var source = new DOMSource(document)
        var res = new DataResult()
        transformer.transform(source, res)
        body = res.result 
		fsa.generateFile('''«dataInterchange.name»-«WorkerThreadRunnable.Direction.EXPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, body)
	}
	
	def void generateImportConfigStub(IFileSystemAccess fsa, DataInterchange dataInterchange) {
		var body = ""
		dbf.namespaceAware = true
		var db = dbf.newDocumentBuilder()
        var domImpl = db.DOMImplementation
        var document = domImpl.createDocument("http://www.milyn.org/xsd/smooks-1.1.xsd", "smooks-resource-list", null)
	
		var fieldList = <LFeature>newArrayList()
		var cartridges = <String,String>newHashMap()
		var parameters = <String,ParameterValue>newHashMap()
		// for the meaning of cartridges see: http://www.smooks.org/mediawiki/index.php?title=V1.5:Smooks_v1.5_User_Guidecartridges  
		cartridges.put("xmlns:jb", "http://www.milyn.org/xsd/smooks/javabean-1.2.xsd")
		cartridges.put("xmlns:dao", "http://www.milyn.org/xsd/smooks/persistence-1.2.xsd")
		var pval = new ParameterValue
		pval.value = "SAX" 
		parameters.put("stream.filter.type", pval)
		// the smooks.visitor.sort=false removes NPE when using dao:lookup according to:
		// http://milyn.996300.n3.nabble.com/jira-Created-MILYN-265-Add-support-for-Producer-Consumer-based-sorting-of-Visitor-logic-td3387.html
		pval = new ParameterValue
		pval.value = "false" 
		parameters.put("smooks.visitors.sort", pval)
		 
		switch (dataInterchange.fileEndpoint) {
			DataInterchangeFileXML: {
				// set input type and active filename
				pval = new ParameterValue
				pval.value = "input.xml"
				parameters.put("inputType", pval) 
				pval = new ParameterValue
				pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileXML).fileURL
				pval.modifiers.put("type", "input.type.actived")
				parameters.put("input.xml", pval)
				dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint)
				(dataInterchange.fileEndpoint as DataInterchangeFileXML).input(dataInterchange, document)
			}
			DataInterchangeFileCSV: {
				cartridges.put("xmlns:csv", "http://www.milyn.org/xsd/smooks/csv-1.2.xsd")
				// set input type and active filename
				pval = new ParameterValue
				pval.value = "input.csv"
				parameters.put("inputType", pval) 
				pval = new ParameterValue
				pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileCSV).fileURL
				pval.modifiers.put("type", "input.type.actived")
				parameters.put("input.csv", pval)
				dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint)
				(dataInterchange.fileEndpoint as DataInterchangeFileCSV).input(dataInterchange, fieldList, document)
			}
			DataInterchangeFileEDI: {
				cartridges.put("xmlns:edi", "http://www.milyn.org/xsd/smooks/edi-1.2.xsd")
				// set input type and active filename
				pval = new ParameterValue
				pval.value = "input.edi"
				parameters.put("inputType", pval) 
				pval = new ParameterValue
				pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileEDI).fileURL
				pval.modifiers.put("type", "input.type.actived")
				parameters.put("input.edi", pval)
				dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint)
				(dataInterchange.fileEndpoint as DataInterchangeFileEDI).input(dataInterchange, document)
			}
			DataInterchangeFileFixed: {
				cartridges.put("xmlns:fl", "http://www.milyn.org/xsd/smooks/fixed-length-1.3.xsd")
				pval = new ParameterValue
				pval.value = "input.txt"
				parameters.put("inputType", pval) 
				pval = new ParameterValue
				pval.value = (dataInterchange.fileEndpoint as DataInterchangeFileFixed).fileURL
				pval.modifiers.put("type", "input.type.actived")
				parameters.put("input.txt", pval)
				dataInterchange.generateImportConfig(fieldList, document, dataInterchange.fileEndpoint)
				(dataInterchange.fileEndpoint as DataInterchangeFileFixed).input(dataInterchange, fieldList, document)
			}
		}
		for(cdg:cartridges.keySet) {
			document.documentElement.setAttributeNS("http://www.w3.org/2000/xmlns/", cdg, cartridges.get(cdg))			
		}
		var params = document.createElement("params")
		for(para:parameters.keySet) {
			var pEl = document.createElement("param");
			var name = document.createAttribute("name")
			name.textContent = para
			pEl.attributeNode = name
			var value = document.createTextNode(parameters.get(para).value)
			pEl.appendChild(value)
			for(mod:parameters.get(para).modifiers.keySet) {
				var pAt = document.createAttribute(mod)
				pAt.textContent = parameters.get(para).modifiers.get(mod)
				pEl.attributeNode = pAt
			}			
			params.appendChild(pEl)
		}
		document.documentElement.appendChild(params)
        var source = new DOMSource(document)
        var res = new DataResult()
        transformer.transform(source, res)
        body = res.result 
		fsa.generateFile('''«dataInterchange.name»-«WorkerThreadRunnable.Direction.IMPORT.toString().toLowerCase()».xml''', DSLOutputConfigurationProvider.SMOOKS_OUTPUT_ONCE, body)
	}
	
	def input(DataInterchangeFileXML xml, DataInterchange interchange, Document doc) {
	}
	
	def input(DataInterchangeFileCSV csv, DataInterchange interchange, List<LFeature> fieldList, Document doc) {
		var reader = doc.createElement("csv:reader")
		var fields = doc.createAttribute("fields")
		var fldList = <String>newArrayList
		var mappingInterchanges = interchange.path.filter[it.hasAttributeMapping]
		var lookupInterchanges = interchange.path.filter[it.hasReferenceLookup]
		if(mappingInterchanges.empty){
			for(f:fieldList) {
				if(f instanceof LEntityAttribute || f instanceof LBeanAttribute){
					fldList.add(f.toName)
				}else if(f instanceof LEntityReference && lookupInterchanges.length > 0){
					//add reference only if they are specified by lookup
					for(li:lookupInterchanges){
						for(lup:li.lookup){
							if(!fldList.contains(lup.dataMap) && f.name.equals(lup.dataMap)){
								fldList.add(f.toName)
							}
						}
					}
				}
			}
		} else {
			for(f:fieldList) {
				if(f instanceof LEntityAttribute || f instanceof LBeanAttribute){
					for(mi:mappingInterchanges){
						for(mapping:mi.mappings){
							if(!(mapping instanceof DataInterchangeBlobMapping) && mapping.property.equals(f)) {
								fldList.add(mapping.data)
							}
						}
					}
				}else if(f instanceof LEntityReference && lookupInterchanges.length > 0){
					//add reference only if they are specified by lookup
					for(li:lookupInterchanges){
						for(lup:li.lookup){
							if(!fldList.contains(lup.dataMap) && f.name.equals(lup.dataMap)){
								fldList.add(f.toName)
							}
						}
					}
				}
			}
		}

		fields.textContent = fldList.join(",")
		reader.attributeNode = fields

		if(csv.delimiter !== null) {
			var sep = doc.createAttribute("separator")
			sep.textContent = csv.delimiter
			reader.attributeNode = sep
		}
		
		if(csv.quoteCharacter !== null) {
			var quote = doc.createAttribute("quote")
			quote.textContent = StringEscapeUtils.unescapeXml(csv.quoteCharacter) 
			reader.attributeNode = quote;
		}

		var indent = doc.createAttribute("indent")
		indent.textContent = csv.indent.booleanValue.toString
		reader.attributeNode = indent

		var skip = doc.createAttribute("skipLines")
		skip.textContent = csv.skipLines.toString
		reader.attributeNode = skip

		doc.documentElement.appendChild(reader)
	}

	def input(DataInterchangeFileEDI edi, DataInterchange interchange, Document doc) {
		var reader = doc.createElement("edi:reader")
		var mapping = doc.createAttribute("mappingModel")
		mapping.textContent = edi.mappingModel
		reader.attributeNode = mapping
		
		var validate = doc.createAttribute("validate")
		validate.textContent = edi.validate.booleanValue.toString
		reader.attributeNode = validate

		doc.documentElement.appendChild(reader)
	}

	def input(DataInterchangeFileFixed fixed, DataInterchange interchange, List<LFeature> fieldList, Document doc) {
		var reader = doc.createElement("fl:reader")
		var fields = doc.createAttribute("fields")
		var fldList = <String>newArrayList
		var iter = interchange.path.iterator
		if(iter.hasNext) {
			var path = iter.next
			for(map:path.mappings) {
				var column = map as DataInterchangeFixedColumnMapping
				fldList.add(column.createFixedLengthField)
			}
			fields.textContent = fldList.join(",")
			reader.attributeNode = fields
		}
		doc.documentElement.appendChild(reader)
	}
	
	def String createFixedLengthField(DataInterchangeFixedColumnMapping f) {
		var body = '''«f.property.toName»[«f.length»]'''
		var isFirst = true
		if(f.trim) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»trim'''
			isFirst = false
		}
		if(f.leftTrim) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»left_trim'''
			isFirst = false
		}
		if(f.rightTrim) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»right_trim'''
			isFirst = false
		}
		if(f.upperCase) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»upper_case'''
			isFirst = false
		}
		if(f.lowerCase) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»lower_case'''
			isFirst = false
		}
		if(f.capFirst) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»cap_first'''
			isFirst = false
		}
		if(f.uncapFirst) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»uncap_first'''
			isFirst = false
		}
		if(f.capitalize) {
			body = '''«body»«IF isFirst»?«ELSE».«ENDIF»capitalize'''
			isFirst = false
		}
		return body
	}

	def createFreemarker(Document doc, String templateString, DataInterchangeFile endPoint) {
		var freemarker = doc.createElement("ftl:freemarker")
		var apply = doc.createAttribute("applyOnElement")
		apply.textContent = "#document"
		freemarker.attributeNode = apply

		doc.documentElement.appendChild(freemarker)
		var template = doc.createElement("ftl:template")
		var tplName = doc.createCDATASection('''«IF endPoint.encoding !== null»<#ftl encoding='«endPoint.encoding»'>«ENDIF»«IF endPoint.locale !== null»<#setting locale="«endPoint.locale»">«ENDIF»'''+templateString.replaceAll("\r",""));
		template.appendChild(tplName)
		freemarker.appendChild(template)
	}
	
	def Element createBean(Document doc, String beanIdName, String className, String elementMap, boolean isList) {
		var bean = doc.createElement("jb:bean")
		doc.documentElement.appendChild(bean)
		var beanId = doc.createAttribute("beanId")
		beanId.textContent = beanIdName
		bean.attributeNode = beanId
		var clazz = doc.createAttribute("class")
		clazz.textContent = '''«className»«IF isList»[]«ENDIF»'''
		bean.attributeNode = clazz
		// is mapping given?
		if(elementMap !== null) {
			var create = doc.createAttribute("createOnElement")
			create.textContent = elementMap
			bean.attributeNode = create
		}
		return bean
	}	
	
	def Element createProperty(Document doc, Element parent, String propertyName, String decoderName, EType type) {
		var Element value = null
		// try to find a value element, or create a new one
		var node = parent.firstChild
		var done = false
		while(node !== null && (!node.nodeName.equals("jb:value") || (node.attributes.getNamedItem("property") !== null) && !done)) { /* && !node.attributes.getNamedItem("property").nodeValue.equals(propertyName)))) {*/
			var nval = node.attributes.getNamedItem("property")?.nodeValue
			if(propertyName.equals(nval)) {
				done = true
			} else {
				node = node.nextSibling
			}
		}
		if(node === null) {
			value = doc.createElement("jb:value")
			parent.appendChild(value)
		} else {
			value = node as Element
		}

		var property = doc.createAttribute("property")
		property.textContent = propertyName
		value.attributeNode = property
		if(decoderName !== null) {
			var decoder = doc.createAttribute("decoder")
			decoder.textContent = decoderName
			value.attributeNode = decoder
		}
		if	(type == EType.DATE) {
			var defaultValue = doc.createAttribute("default")
			defaultValue.textContent = "null"
			value.attributeNode = defaultValue
		}
		return value
	}
	
	def addMapping(Document doc, Element parent, String propertyName, String dataName, boolean byAttribute) {
		var elementMap = ""
		var attr = parent.attributes.getNamedItem("createOnElement")
		if (attr !== null) {
			elementMap = attr.textContent
		}
		var Element value = null
		// try to find a value element, or create a new one
		var node = parent.firstChild
		while(node !== null && node.hasAttributes && (!node.nodeName.equals("jb:value") || (node.attributes.getNamedItem("property") !== null && !node.attributes.getNamedItem("property").nodeValue.equals(propertyName)))) {
			node = node.nextSibling
		}
		if(node === null) {
			value = doc.createElement("jb:value")
			parent.appendChild(value)
		} else {
			value = node as Element
		}
		var data = doc.createAttribute("data")
		data.textContent = '''«elementMap»/«IF byAttribute»@«ENDIF»«dataName»'''
		value.attributeNode = data
	}
	
	def Element createDecodeParam(String prefix, Document doc, Element parent, String paramName, String paramValue) {
		var param = doc.createElement(prefix+":decodeParam")
		parent.appendChild(param)
		var name = doc.createAttribute("name")
		name.textContent = paramName
		param.attributeNode = name
		var form = doc.createTextNode(paramValue)
		param.appendChild(form)
		return param
	}

	def Element createWiring(Document doc, Element parent, String beanIdRefName, String propertyName, String setterName) {
		var value = doc.createElement("jb:wiring")
		parent.appendChild(value)
		var beanIdRef = doc.createAttribute("beanIdRef")
		beanIdRef.textContent = beanIdRefName
		value.attributeNode = beanIdRef
		if(propertyName !== null) {
			var property = doc.createAttribute("property")
			property.textContent = propertyName
			value.attributeNode = property
		}
		if(setterName !== null) {
			var setter = doc.createAttribute("setterMethod")
			setter.textContent = setterName
			value.attributeNode = setter
		}
		return value
	}

	def Element createExpression(Document doc, Element parent, String propertyName, String propertyValue) {
		var expression = doc.createElement("jb:expression")
		parent.appendChild(expression)
		var property = doc.createAttribute("property")
		property.textContent = propertyName
		expression.attributeNode = property
		var propNode = doc.createTextNode(propertyValue)
		expression.appendChild(propNode)
		return expression
	}

	def Element createDaoLocator(Document doc, Element parent, String beanIdName, String elementMap, boolean allowNoResult) {
		var locator = doc.createElement("dao:locator")
		if (parent === null) {
			doc.documentElement.appendChild(locator)
		} else {
			parent.appendChild(locator)
		}
		var beanId = doc.createAttribute("beanId")
		beanId.textContent = beanIdName
		locator.attributeNode = beanId
		// mapping given?
		if(elementMap !== null) {
			var lookupOnElement = doc.createAttribute("lookupOnElement")
			lookupOnElement.textContent = elementMap
			locator.attributeNode = lookupOnElement
		}
		
		if(!allowNoResult) {
			var onNoResult = doc.createAttribute("onNoResult")
			onNoResult.textContent = "EXCEPTION"
			locator.attributeNode = onNoResult
		}
		var uniqueResult = doc.createAttribute("uniqueResult")
		uniqueResult.textContent = "true"
		locator.attributeNode = uniqueResult
		return locator
	}
		
	def Element createDaoQuery(Document doc, Element parent, String query) {
		var daoQuery = doc.createElement("dao:query")
		parent.appendChild(daoQuery)
		var queryText = doc.createTextNode(query)
		daoQuery.appendChild(queryText)
		return daoQuery
	}
	
	def Element createDaoParam(Document doc, Element parent, String paramName, String paramValue, String elementMap, String dataMap, boolean byAttribute) {
		var Element daoParams = null
		var node = parent.firstChild
		while(node !== null && !node.nodeName.equals("dao:params")) {
			node = node.nextSibling
		}
		if(node === null) {
			daoParams = doc.createElement("dao:params")
			parent.appendChild(daoParams)
		} else {
			daoParams = node as Element
		}
		var daoValue = doc.createElement("dao:value")
		daoParams.appendChild(daoValue)
		var param = doc.createAttribute("name")
		param.textContent = paramName
		daoValue.attributeNode = param
		var decoder = doc.createAttribute("decoder")
		var paramContent = paramValue
		if(paramValue.equalsIgnoreCase("int")){
			paramContent = "Integer"
		}
		decoder.textContent = paramContent
		
		daoValue.attributeNode = decoder
		// mapping given?
		if(dataMap !== null) {
			var data = doc.createAttribute("data")
			data.textContent = '''«elementMap»/«IF byAttribute»@«ENDIF»«dataMap»'''
			daoValue.attributeNode = data
		}
		return daoValue
	}
	
	def Element createDaoInserter(Document doc, String beanIdName, String elementMap) {
		var inserter = doc.createElement("dao:inserter")
		doc.documentElement.appendChild(inserter)
		var beanId = doc.createAttribute("beanId")
		beanId.textContent = beanIdName
		inserter.attributeNode = beanId
		if(elementMap !== null) {
			var create = doc.createAttribute("insertOnElement")
			create.textContent = elementMap
			inserter.attributeNode = create
		}
		return inserter
	}
	
	def generateExportConfig(DataInterchange dataInterchange, Document doc, DataInterchangeFile endPoint, String delimiter, String quote) {
		var substitutionMap = <String,String>newHashMap
		var vectorMap = <String,String>newHashMap
		var substitutionCount = 0
		var fieldList = <LFeature>newArrayList 
		var String rootEntityName = null
		var Document ftlDocument = null
		var Element bean = null
		var Element oldParent = null
		var vector = "vector"
		var depth = 0
		var LEntity previousEntity = null
		// iterate through all path (bean) listed under `path` keyword 
		for(path : dataInterchange.path) {
			if (rootEntityName === null && !path.isMarkLatestImport) {
				rootEntityName = (path.entity as LAnnotationTarget).toName.toString
			}
			if (dataInterchange.fileEndpoint instanceof DataInterchangeFileXML) {
				var currentKey = '''list«substitutionCount»'''
				if(ftlDocument === null) {
					ftlDocument = domImpl.createDocument(null, '''«IF dataInterchange.vectorName !== null»«dataInterchange.vectorName»«ELSE»vector«ENDIF»''', null)
				}
				vector = vectorMap.get(path.entity.toName) ?: vector

				substitutionMap.put(currentKey, '''«vector» as «path.entity.toName»''')
				if(previousEntity !== null && !previousEntity.hasRelation(path.entity)){
					bean = createXmlBean(ftlDocument, oldParent, path.entity, path.format, currentKey, path, dataInterchange)
				}else{
					oldParent = bean
					bean = createXmlBean(ftlDocument, bean, path.entity, path.format, currentKey, path, dataInterchange)
					depth = depth + 1
				}
				substitutionCount = substitutionCount + 1
				previousEntity = path.entity
			}

			for (f : path.entity.allAttributes) {
				createExportAttribute(dataInterchange, path, f, fieldList, vectorMap)
				if(f.type instanceof LBean) {
					var beanAttr = (f as LEntityAttribute).type as LBean
					for(ba : beanAttr.allAttributes) {
						createExportAttribute(dataInterchange, path, ba, fieldList, vectorMap)
					}
				}
			}			
		}
		if(endPoint instanceof DataInterchangeFileCSV) {
			createFreemarker(doc, createCsvTemplate(rootEntityName, fieldList, delimiter, quote, dataInterchange.path), endPoint)
		}
		if(endPoint instanceof DataInterchangeFileXML) {
			createFreemarker(doc, createXmlTemplate(ftlDocument, substitutionMap, dataInterchange.path), endPoint)
		}
		if(endPoint instanceof DataInterchangeFileFixed) {
			createFreemarker(doc, createFixedTemplate(rootEntityName, fieldList, dataInterchange.path), endPoint)
		}
	}
	
	def createExportAttribute(DataInterchange dataInterchange, DataInterchangeBean path, LFeature f, List<LFeature> fieldList, Map<String, String> vectorMap) {
		if(path.getExportFilter === null && f instanceof LAttribute && !f.toMany || 
			path.getExportFilter !== null && 
			f instanceof LAttribute && !f.toMany &&
			path.getExportFilter.hiddenproperties !== null && 
			!path.getExportFilter.hiddenproperties.empty &&
			!path.getExportFilter.hiddenproperties.toList.containsFeature(f)) {
			if(useFeature(f, path, dataInterchange)) {
				fieldList.add(f)
			}
		}
		if(f instanceof LReference && !f.toMany && path.lookupKeys.empty) {
			fieldList.add(f as LEntityReference)
		}
		// if a feature is a 1-* reference, find if the referenced entity is also under this path.
		if(f instanceof LReference && f.toMany && !path.isMarkLatestImport) {
			var iter = dataInterchange.path.iterator
			var next = iter.next
			// find current entity
			while (iter.hasNext && next.entity.toName != path.entity.toName) {
				next = iter.next
			} 
			while (iter.hasNext) {
				// move to next entity
				next = iter.next
				if (next !== null && next.entity.toName == (f.type as LEntity).toName) {
					if(next.refDataSource !== null){								
						vectorMap.put(next.entity.toName, '''«path.entity.toName».«next.refDataSource.name»''')
					}
					else{
						vectorMap.put(next.entity.toName, '''«path.entity.toName».«f.name»''')
					}
				}
			}
		}		
	}
	
	def boolean hasRelation(LEntity root, LEntity entity) {
		var result = root.features.filter[it instanceof LReference && (it as LReference).type.equals(entity)]
		return !result.empty
	}
	
	def generateImportConfig(DataInterchange dataInterchange, List<LFeature> fieldList, Document doc, DataInterchangeFile endPoint) {
		var isFirst = true
		var autoMapping = ""
		var byAttribute = false
		var isMarked = false
		switch(endPoint) {
			DataInterchangeFileCSV:
				autoMapping = "/csv-set"
			DataInterchangeFileXML: {
				autoMapping = '''«IF dataInterchange.vectorName !== null»«dataInterchange.vectorName»«ELSE»vector«ENDIF»'''
				byAttribute = endPoint.byAttribute
			}
			DataInterchangeFileEDI: {} 
			DataInterchangeFileFixed:
				autoMapping = "/set"
		}
		for(path : dataInterchange.path) {
			var map = ""
			if(path.elementMap === null) {
				map = autoMapping
			} else {
				map = path.elementMap
			}
			var Element bean = null
			if(!path.isMarkLatestImport && isFirst) {
				var rootBean = createBean(doc, path.entity.toName+"List", path.entity.fullyQualifiedName.toString, map, true)
				createWiring(doc, rootBean, path.entity.toName, null, null)
				isFirst = false
			} else {
				isMarked = true
			}
			switch(endPoint) {
				DataInterchangeFileCSV: {
					if(!path.isMarkLatestImport) {
						autoMapping = autoMapping + "/csv-record"
					}
				}
				DataInterchangeFileXML: {
					autoMapping = '''«autoMapping»/«IF path.nodeName !== null»«path.nodeName»«ELSE»«path.entity.toName»«ENDIF»'''
				}
				DataInterchangeFileEDI: {} 
				DataInterchangeFileFixed: {
					autoMapping = autoMapping + "/record"
				}
			}
			if(path.elementMap === null) {
				map = autoMapping
			} else {
				map = path.elementMap
			}
			bean = createBean(doc, path.entity.toName, path.entity.fullyQualifiedName.toString, map, false)
			// if merge or remove - create a locator for id and version
			if(dataInterchange.mode != EntityManagerMode.PERSIST) {
				if(!path.lookupKeys.empty) {
					createExpression(doc, bean, path.entity.idAttributeName, "?"+path.entity.toName+"Merger."+path.entity.idAttributeName)
					if(path.entity.versionAttribute !== null) {
						createExpression(doc, bean, path.entity.versionAttributeName, "?"+path.entity.toName+"Merger."+path.entity.versionAttributeName)
					}
					var locator = createDaoLocator(doc, null, path.entity.toName+"Merger", map, true)
					createDaoQuery(doc, locator, path.queryKeys)
					createLookupKeys(path, doc, locator, map, byAttribute, endPoint)
				}
				else if(path.entity.versionAttribute !== null) {
					createExpression(doc, bean, path.entity.versionAttributeName, "?"+path.entity.toName+"Merger."+path.entity.versionAttributeName)
					var locator = createDaoLocator(doc, null, path.entity.toName+"Merger", map, true)
					createDaoQuery(doc, locator, path.queryVersion)
					createDaoParam(doc, locator, '''param''', path.entity.primaryKeyAttribute.decoder, map, path.entity.idAttributeName, byAttribute)
				}
			} else if(!isMarked && !path.hasBlob) {
				createDaoInserter(doc, path.entity.toName, map)
			}
			// are there any mappings?
			var mappingFound = hasAttributeMapping(path)
			for (f : path.entity.allFeatures) {
				switch f {
					LAttribute: {
						if (!f.toMany) {
							// enable mapping for this field
							// if not disposed and not latest marker and not id except no lookup keys given and mode is not persist
							if (!isInternal(f) && (!isId(f) || (path.lookupKeys.empty && dataInterchange.mode != EntityManagerMode.PERSIST))
								&& (!path.isMarkLatestImport  || !path.latestProperty.toName.equals(f.toName))) {
								// add to the level's field list
								if (!path.isMarkLatestImport) {
									if((f as LEntityAttribute).type instanceof LBean) {
										var beanAttr = (f as LEntityAttribute).type as LBean
										for(ba : beanAttr.allAttributes) {
											fieldList.add(ba)
										}
									} else {
										fieldList.add(f)
									}
								}
								if(bean !== null) {
									if((f as LEntityAttribute).type instanceof LBean) {
										var beanAttr = (f as LEntityAttribute).type as LBean
										var subBean = createBean(doc, beanAttr.toName, beanAttr.fullyQualifiedName.toString, map, false)
										for(ba : beanAttr.allAttributes) {
											createImportAttribute(path, ba, doc, subBean, byAttribute, endPoint, mappingFound)
										}
										createWiring(doc, bean, beanAttr.toName, null, f.toSetter.simpleName)
									} else {
										createImportAttribute(path, f, doc, bean, byAttribute, endPoint, mappingFound)
									}
								}
							}
						}
					}
					// check relations for modeled lookup
					LReference: {
						if (f.toMany) {
							// one to many
							// mapped automatically
							var iter = dataInterchange.path.iterator
							var next = iter.next
							// find this entity
							while (iter.hasNext && !next.entity.toName.equals(path.entity.toName)) {
								next = iter.next
							} 
							while (iter.hasNext) {
								// move to next entity
								next = iter.next
								if (next !== null && next.entity.toName.equals((f.type as LEntity).toName)) {
									createWiring(doc, bean, (f.type as LEntity).toName, null, f.toAdder(f.name).simpleName)
								}
							}
						} else {
							// many to one
							if(path.lookup.isEmpty) {
								fieldList.add(f as LEntityReference)
								var field = (f as LEntityReference).type.primaryKeyAttribute
								var etype = dtType.getBasicType(field)

								for(mapping : path.mappings) {
									if(f.name.equals(mapping.property.name)) {
										createProperty(doc, bean, f.toName, field.decoder, etype)
										addMapping(doc, bean, f.toName, mapping.data, byAttribute)
									}
								}

							} else {
								// generate possible lookups for this many to one relationship
								var paramCnt = 0
								for (lookup : path.lookup) {
									// entity and property must match
									if (lookup.targetProperty.toName.equals((f as LReference).name)) {
										if(endPoint instanceof DataInterchangeFileCSV){
											// the field will need to be included for header
											fieldList.add(f as LEntityReference)
										}
										createWiring(doc, bean, (f.type as LEntity).toName, (f as LReference).name, null)
										var locator = createDaoLocator(doc, null, (f.type as LEntity).toName, lookup.elementMap, lookup.allowNoResult)
										createDaoQuery(doc, locator, (f.type as LEntity).query(lookup, paramCnt))
										createDaoParam(doc, locator, '''param«paramCnt»''', lookup.queryProperty.type.name.toFirstUpper, lookup.elementMap, lookup.dataMap, byAttribute)
										paramCnt ++
										if(lookup.condition !== null && lookup.condition.operand instanceof DataInterchangeLookupFilterOperandProperty && !lookup.condition.operator.literal.startsWith("is")) {
											var prop = (lookup.condition.operand as DataInterchangeLookupFilterOperandProperty).refProperty
											for(mapping:path.mappings) {
												if(mapping.property.equals(prop)) {
													if(mapping.data === null) {
														createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, autoMapping, prop.toName, byAttribute)
													} else {
														createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, mapping.data, prop.toName, byAttribute)
													}
													paramCnt ++
												}
											}
										}
										if(lookup.condition !== null && lookup.condition.subcondition !== null) {
											lookup.condition.subcondition.iterateConditionParameter(doc, locator, path.mappings, autoMapping, paramCnt, byAttribute)
										}									
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
	def createImportAttribute(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, boolean byAttribute, DataInterchangeFile endPoint, boolean mappingFound) {
		// scan expressions for this field
		var expressionFound = path.createAttributeExpression(f, doc, parentElement)
		// scan formats for this field
		var formatFound = path.createAttributeFormat(f, doc, parentElement, endPoint)
		// default for mapping purposes
		if (!expressionFound && !formatFound) {
			// create no property for unmapped marker entities
			if (!(endPoint instanceof DataInterchangeFileCSV) || !path.isMarkLatestImport) {
				// create no property if mapping is used and this attribute is unmapped
				if(!mappingFound || path.mappings.isMapped(f)) {
					path.createAttributeMapping(f as LAttribute, doc, parentElement, endPoint)
				}
			}
		}
		createAttributeMapping(path, f, doc, parentElement, byAttribute)
		// default mapping for xml and csv
		if (!mappingFound && !path.isMarkLatestImport && (endPoint instanceof DataInterchangeFileXML||endPoint instanceof DataInterchangeFileCSV)) {
			addMapping(doc, parentElement, f.toName, f.toName, byAttribute)
		}
	}
	
	def boolean isId(LFeature f) {
		if(f instanceof LEntityAttribute) {
			return (f as LEntityAttribute).id || (f as LEntityAttribute).uuid
		}
		return false
	}
	
	protected def boolean hasBlob(DataInterchangeBean path) {
		for(mapping : path.mappings) {
			if(mapping instanceof DataInterchangeBlobMapping) {
				return true
			}
		}
	}

	protected def void createAttributeMapping(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, boolean byAttribute) {
		for(mapping : path.mappings) {
			if(f.name.equals(mapping.property.name)) {
				if(mapping.data === null || mapping.data.empty) {
					addMapping(doc, parentElement, f.toName, f.toName, byAttribute)
				} else {
					addMapping(doc, parentElement, f.toName, mapping.data, byAttribute)
				}
			}
		}
	}
	
	def createAttributeMapping(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, DataInterchangeFile endPoint) {
		var etype = dtType.getBasicType(f)
		// add enum decoder
		if(etype == EType.LENUM){
			var value = createProperty(doc, parentElement, f.toName, "Enum", etype)
			createDecodeParam("jb", doc, value, "enumType", f.type.toQualifiedName.toString)
			
			var enumsliterals = f.type.eContents;
			for(literal : enumsliterals){
				val enumname = literal.fullyQualifiedName.lastSegment
				// extra fileds
				createDecodeParam("jb", doc, value, enumsliterals.indexOf(literal).toString, enumname) 
				// mandatory fields 
				createDecodeParam("jb", doc, value, enumname, enumname)
			}
		}
		else{
			// add format decoder
			var Element value = null
			value = createProperty(doc, parentElement, f.toName, f.decoder, etype)
			createDefaultDecoderFormat("jb", doc, value, f, endPoint)
		}
	}
	
	protected def createDefaultDecoderFormat(String prefix, Document doc, Element parentElement, LAttribute f, DataInterchangeFile endPoint) {
		var etype = dtType.getBasicType(f)
		if (etype == EType.DATE) {
			createDecodeParam(prefix, doc, parentElement, "format", "yyyy-MM-dd'T'HH:mm:ss")
		} else if((etype == EType.DOUBLE || etype == EType.FLOAT) && endPoint.locale !== null) {
			createDecodeParam(prefix, doc, parentElement, "format", "#.######")
			if (endPoint.locale !== null) {
				createDecodeParam(prefix, doc, parentElement, "locale-language", endPoint.locale.split("_").get(0))
				if(endPoint.locale.split("_").size > 1) {
					createDecodeParam(prefix, doc, parentElement, "locale-country", endPoint.locale.split("_").get(1))
				}
			}
		}
	}
	
	protected def boolean createAttributeFormat(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement, DataInterchangeFile endPoint) {
		var formatFound = false
		for (format : path.format) {
			// is there a format modeled for this attribute ?
			if (f.toName.equals(format.targetProperty.toName)) {
				var value = createProperty(doc, parentElement, f.toName, f.decoder, dtType.getBasicType(f))
				if(format.format !== null) {
					createDecodeParam("jb", doc, value, "format", format.format)
			
					if (endPoint.locale !== null) {
						createDecodeParam("jb", doc, value, "locale-language", endPoint.locale.split("_").get(0))
						if(endPoint.locale.split("_").size > 1) {
							createDecodeParam("jb", doc, value, "locale-country", endPoint.locale.split("_").get(1))
						}
					}
			
				}
				formatFound = true
			}
		}
		return formatFound
	}
	
	protected def boolean createAttributeExpression(DataInterchangeBean path, LAttribute f, Document doc, Element parentElement) {
		var expressionFound = false
		for (expr : path.expression) {
			switch(expr) {
				DataInterchangeEntityExpression: {
					// is there an entity expression for this attribute ?
					if (f.toName.equals((expr as DataInterchangeEntityExpression).targetProperty.toName)) {
						createExpression(doc, parentElement, f.toName, (expr as DataInterchangeEntityExpression).entity.toName+"."+(expr as DataInterchangeEntityExpression).property.toName)
						expressionFound = true
					}
				}
				DataInterchangePredefinedExpression: {
					// is there an predefined expression modeled for this attribute ?
					if (f.toName.equals((expr as DataInterchangePredefinedExpression).targetProperty.toName)) {
						if("UUID".equals((expr as DataInterchangePredefinedExpression).bean.literal)) {
							createExpression(doc, parentElement, f.toName, "PUUID."+(expr as DataInterchangePredefinedExpression).beanType.getName)
						} else {
							createExpression(doc, parentElement, f.toName, "PTIME."+(expr as DataInterchangePredefinedExpression).bean.getName+(expr as DataInterchangePredefinedExpression).beanType.getName)
						}
						expressionFound = true
					}
				}
			}
		}
		return expressionFound
	}
	
	protected def void createLookupKeys(DataInterchangeBean path, Document doc, Element locator, String map, boolean byAttribute, DataInterchangeFile endPoint) {
		var pCnt = 0
		for(key:path.lookupKeys) {
			if(key.property.eContainer.equals(path.entity)) {
				var daoValue = createDaoParam(doc, locator, '''param«pCnt»''', key.property.decoder, map, path.mappings.mapElement(key.property.name), byAttribute)
				createDefaultDecoderFormat("dao", doc, daoValue, key.property, endPoint)
			} else {
				for(lookup:path.lookup) {
					if(lookup.queryProperty.equals(key.property)) {
						var daoValue = createDaoParam(doc, locator, '''param«pCnt»''', key.property.decoder, map, lookup.elementMap.replace(map, "").replace("//", ""), byAttribute)
						createDefaultDecoderFormat("dao", doc, daoValue, key.property, endPoint)
					}
				}
			}
			pCnt ++
		}
	}
	
	def boolean hasAnnotation(LFeature feature, Class<?> annotationType) {
		for(anno:(feature).annotationInfo.annotations) {
			if (anno.annotation.annotationType.fullyQualifiedName.toString.equals(annotationType.name)) {
				return true;
			}
		}
		return false;
	}
	
	def boolean isInternal(LFeature f) {
		if("disposed".equals(f.toName)) {
			return true
		}
		if(f instanceof LEntityAttribute) {
			if((f as LEntityAttribute).version) {
				return true
			}
			if(f.hasAnnotation(Dirty) || f.hasAnnotation(UpdateAt) || f.hasAnnotation(UpdateBy) || f.hasAnnotation(CreateAt) || f.hasAnnotation(CreateBy)) {
				return true
			}
		}
		return false
	}
	
	protected def boolean hasAttributeMapping(DataInterchangeBean path) {
		for(mapping : path.mappings) {
			for (a : path.entity.allAttributes) {
				if(a.name.equals(mapping.property.name)) {
					return true
				}
			}
		}
		return false
	}

	protected def boolean hasReferenceLookup(DataInterchangeBean path){
		for(lu : path.lookup) {
			for(a : path.entity.getAllReferences) {
				if(a.name.equals(lu.dataMap)){
					return true
				}
			}
		}
		return false
	}
	
	protected def boolean hasReferenceExport(DataInterchangeBean path){
		for(expose : path.exportExposes) {
			for(a : path.entity.getAllReferences) {
				if(a.name.equals(expose.refEntity.name)){
					return true
				}
			}
		}
		return false
	}

	def boolean isMapped(EList<DataInterchangeMapping> list, LFeature attribute) {
		if(attribute instanceof LEntityAttribute) {
			return !list.filter[it|it.property.name.equals(attribute.name)].empty	
		}
		return false;
	}
	
	def String mapElement(EList<DataInterchangeMapping> mappings, String propertyName) {
		var element = (mappings.findFirst[it.property.name.equals(propertyName) && it instanceof DataInterchangeValueMapping] as DataInterchangeValueMapping)?.data
		if(element === null) {
			element = propertyName
		}
		return element
	}
	
	def Element createXmlBean(Document doc, Element parent, LEntity entity, EList<DataInterchangeFormat> formats, String currentKey, DataInterchangeBean path, DataInterchange dataInterchange) {
		var LAttribute prevAttr = null
		var bean = doc.createElement('''«IF path.nodeName !== null»«path.nodeName»«ELSE»«entity.toName»«ENDIF»''')
		var pi = doc.createProcessingInstruction(currentKey, "")
		if(parent === null) {
			doc.documentElement.appendChild(pi)
			doc.documentElement.appendChild(bean)
		} else {
			bean = doc.createElement('''«IF path.nodeName !== null»«path.nodeName»«ELSE»«entity.toName»«ENDIF»''')
			parent.appendChild(pi)
			parent.appendChild(bean)
		}
		for(p:entity.allAttributes) {
			if(useFeature(p, path, dataInterchange)) {
				if(p instanceof LAttribute && p.type instanceof LBean) {
					prevAttr = p as LAttribute
				} else {
					var format = null as DataInterchangeFormat
					for (step : formats) {
						// is there a format modeled for this attribute ?
						if ((p as LFeature).toName.equals(step.targetProperty.toName)) {
							if	(step.format !== null) {
								format = step
							}
						}
					}
					var property = doc.createElement(p.toName)
					property.textContent = encodeFreemarker(entity.toName, p, format, "", true, -1, prevAttr?.toName)
					bean.appendChild(property)
				}
			}
		}
		for(e : path.exportExposes){
			var expose = e
			var segments = <String>newArrayList()
			segments.add(expose.refEntity.name)
			while(expose.refProperty === null){
				expose = expose.subExpose
				segments.add(expose.refEntity.name)
			}

			var property = doc.createElement(expose.refProperty.toName)
			var pathToProperty = segments.join(".")

			property.textContent = encodeFreemarker('''«entity.toName».«pathToProperty»''', expose.refProperty, null as DataInterchangeFormat, "", true, -1, "");
			bean.appendChild(property)
		}
		var pa = doc.createProcessingInstruction(currentKey, "")
		if(parent === null) {
			doc.documentElement.appendChild(pa)
		} else {
			parent.appendChild(pa)
		}
		return bean
	}
	
	def boolean useFeature(LFeature f, DataInterchangeBean path, DataInterchange dataInterchange) {
		var mappingFound = hasAttributeMapping(path)
		if (!isInternal(f) &&				// don't export version etc.
			!path.isMarkLatestImport &&	(!mappingFound || path.mappings.isMapped(f))) {
				if(dataInterchange.mode == EntityManagerMode.PERSIST) {
					if(isId(f)) {
						return false
					}
					return true
				} else {
					return true
				}
		}
		return false
	}
	
	def String decoder(LFeature f) {
		return getPrimitiveDataTypeName(f as LAttribute)
	}

	def String decoder(LEntityAttribute f) {
		return getPrimitiveDataTypeName(f)
	}

	def String getPrimitiveDataTypeName(LAttribute attribute) {
		var eType = dtType.getBasicType(attribute)
		var String typeName = null
		if	(eType == EType.DATE) {
			typeName = "Date"
		}
		else if (attribute.type !== null && (attribute.type instanceof LDataType) && (attribute.type as LDataType).jvmTypeReference !== null) {
			typeName = (attribute.type as LDataType).jvmTypeReference.simpleName
		} else {
			typeName = attribute.type.name
		}
		if ("int".equals(typeName)) {
			typeName = "Integer"
		}
		return typeName.toFirstUpper
	}

//	<ftl:freemarker applyOnElement="org.eclipse.osbp.foodmart.entities.Mregion">
//		<ftl:template>
//		<!--
//			<#list vector as Mregion>
//				<Mregion>
//    				<sales_city>${Mregion.sales_city}</sales_city>
//    				<#list Mregion.stores as Mstore>
//						<store_type>${Mstore.store_type}</store_type>
//    				</#list>
//				</Mregion>
//			</#list>
//		-->
//  	</ftl:template>
//	</ftl:freemarker>
				
	def String createXmlTemplate(Document doc, HashMap<String,String> substitutionMap, EList<DataInterchangeBean> path)	{
        var source = new DOMSource(doc)
        var res = new DataResult()
		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.transform(source, res)
        var output = res.result
        
        // processing the template string for filtered information
        for(f: path){ // for exclusion
        	if(f.getExportFilter !== null && f.getExportFilter.hiddenproperties !== null && !f.getExportFilter.hiddenproperties.empty){
        		for(hiddenprop : f.getExportFilter.hiddenproperties){ 
        			var attrname = hiddenprop.property.name
        			if(output.contains(attrname)){
	        			var targetstatement = output.substring(output.indexOf("<"+attrname+">${("+f.entity.name),output.indexOf("</"+attrname+">") + ("</"+attrname+">").length)
	        			output = output.replace(targetstatement, "")
        			}
        		}
        	}
        }
        // cleaning whitespaces
        var result = "" 
        for(f : output.split("\r")){
        	if(!f.trim.isEmpty){
        		result = result.concat(f)
        	}
        }
        // processing instructions are embedded in question marks - they must be replaced
        for(k:substitutionMap.keySet) {
        	result = result.replaceFirst(k, '''#list «substitutionMap.get(k)»''')
        }
        for(l:substitutionMap.keySet) {
        	result = result.replaceFirst(l, '''/#list''')
        }
        return result.replace("&lt;","<").replace("&gt;",">").replace("<?","<").replace("?>",">")//.replace("</#","\n</#") 
	}
	
	def String createCsvTemplate(String rootEntityName, List<LFeature> fieldList, String delimiter, String quote, EList<DataInterchangeBean> paths)	{
		var tmpList = <String>newArrayList()
		var fldList = <String>newArrayList
		var LAttribute prevAttr = null
		for(field:fieldList) {
			if(field instanceof LAttribute && field.type instanceof LBean) {
				prevAttr = field as LAttribute
			} else {
				tmpList.add(encodeFreemarker(rootEntityName, field, paths, quote, false, -1, prevAttr?.toName))
				fldList.add(field.toName)
			}
		}
		var body = '''
		«fldList.join(delimiter)»
		<#list vector as «rootEntityName»>
		«tmpList.join(delimiter)»
		</#list>'''
        return body
	}

	def String createFixedTemplate(String rootEntityName, List<LFeature> fieldList, EList<DataInterchangeBean> paths)	{
		var tmpList = <String>newArrayList()
		for(path:paths) {		
			for(map:path.mappings) {
				var column = map as DataInterchangeFixedColumnMapping
				tmpList.add(encodeFreemarker(rootEntityName, column.property, paths, null, false, column.length, null))
			}
		}		
		var body = '''
		<#list vector as «rootEntityName»>
		«tmpList.join()»
		</#list>'''
        return body
	}

	def String encodeFreemarker(String entityName, LFeature field, EList<DataInterchangeBean> paths, String quote, boolean encodeHtml, int length, String beanPrefix) {
		var format = null as DataInterchangeFormat
		var LEntity entity = null
		if(field.eContainer instanceof LEntity) {
			entity = field.eContainer as LEntity
			for	(path : paths) {
				if (path.entity.equals(entity)) {
					for (step : path.format) {
						// is there a format modeled for this attribute ?
						if (field.toName.equals(step.targetProperty.toName)) {
							if	(step.format !== null) {
								format = step
							}
						}
					}
				}
			}
		}
		return encodeFreemarker(entityName, field, format, quote, encodeHtml, length, beanPrefix)
	}

	def String encodeFreemarker(String entityName, LFeature field, DataInterchangeFormat format, String quote, boolean encodeHtml, int length, String beanPrefix) {
		var EType etype = null
		var String fldName = null
		if(field instanceof LEntityAttribute) {
			fldName = '''«entityName».«field.toName»'''
			etype = dtType.getBasicType(field)
		} 
		if(field instanceof LBeanAttribute) {
			fldName = '''«entityName».«beanPrefix».«field.toName»'''
			etype = dtType.getBasicType(field)
		}
		if(field instanceof LEntityAttribute || field instanceof LBeanAttribute) {
			if	(etype == EType.BOOLEAN) {
				return '''${(«fldName»?c«fixedLength(length)»)!«fixedLength(length)»}'''
			}
			else if	(format !== null) {
				return '''${(«fldName»?string["«format.format»"]«fixedLength(length)»)!«fixedLength(length)»}'''
			}
			else if	(etype == EType.DATE) {
				return '''${(«fldName»?datetime?iso_local_ms_nz)«fixedLength(length)»!«fixedLength(length)»}'''
			}
			else if	(etype == EType.STRING) {
				return '''«quote»${(«fldName»«IF encodeHtml»?html«ENDIF»«fixedLength(length)»)!«fixedLength(length)»}«quote»'''
			} 
			else {
				return '''${(«fldName»)«fixedLength(length)»!«fixedLength(length)»}'''
			}
		} 
		if(field instanceof LEntityReference) {
			etype = dtType.getBasicType((field as LEntityReference).type.primaryKeyAttribute)
			if	(etype == EType.STRING) {
				return '''«quote»${(«entityName».«field.toName».«(field as LEntityReference).type.primaryKeyAttribute.name»«fixedLength(length)»)!«fixedLength(length)»}«quote»'''
			} else {
				return '''${(«entityName».«field.toName».«(field as LEntityReference).type.primaryKeyAttribute.name»«fixedLength(length)»)!«fixedLength(length)»}'''
			}
		}
	}	
	
	def fixedLength(int length)
		'''«IF length > 0»?right_pad(«length»)[0..*«length»]«ENDIF»'''
	
	/* create a multistage left joined query to climb up along the one to many relations until import marker */
	def String query(LEntity entity, DataInterchangeLookup lookup, int paramCnt) {
		var pCnt = paramCnt
		var aliasCnt = 0
		var select = '''«entity.toName» x«aliasCnt»'''
		var joinList = <String>newArrayList
		var whereList = <String>newArrayList
		var qstr = '''x«aliasCnt».«lookup.queryProperty.toName» = :param«pCnt++»'''
		whereList.add(qstr)
		if(lookup.condition !== null) {
			var lstr = '''x«aliasCnt».«lookup.condition.refProperty.toName» «lookup.condition.operator» «IF lookup.condition.operand instanceof DataInterchangeLookupFilterOperandString»'«(lookup.condition.operand as DataInterchangeLookupFilterOperandString).value»'«ELSE»:param«pCnt++»«ENDIF»'''
			if(lookup.condition.subcondition !== null) {
				lstr = lstr + " " + lookup.condition.operator2.literal + " "
				lstr = lookup.condition.subcondition.iterateCondition(lstr, aliasCnt, pCnt)
			}
			whereList.add("("+lstr+")")
		}
		if (lookup.markerPath !== null) {
			for(markerEntity:lookup.markerPath.path) {
				aliasCnt = aliasCnt + 1
				if (markerEntity.markLatest) {
					qstr = '''x«aliasCnt».«markerEntity.markerProperty.toName» = 1'''
					whereList.add(qstr)
				}
				for(ff:entity.features) {
					if (ff instanceof LReference && !ff.toMany) {
						if (markerEntity.markerEntity.toName.equals((ff.type as LEntity).toName)) {
							qstr = '''x«aliasCnt-1».«ff.toName» x«aliasCnt»'''
							joinList.add(qstr)
						}
					}
				}
			}
		}
		return '''from «select»«IF joinList.size>0» left join «ENDIF»«joinList.join(" left join ")» where «whereList.join(" and ")»'''
	}
	
	def String iterateCondition(DataInterchangeLookupFilterCondition condition, String input, int aliasCnt, int paramCnt) {
		var pCnt = paramCnt
		var lstr = '''«input»x«aliasCnt».«condition.refProperty.toName» «condition.operator» «IF condition.operand instanceof DataInterchangeLookupFilterOperandString»'«(condition.operand as DataInterchangeLookupFilterOperandString).value»'«ELSEIF !condition.operator.literal.startsWith("is")»:param«pCnt++»«ENDIF»'''
		if(condition.subcondition !== null) {
			lstr = lstr + " " + condition.operator2.literal + " "
			lstr = condition.subcondition.iterateCondition(lstr, aliasCnt, pCnt)
		}
		return lstr
	}

	def void iterateConditionParameter(DataInterchangeLookupFilterCondition condition, Document doc, Element locator, EList<DataInterchangeMapping> mappings, String autoMapping, int paramCnt, boolean byAttribute) {
		var pCnt = paramCnt
		if(condition.operand instanceof DataInterchangeLookupFilterOperandProperty && !condition.operator.literal.startsWith("is")) {
			var prop = (condition.operand as DataInterchangeLookupFilterOperandProperty).refProperty
			for(mapping:mappings) {
				if(mapping.property.equals(prop)) {
					if(mapping.data === null) {
						createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, autoMapping, prop.toName, byAttribute)
					} else {
						createDaoParam(doc, locator, '''param«paramCnt»''', prop.type.name.toFirstUpper, mapping.data, prop.toName, byAttribute)
					}
					pCnt ++
				}
			}
		}
		if(condition.subcondition !== null) {
			condition.subcondition.iterateConditionParameter(doc, locator, mappings, autoMapping, pCnt, byAttribute)
		}
	}
	
	def String queryKeys(DataInterchangeBean bean) {
		var pCnt = 0
		var eCnt = -1
		var LEntity oldEntity = null
		var select = '''«bean.entity.toName» x«pCnt»'''
		var rootAlias = '''x«pCnt»'''
		var whereList = <String>newArrayList
		for(key:bean.lookupKeys) {
			if(key.property.eContainer.equals(bean.entity)) {
				if(!key.property.eContainer.equals(oldEntity)) {
					eCnt ++
					oldEntity = key.property.eContainer as LEntity
				}
				var qstr = '''x«eCnt».«key.property.toName» = :param«pCnt»'''
				whereList.add(qstr)
			} else {
				for(lookup:bean.lookup) {
					if(lookup.queryProperty.equals(key.property)) {
						if(!lookup.queryProperty.equals(oldEntity)) {
							eCnt ++
							oldEntity = lookup.queryProperty as LEntity
						}
						select = '''«select» left join «lookup.entity.toName» x«pCnt» on(x«pCnt»=«rootAlias».«lookup.targetProperty.toName»)'''
						var qstr = '''x«eCnt».«key.property.toName» = :param«pCnt»'''
						whereList.add(qstr)
					}
				}
			}
			pCnt ++;
		}
		return '''from «select» where «whereList.join(" and ")»'''
	}

	def String queryVersion(DataInterchangeBean bean) {
		var select = '''«bean.entity.toName» x'''
		var qstr = '''x.«bean.entity.idAttributeName» = :param'''
		return '''from «select» where «qstr»'''
	}
	
	def boolean containsFeature(List<DataInterchangeExportHide> list, LFeature f){
		for(exclude : list){
			if(exclude.property.equals(f)){
				return true
			} 	
		}
		return false
	}

	override createAppendable(EObject context, ImportManager importManager, GeneratorConfig config) {
		// required to initialize the needed builder to avoid deprecated methods
		builder = context.eResource
		// ---------
		addImportFor(importManager, _typeReferenceBuilder
			, FrameworkUtil
			, IDataInterchange
			, StreamSource
			, URL
			, URI
			, InputStream
			, StreamUtils
			, MalformedURLException
			, FileAlreadyExistsException
			, URISyntaxException
			, EntityManager
			, EntityTransaction
			, Logger
			, LoggerFactory
			, Label
			, Button
			, NativeButton
			, ClickListener
			, ClickEvent
			, ContentMode
			, PersistenceUnitProperties
			, HorizontalLayout
			, ProgressBar
			, IEventBroker
			, WorkerThreadRunnable
			, HashMap
			, Executors
			, TimeUnit
			, QueryHints
			, PessimisticLock
			, MissingResourceException
			, MessageFormat
			, EventHandler
			, Event
			, EventUtils
			, EventBrokerMsg
			, Bundle
			, BundleContext
			, List
			, Arrays
			, StringWriter
			, StringReader
			, OutputKeys
			, StreamResult
			, CriteriaBuilder
			, CriteriaQuery
			, Root
			, TypedQuery
			, JoinType
			, Paths
			, Path
			, Files
			, StandardOpenOption
			, BufferedOutputStream
			, BufferedInputStream
			, UI
			, Pair
			, IEntityImportInitializationListener
			, ConstraintViolationException
			, ConstraintViolation
			, EventDispatcherEvent
			, EventDispatcherCommand
			, TransformerConfigurationException
			, SAXException
			, IOException
			, UUID
			, IOException
			, File
			, FileInputStream
			, Properties
			, ProductConfiguration
			, PrintWriter
			, BlobService
			, BlobTypingAPI
			, Component
			, Panel
			, Paths
			, Date
		)
		super.createAppendable(context, importManager, config)
	}
}

Back to the top