Source Code Cross Referenced for ImplementationGeneratorBase.java in  » UML » MetaBoss » com » metaboss » sdlctools » services » codegeneration » storageimplementationgenerator » relational » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » UML » MetaBoss » com.metaboss.sdlctools.services.codegeneration.storageimplementationgenerator.relational 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
0002:        // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
0003:        // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
0004:        // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
0005:        // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0006:        // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0007:        // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
0008:        // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0009:        // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0010:        // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0011:        // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
0012:        // POSSIBILITY OF SUCH DAMAGE.
0013:        //
0014:        // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
0015:        package com.metaboss.sdlctools.services.codegeneration.storageimplementationgenerator.relational;
0016:
0017:        import java.io.File;
0018:        import java.io.FileWriter;
0019:        import java.io.IOException;
0020:        import java.io.PrintWriter;
0021:        import java.util.ArrayList;
0022:        import java.util.Collection;
0023:        import java.util.HashMap;
0024:        import java.util.HashSet;
0025:        import java.util.Iterator;
0026:        import java.util.List;
0027:        import java.util.ListIterator;
0028:        import java.util.Map;
0029:        import java.util.Properties;
0030:        import java.util.Set;
0031:        import java.util.StringTokenizer;
0032:
0033:        import javax.jmi.reflect.JmiException;
0034:
0035:        import org.apache.commons.logging.Log;
0036:        import org.apache.commons.logging.LogFactory;
0037:
0038:        import com.metaboss.enterprise.bo.BOException;
0039:        import com.metaboss.enterprise.bs.BSDomainObjectInvocationException;
0040:        import com.metaboss.enterprise.bs.BSException;
0041:        import com.metaboss.enterprise.bs.BSServiceProviderException;
0042:        import com.metaboss.enterprise.bs.BSUnexpectedProgramConditionException;
0043:        import com.metaboss.enterprise.datatypes.DataTypeTranslationMetadata;
0044:        import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.DataType;
0045:        import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.DataTypeUtils;
0046:        import com.metaboss.sdlctools.models.metabossmodel.datadictionarymodel.TypeTemplate;
0047:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.Enterprise;
0048:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Association;
0049:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.AssociationRole;
0050:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.AssociationRoleCardinalityEnum;
0051:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Attribute;
0052:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Domain;
0053:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Entity;
0054:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.PrimaryKeyElement;
0055:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.Selector;
0056:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.SelectorInputField;
0057:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.domainimplementationmodel.DomainRelationalStorageDefinition;
0058:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.domainimplementationmodel.RelationalAssociationTable;
0059:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.domainimplementationmodel.RelationalEntityTable;
0060:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.domainimplementationmodel.RelationalEntityTableAttributeColumn;
0061:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.domainimplementationmodel.RelationalEntityTableReferenceColumn;
0062:        import com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.systemimplementationmodel.domainimplementationmodel.RelationalReferenceTable;
0063:        import com.metaboss.sdlctools.services.codegeneration.CodeGenerationStylesheetAccessor;
0064:        import com.metaboss.sdlctools.services.codegeneration.CommonUtil;
0065:        import com.metaboss.sdlctools.services.codegeneration.CopyrightUtils;
0066:        import com.metaboss.sdlctools.services.codegeneration.corecodegenerator.EntityUtils;
0067:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STAssociationStylesheet;
0068:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STAttributeStylesheet;
0069:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STDatatypeStylesheet;
0070:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STDatatypeTranslationStylesheet;
0071:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STDomainStylesheet;
0072:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STEntityStylesheet;
0073:        import com.metaboss.sdlctools.services.codegenerationstylesheet.STSelectorInputFieldStylesheet;
0074:        import com.metaboss.util.DirectoryUtils;
0075:        import com.metaboss.util.StringUtils;
0076:        import com.metaboss.util.TemplateUtil;
0077:
0078:        /** Generator of the persistence layer implementation based on oracle DBMS */
0079:        public abstract class ImplementationGeneratorBase {
0080:            // Logger instance
0081:            private static final Log sLogger = LogFactory
0082:                    .getLog(ImplementationGeneratorBase.class);
0083:            private DataBaseMetaData mDataBaseMetaData = null;
0084:
0085:            /** Hide default constructor */
0086:            private ImplementationGeneratorBase() {
0087:            }
0088:
0089:            /** The only publicly available constructor */
0090:            public ImplementationGeneratorBase(
0091:                    DataBaseMetaData pDataBaseMetaData) throws BSException {
0092:                if (pDataBaseMetaData == null)
0093:                    throw new BSUnexpectedProgramConditionException(
0094:                            "pDataBaseMetaData argument can not be null");
0095:                mDataBaseMetaData = pDataBaseMetaData;
0096:            }
0097:
0098:            /** Returns DataBase MetaData for which this generator is setup */
0099:            public DataBaseMetaData getDataBaseMetaData() {
0100:                return mDataBaseMetaData;
0101:            }
0102:
0103:            public String getImplementationJavaPackage(
0104:                    DomainRelationalStorageDefinition pDomainStorage)
0105:                    throws BSException, BOException {
0106:                STDomainStylesheet lDomainStylesheet = CodeGenerationStylesheetAccessor
0107:                        .getDomainStylesheet(pDomainStorage.getDomain());
0108:                return lDomainStylesheet.getStoragePackageName() + "."
0109:                        + getDataBaseMetaData().getImplementationPackageName();
0110:            }
0111:
0112:            public void generateImplementation(String pSourceRootDir,
0113:                    DomainRelationalStorageDefinition pDomainStorage)
0114:                    throws BSException {
0115:                try {
0116:                    Domain lDomain = pDomainStorage.getDomain();
0117:                    String lImplementationJavaPackage = getImplementationJavaPackage(pDomainStorage);
0118:                    // Ensure that directory is available
0119:                    String lImplementationDir = pSourceRootDir
0120:                            + File.separator
0121:                            + StringUtils.replace(lImplementationJavaPackage,
0122:                                    ".", File.separator);
0123:                    DirectoryUtils.ensureNewCleanDirectory(lImplementationDir);
0124:
0125:                    // Generate domain service
0126:                    generateImplementationForDomainService(lImplementationDir,
0127:                            lImplementationJavaPackage, lDomain, pDomainStorage);
0128:                    generateFactoryForDomainService(lImplementationDir,
0129:                            lImplementationJavaPackage, lDomain);
0130:                    // Generate utility class
0131:                    generateImplementationForUtilities(lImplementationDir,
0132:                            lImplementationJavaPackage, lDomain);
0133:                    // Generate selector utility class
0134:                    generateImplementationForSelectors(lImplementationDir,
0135:                            lImplementationJavaPackage, lDomain, pDomainStorage);
0136:                    // Generate type conversions class
0137:                    generateImplementationForTypesConvertor(lImplementationDir,
0138:                            lImplementationJavaPackage, lDomain);
0139:                    // Generate alias factory class
0140:                    generateQueryContext(lImplementationDir,
0141:                            lImplementationJavaPackage, lDomain, pDomainStorage);
0142:
0143:                    // Now generate per-entity classes
0144:                    Collection lEntities = lDomain.getEntities();
0145:                    for (Iterator lEntitiesIterator = lEntities.iterator(); lEntitiesIterator
0146:                            .hasNext();) {
0147:                        Entity lEntity = (Entity) lEntitiesIterator.next();
0148:                        generateImplementationForFactoryObject(
0149:                                lImplementationDir, lImplementationJavaPackage,
0150:                                lEntity);
0151:                        generateImplementationForServiceObject(
0152:                                lImplementationDir, lImplementationJavaPackage,
0153:                                lEntity, pDomainStorage);
0154:                    }
0155:                } catch (IOException e) {
0156:                    throw new BSServiceProviderException(e);
0157:                } catch (BOException e) {
0158:                    throw new BSDomainObjectInvocationException("", e);
0159:                }
0160:            }
0161:
0162:            // Generate an interface for the general domain functions			
0163:            public static void generateImplementationForDomainService(
0164:                    String pImplementationDir, String pImplementationPackage,
0165:                    Domain pDomain,
0166:                    DomainRelationalStorageDefinition pDomainStorage)
0167:                    throws BSException {
0168:                PrintWriter lWriter = null;
0169:                FileWriter lFileWriter = null;
0170:                // Generate full data structure
0171:                try {
0172:                    STDomainStylesheet lDomainStylesheet = CodeGenerationStylesheetAccessor
0173:                            .getDomainStylesheet(pDomain);
0174:                    String lDomainServiceFileName = pImplementationDir
0175:                            + File.separator
0176:                            + lDomainStylesheet.getStorageImplementationName()
0177:                            + ".java";
0178:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
0179:                            lDomainServiceFileName));
0180:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
0181:                    // Package statement
0182:                    lWriter.println("package " + pImplementationPackage + ";");
0183:                    lWriter.println();
0184:                    lWriter
0185:                            .println("import com.metaboss.enterprise.ps.PSObject;");
0186:                    lWriter
0187:                            .println("import com.metaboss.enterprise.ps.PSException;");
0188:                    lWriter
0189:                            .println("import com.metaboss.enterprise.ps.PSIllegalArgumentException;");
0190:                    lWriter
0191:                            .println("import com.metaboss.enterprise.ps.impl.PSObjectImpl;");
0192:                    lWriter.println();
0193:                    // Service interface
0194:                    lWriter.println("public class "
0195:                            + lDomainStylesheet.getStorageImplementationName()
0196:                            + " extends PSObjectImpl implements "
0197:                            + lDomainStylesheet.getStorageInterfaceFullName());
0198:                    lWriter.println("{");
0199:                    lWriter.println();
0200:                    lWriter
0201:                            .println("    /** Returns unique entity type suggested by given string containing instance id. */");
0202:                    lWriter
0203:                            .println("    public String getEntityType(String pEntityInstanceIdString) throws PSException");
0204:                    lWriter.println("    {");
0205:                    lWriter
0206:                            .println("        if (pEntityInstanceIdString == null)");
0207:                    lWriter
0208:                            .println("            throw new PSIllegalArgumentException(\"EntityInstanceIdString argument can not be null\");");
0209:                    // Instance id in our case is ending in -<entity table alias>
0210:                    Collection lEntityTables = pDomainStorage.getEntityTables();
0211:                    for (Iterator lEntityTablesIterator = lEntityTables
0212:                            .iterator(); lEntityTablesIterator.hasNext();) {
0213:                        RelationalEntityTable lEntityTable = (RelationalEntityTable) lEntityTablesIterator
0214:                                .next();
0215:                        lWriter
0216:                                .println("        if (pEntityInstanceIdString.endsWith(\"-"
0217:                                        + lEntityTable.getTableAlias() + "\"))");
0218:                        lWriter.println("            return \""
0219:                                + lEntityTable.getEntity().getRef() + "\";");
0220:                    }
0221:                    // Nothing found
0222:                    lWriter.println("        return null;");
0223:                    lWriter.println("    }");
0224:                    lWriter.println("}");
0225:                } catch (IOException e) {
0226:                    throw new BSException(e);
0227:                } finally {
0228:                    if (lFileWriter != null) {
0229:                        try {
0230:                            lFileWriter.flush();
0231:                        } catch (IOException e) {
0232:                            // Ignore
0233:                        }
0234:                        try {
0235:                            lFileWriter.close();
0236:                        } catch (IOException e) {
0237:                            // Ignore
0238:                        }
0239:                    }
0240:                    if (lWriter != null) {
0241:                        lWriter.flush();
0242:                        lWriter.close();
0243:                    }
0244:                }
0245:            }
0246:
0247:            private static void generateFactoryForDomainService(
0248:                    String pImplementationDir, String pImplementationPackage,
0249:                    Domain pDomain) throws BSException {
0250:                FileWriter lFileWriter = null;
0251:                PrintWriter lWriter = null;
0252:                // Generate services interface
0253:                try {
0254:                    STDomainStylesheet lDomainStylesheet = CodeGenerationStylesheetAccessor
0255:                            .getDomainStylesheet(pDomain);
0256:
0257:                    String lFactoryFileName = pImplementationDir
0258:                            + File.separator
0259:                            + lDomainStylesheet.getStorageFactoryName()
0260:                            + ".java";
0261:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
0262:                            lFactoryFileName));
0263:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
0264:                    lWriter.println("package " + pImplementationPackage + ";");
0265:                    lWriter.println("");
0266:                    lWriter.println("public class "
0267:                            + lDomainStylesheet.getStorageFactoryName()
0268:                            + " implements javax.naming.spi.ObjectFactory");
0269:                    lWriter.println("{");
0270:                    lWriter
0271:                            .println("    private static Object sServiceCreationSemaphore = new Object();");
0272:                    lWriter.println("    private static "
0273:                            + lDomainStylesheet.getStorageImplementationName()
0274:                            + " sServiceImplementation = null;");
0275:                    lWriter
0276:                            .println("    /* Returns the instance of the service */");
0277:                    lWriter
0278:                            .println("    public Object getObjectInstance(Object obj, javax.naming.Name name, javax.naming.Context nameCtx, java.util.Hashtable environment) throws Exception");
0279:                    lWriter.println("    {");
0280:                    lWriter
0281:                            .println("        if (sServiceImplementation == null)");
0282:                    lWriter.println("        {");
0283:                    lWriter
0284:                            .println("            synchronized(sServiceCreationSemaphore)");
0285:                    lWriter.println("            {");
0286:                    lWriter
0287:                            .println("                if (sServiceImplementation == null)");
0288:                    lWriter.println("                {");
0289:                    lWriter
0290:                            .println("                    sServiceImplementation = new "
0291:                                    + lDomainStylesheet
0292:                                            .getStorageImplementationName()
0293:                                    + "();");
0294:                    lWriter.println("                }");
0295:                    lWriter.println("            }");
0296:                    lWriter.println("        }");
0297:                    lWriter.println("        return sServiceImplementation;");
0298:                    lWriter.println("    }");
0299:                    lWriter.println("}");
0300:                } catch (IOException e) {
0301:                    throw new BSException(e);
0302:                } finally {
0303:                    if (lWriter != null) {
0304:                        lWriter.flush();
0305:                        lWriter.close();
0306:                    }
0307:                    if (lFileWriter != null) {
0308:                        try {
0309:                            lFileWriter.flush();
0310:                        } catch (IOException e) {
0311:                            // Ignore
0312:                        }
0313:                        try {
0314:                            lFileWriter.close();
0315:                        } catch (IOException e) {
0316:                            // Ignore
0317:                        }
0318:                    }
0319:                }
0320:            }
0321:
0322:            private static void generateImplementationForFactoryObject(
0323:                    String pImplementationDir, String pImplementationPackage,
0324:                    Entity pEntity) throws BSException {
0325:                FileWriter lFileWriter = null;
0326:                PrintWriter lWriter = null;
0327:                // Generate services interface
0328:                try {
0329:                    STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
0330:                            .getEntityStylesheet(pEntity);
0331:
0332:                    String lFactoryFileName = pImplementationDir
0333:                            + File.separator
0334:                            + lEntityStylesheet.getStorageFactoryName()
0335:                            + ".java";
0336:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
0337:                            lFactoryFileName));
0338:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
0339:                    lWriter.println("package " + pImplementationPackage + ";");
0340:                    lWriter.println("");
0341:                    lWriter.println("public class "
0342:                            + lEntityStylesheet.getStorageFactoryName()
0343:                            + " implements javax.naming.spi.ObjectFactory");
0344:                    lWriter.println("{");
0345:                    lWriter
0346:                            .println("    private static Object sServiceCreationSemaphore = new Object();");
0347:                    lWriter.println("    private static "
0348:                            + lEntityStylesheet.getStorageImplementationName()
0349:                            + " sServiceImplementation = null;");
0350:                    lWriter
0351:                            .println("    /* Returns the instance of the service */");
0352:                    lWriter
0353:                            .println("    public Object getObjectInstance(Object obj, javax.naming.Name name, javax.naming.Context nameCtx, java.util.Hashtable environment) throws Exception");
0354:                    lWriter.println("    {");
0355:                    lWriter
0356:                            .println("        if (sServiceImplementation == null)");
0357:                    lWriter.println("        {");
0358:                    lWriter
0359:                            .println("            synchronized(sServiceCreationSemaphore)");
0360:                    lWriter.println("            {");
0361:                    lWriter
0362:                            .println("                if (sServiceImplementation == null)");
0363:                    lWriter.println("                {");
0364:                    lWriter
0365:                            .println("                    sServiceImplementation = new "
0366:                                    + lEntityStylesheet
0367:                                            .getStorageImplementationName()
0368:                                    + "();");
0369:                    lWriter.println("                }");
0370:                    lWriter.println("            }");
0371:                    lWriter.println("        }");
0372:                    lWriter.println("        return sServiceImplementation;");
0373:                    lWriter.println("    }");
0374:                    lWriter.println("}");
0375:                } catch (IOException e) {
0376:                    throw new BSException(e);
0377:                } finally {
0378:                    if (lWriter != null) {
0379:                        lWriter.flush();
0380:                        lWriter.close();
0381:                    }
0382:                    if (lFileWriter != null) {
0383:                        try {
0384:                            lFileWriter.flush();
0385:                        } catch (IOException e) {
0386:                            // Ignore
0387:                        }
0388:                        try {
0389:                            lFileWriter.close();
0390:                        } catch (IOException e) {
0391:                            // Ignore
0392:                        }
0393:                    }
0394:                }
0395:            }
0396:
0397:            protected void generateImplementationForServiceObject(
0398:                    String pImplementationDir, String pImplementationPackage,
0399:                    Entity pEntity,
0400:                    DomainRelationalStorageDefinition pDomainStorage)
0401:                    throws BSException {
0402:                FileWriter lFileWriter = null;
0403:                PrintWriter lWriter = null;
0404:                // Generate services interface
0405:                try {
0406:                    // This should be in storage definition latter on
0407:                    boolean lUpdateInBatches = false;
0408:                    // Get some stylesheets
0409:                    STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
0410:                            .getEntityStylesheet(pEntity);
0411:
0412:                    DataType lInstanceIdDatatype = pEntity
0413:                            .getInstanceIdDataType();
0414:                    STDatatypeStylesheet lInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
0415:                            .getDatatypeStylesheet(lInstanceIdDatatype);
0416:                    STDatatypeTranslationStylesheet lInstanceIdDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
0417:                            .getDatatypeTranslationStylesheet(lInstanceIdDatatype);
0418:                    DataTypeTranslationMetadata.SqlType lInstanceIdDatatypeSqlType = DataTypeTranslationMetadata.SqlType
0419:                            .createFromName(lInstanceIdDatatypeTranslationStylesheet
0420:                                    .getSqlTypeName());
0421:
0422:                    boolean lIsModifiable = pEntity.isModifiable();
0423:                    DataType lVersionIdDatatype = (lIsModifiable) ? pEntity
0424:                            .getVersionIdDataType() : null;
0425:                    STDatatypeStylesheet lVersionIdDatatypeStylesheet = (lIsModifiable) ? CodeGenerationStylesheetAccessor
0426:                            .getDatatypeStylesheet(lVersionIdDatatype)
0427:                            : null;
0428:                    STDatatypeTranslationStylesheet lVersionIdDatatypeTranslationStylesheet = (lIsModifiable) ? CodeGenerationStylesheetAccessor
0429:                            .getDatatypeTranslationStylesheet(lVersionIdDatatype)
0430:                            : null;
0431:                    DataTypeTranslationMetadata.SqlType lVersionIdDatatypeSqlType = (lIsModifiable) ? DataTypeTranslationMetadata.SqlType
0432:                            .createFromName(lVersionIdDatatypeTranslationStylesheet
0433:                                    .getSqlTypeName())
0434:                            : null;
0435:
0436:                    boolean lHasState = pEntity.getStateMachine() != null;
0437:                    DataType lStateDatatype = (lHasState) ? pEntity
0438:                            .getStateDataType() : null;
0439:                    STDatatypeStylesheet lStateDatatypeStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
0440:                            .getDatatypeStylesheet(lStateDatatype)
0441:                            : null;
0442:                    STDatatypeTranslationStylesheet lStateDatatypeTranslationStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
0443:                            .getDatatypeTranslationStylesheet(lStateDatatype)
0444:                            : null;
0445:                    DataTypeTranslationMetadata.SqlType lStateDatatypeSqlType = (lHasState) ? DataTypeTranslationMetadata.SqlType
0446:                            .createFromName(lStateDatatypeTranslationStylesheet
0447:                                    .getSqlTypeName())
0448:                            : null;
0449:
0450:                    DataType lCollectionSizeDatatype = pEntity
0451:                            .getCollectionSizeDataType();
0452:                    STDatatypeStylesheet lCollectionSizeDatatypeStylesheet = CodeGenerationStylesheetAccessor
0453:                            .getDatatypeStylesheet(lCollectionSizeDatatype);
0454:                    STDatatypeTranslationStylesheet lCollectionSizeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
0455:                            .getDatatypeTranslationStylesheet(lCollectionSizeDatatype);
0456:                    DataTypeTranslationMetadata.SqlType lCollectionSizeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
0457:                            .createFromName(lCollectionSizeDatatypeTranslationStylesheet
0458:                                    .getSqlTypeName());
0459:
0460:                    DataType lCollectionOffsetDatatype = pEntity
0461:                            .getCollectionOffsetDataType();
0462:                    STDatatypeTranslationStylesheet lCollectionOffsetDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
0463:                            .getDatatypeTranslationStylesheet(lCollectionOffsetDatatype);
0464:                    DataTypeTranslationMetadata.SqlType lCollectionOffsetDatatypeSqlType = DataTypeTranslationMetadata.SqlType
0465:                            .createFromName(lCollectionOffsetDatatypeTranslationStylesheet
0466:                                    .getSqlTypeName());
0467:
0468:                    DataType lSubsetSizeDatatype = pEntity
0469:                            .getSubsetSizeDataType();
0470:                    STDatatypeTranslationStylesheet lSubsetSizeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
0471:                            .getDatatypeTranslationStylesheet(lSubsetSizeDatatype);
0472:                    DataTypeTranslationMetadata.SqlType lSubsetSizeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
0473:                            .createFromName(lSubsetSizeDatatypeTranslationStylesheet
0474:                                    .getSqlTypeName());
0475:
0476:                    // Some often used conditions
0477:                    boolean lHasPrimaryKey = !pEntity.getPrimaryKeyElements()
0478:                            .isEmpty();
0479:
0480:                    // Some often used values
0481:                    Collection lAttributes = pEntity.getAttributes();
0482:                    Collection lReferences = pEntity.getReferences();
0483:                    Collection lCombinedReferences = pEntity
0484:                            .getCombinedReferences();
0485:                    List lSupertypes = new ArrayList();
0486:                    if (pEntity.getSupertype() != null) {
0487:                        for (Entity lSupertype = pEntity.getSupertype(); lSupertype != null; lSupertype = lSupertype
0488:                                .getSupertype())
0489:                            lSupertypes.add(lSupertype);
0490:                    }
0491:                    List lSupertypesAndSelf = new ArrayList();
0492:                    lSupertypesAndSelf.add(pEntity);
0493:                    lSupertypesAndSelf.addAll(lSupertypes);
0494:
0495:                    // For each many-to-many association where we are aggregators we have to look after removal and insertion of records
0496:                    Collection lAgregatedManyToManyReferences = pEntity
0497:                            .getAgregatedManyToManyReferences();
0498:
0499:                    // If this entity has selfreference roles (association with the entity itself
0500:                    // or any of it's subtypes or supertypes) special care must be taken on batching as simply 
0501:                    // wholesale insert of parent and child will not work
0502:                    List lSelfReferenceRoles = new ArrayList();
0503:                    {
0504:                        // Build set of selftypes - referernce to which is like selfreference 
0505:                        for (Iterator lCombinedReferencesIterator = lCombinedReferences
0506:                                .iterator(); lCombinedReferencesIterator
0507:                                .hasNext();) {
0508:                            AssociationRole lReference = (AssociationRole) lCombinedReferencesIterator
0509:                                    .next();
0510:                            if (!CommonUtil
0511:                                    .doesEntityStoreReference(lReference))
0512:                                continue; // Only interested in role, which have refence in the entity
0513:                            if (!lSupertypesAndSelf.contains(lReference
0514:                                    .getEntity()))
0515:                                continue; // Only interested in association which have selfreference to same entity or its subtypes
0516:                            lSelfReferenceRoles.add(lReference);
0517:                        }
0518:                    }
0519:                    RelationalEntityTable lEntityTable = pDomainStorage
0520:                            .getEntityTable(pEntity);
0521:
0522:                    String lEntityTableName = lEntityTable.getNameOverride();
0523:                    if (lEntityTableName == null
0524:                            || lEntityTableName.length() == 0)
0525:                        lEntityTableName = lEntityTable.getNameSuggestion();
0526:
0527:                    String lEntityTableAlias = lEntityTable.getTableAlias();
0528:
0529:                    String lInstanceIdColumnName = lEntityTable
0530:                            .getInstanceIdColumnNameOverride();
0531:                    if (lInstanceIdColumnName == null
0532:                            || lInstanceIdColumnName.length() == 0)
0533:                        lInstanceIdColumnName = lEntityTable
0534:                                .getInstanceIdColumnNameSuggestion();
0535:
0536:                    String lVersionIdColumnName = null;
0537:                    if (lIsModifiable) {
0538:                        lVersionIdColumnName = lEntityTable
0539:                                .getVersionIdColumnNameOverride();
0540:                        if (lVersionIdColumnName == null
0541:                                || lVersionIdColumnName.length() == 0)
0542:                            lVersionIdColumnName = lEntityTable
0543:                                    .getVersionIdColumnNameSuggestion();
0544:                    }
0545:
0546:                    String lStateColumnName = null;
0547:                    if (lHasState) {
0548:                        lStateColumnName = lEntityTable
0549:                                .getStateColumnNameOverride();
0550:                        if (lStateColumnName == null
0551:                                || lStateColumnName.length() == 0)
0552:                            lStateColumnName = lEntityTable
0553:                                    .getStateColumnNameSuggestion();
0554:                    }
0555:
0556:                    // Find out if this entity has LOBs (can only be in attributes)
0557:                    boolean lHasBlobs = false;
0558:                    boolean lHasClobs = false;
0559:                    boolean lHasOrdering = false;
0560:                    for (Iterator lAttributesIterator = lAttributes.iterator(); ((lHasBlobs == false)
0561:                            || (lHasBlobs == false) || (lHasOrdering == false))
0562:                            && (lAttributesIterator.hasNext());) {
0563:                        Attribute lAttribute = (Attribute) lAttributesIterator
0564:                                .next();
0565:                        STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
0566:                                .getDatatypeTranslationStylesheet(lAttribute
0567:                                        .getDataType());
0568:                        DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
0569:                                .createFromName(lAttributeDatatypeTranslationStylesheet
0570:                                        .getSqlTypeName());
0571:                        if (lHasBlobs == false
0572:                                && lAttributeDatatypeSqlType
0573:                                        .equals(DataTypeTranslationMetadata.SQL_BLOB))
0574:                            lHasBlobs = true;
0575:                        else if (lHasClobs == false
0576:                                && lAttributeDatatypeSqlType
0577:                                        .equals(DataTypeTranslationMetadata.SQL_CLOB))
0578:                            lHasClobs = true;
0579:                        // Work on ordering
0580:                        if (lHasOrdering == false
0581:                                && lAttribute.isUsedForOrdering())
0582:                            lHasOrdering = true;
0583:                    }
0584:                    String lFactoryFileName = pImplementationDir
0585:                            + File.separator
0586:                            + lEntityStylesheet.getStorageImplementationName()
0587:                            + ".java";
0588:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
0589:                            lFactoryFileName));
0590:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
0591:                    // Package statement
0592:                    lWriter.println("package " + pImplementationPackage + ";");
0593:                    lWriter.println("");
0594:                    if (lHasBlobs || lHasClobs) {
0595:                        lWriter.println("import java.util.Iterator;");
0596:                    }
0597:                    lWriter.println("import java.util.Set;");
0598:                    lWriter.println("import java.util.ArrayList;");
0599:                    lWriter.println("import org.apache.commons.logging.Log;");
0600:                    lWriter
0601:                            .println("import org.apache.commons.logging.LogFactory;");
0602:                    lWriter
0603:                            .println("import com.metaboss.enterprise.datatypes.DataTypeValidationException;");
0604:                    lWriter
0605:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForEmptyInstanceException;");
0606:                    lWriter
0607:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForConcealedInstanceException;");
0608:                    lWriter
0609:                            .println("import com.metaboss.enterprise.ps.STCollectionDetails;");
0610:                    lWriter
0611:                            .println("import com.metaboss.enterprise.ps.STOrderingDetails;");
0612:                    lWriter
0613:                            .println("import com.metaboss.enterprise.ps.PSException;");
0614:                    lWriter
0615:                            .println("import com.metaboss.enterprise.ps.PSUnexpectedProgramConditionException;");
0616:                    lWriter
0617:                            .println("import com.metaboss.enterprise.ps.PSIllegalArgumentException;");
0618:                    lWriter
0619:                            .println("import com.metaboss.enterprise.ps.PSAttributeConstraintViolationException;");
0620:                    lWriter
0621:                            .println("import com.metaboss.enterprise.ps.PSAssociationConstraintViolationException;");
0622:                    lWriter
0623:                            .println("import com.metaboss.enterprise.ps.PSDataSourceOperationInvocationException;");
0624:                    lWriter
0625:                            .println("import com.metaboss.enterprise.ps.PSUpdateDataIntegrityViolationException;");
0626:                    lWriter
0627:                            .println("import com.metaboss.enterprise.ps.impl.PSObjectImpl;");
0628:                    lWriter.println();
0629:                    lWriter.print("public class "
0630:                            + lEntityStylesheet.getStorageImplementationName()
0631:                            + " extends PSObjectImpl implements "
0632:                            + lEntityStylesheet.getStorageInterfaceFullName());
0633:                    lWriter.println("{");
0634:                    // Commons Logging instance.
0635:                    lWriter
0636:                            .println("    private static final Log sLogger = LogFactory.getLog("
0637:                                    + lEntityStylesheet
0638:                                            .getStorageImplementationName()
0639:                                    + ".class);");
0640:                    if (lHasBlobs || lHasClobs) {
0641:                        lWriter.println();
0642:                        // This internal class will help in Lob (BLOB & CLOB) read / write operations
0643:                        lWriter.println("    private class LobOperationDetail");
0644:                        lWriter.println("    {");
0645:                        lWriter.println("        public "
0646:                                + lInstanceIdDatatypeStylesheet
0647:                                        .getClassFullName()
0648:                                + " InstanceId = null;");
0649:                        lWriter
0650:                                .println("        public ArrayList ColumnNames = new ArrayList();");
0651:                        lWriter
0652:                                .println("        public ArrayList ColumnData = new ArrayList();");
0653:                        lWriter.println("    }");
0654:                    }
0655:                    // Construct some static never changing parts of statements or whole statements
0656:                    SelectStatementParts lSelectStatementParts = generateSelectStatementParts(
0657:                            pEntity, pDomainStorage);
0658:
0659:                    lWriter
0660:                            .println("    private Object mInstanceIdSemaphore = new Object();");
0661:                    lWriter.println("    private long mSessionId = 0;");
0662:                    lWriter.println("    private long mInstanceCount = 0;");
0663:                    lWriter.println("");
0664:                    lWriter
0665:                            .println("    /** Constructor. Initialises session Id with the seed value */");
0666:                    lWriter.println("    public "
0667:                            + lEntityStylesheet.getStorageImplementationName()
0668:                            + "() throws PSException");
0669:                    lWriter.println("    {");
0670:                    lWriter
0671:                            .println("        mSessionId = Util.getNextAvailableSessionId(\""
0672:                                    + lEntityTableName + "\");");
0673:                    lWriter.println("        if (sLogger.isDebugEnabled())");
0674:                    lWriter
0675:                            .println("            sLogger.debug(\"Will generate "
0676:                                    + lInstanceIdDatatypeStylesheet
0677:                                            .getClassName()
0678:                                    + " values in format '([a-z0-9]+)-\" + Long.toString(mSessionId,Character.MAX_RADIX) + \"-"
0679:                                    + lEntityTableAlias + "'\");");
0680:                    lWriter.println("    }");
0681:                    // Obtain new unique instance id for the entity
0682:                    lWriter.println("");
0683:                    lWriter
0684:                            .println("   /** Returns next avaialble unique instance id for the new "
0685:                                    + pEntity.getName() + " record */");
0686:                    lWriter
0687:                            .println("   public "
0688:                                    + lInstanceIdDatatypeStylesheet
0689:                                            .getClassFullName()
0690:                                    + " getNextAvailableInstanceId() throws PSException");
0691:                    lWriter.println("    {");
0692:                    lWriter.println("        try");
0693:                    lWriter.println("        {");
0694:                    lWriter
0695:                            .println("            synchronized(mInstanceIdSemaphore)");
0696:                    lWriter.println("            {");
0697:                    lWriter
0698:                            .println("                return "
0699:                                    + lInstanceIdDatatypeStylesheet
0700:                                            .getClassFullName()
0701:                                    + ".createFromString(Long.toString(mInstanceCount++, Character.MAX_RADIX) + \"-\" + Long.toString(mSessionId,Character.MAX_RADIX) + \"-"
0702:                                    + lEntityTableAlias + "\");");
0703:                    lWriter.println("            }");
0704:                    lWriter.println("        }");
0705:                    lWriter
0706:                            .println("        catch(DataTypeValidationException e)");
0707:                    lWriter.println("        {");
0708:                    lWriter
0709:                            .println("            throw new PSUnexpectedProgramConditionException(\"Internally generated instance id has not passed datatype validation\", e);");
0710:                    lWriter.println("        }");
0711:                    lWriter.println("    }");
0712:                    // Insert new record
0713:                    {
0714:                        lWriter.println();
0715:                        lWriter.println("    // Inserts one or more new "
0716:                                + pEntity.getName()
0717:                                + " records into the database");
0718:                        lWriter.println("    public void insert( "
0719:                                + lEntityStylesheet.getStorageRecordFullName()
0720:                                + "[] pNew" + pEntity.getName()
0721:                                + "Records) throws PSException");
0722:                        lWriter.println("    {");
0723:                        lWriter.println("        if (pNew" + pEntity.getName()
0724:                                + "Records == null)");
0725:                        lWriter
0726:                                .println("            throw new PSIllegalArgumentException(\"pNew"
0727:                                        + pEntity.getName()
0728:                                        + "Records is not expected to be undefined for insert() operation.\");");
0729:                        // If this entity has self reference roles - we need to do reordering of the array to make sure that
0730:                        // inserts of dependent records are happening last.
0731:                        if (!lSelfReferenceRoles.isEmpty()) {
0732:                            // Build map of records
0733:                            lWriter
0734:                                    .println("        java.util.HashMap lRecordsMap = new java.util.HashMap(pNew"
0735:                                            + pEntity.getName()
0736:                                            + "Records.length);");
0737:                            lWriter.println("        for (int i = 0; i < pNew"
0738:                                    + pEntity.getName()
0739:                                    + "Records.length; i++)");
0740:                            lWriter.println("        {");
0741:                            lWriter.println("            "
0742:                                    + lEntityStylesheet
0743:                                            .getStorageRecordFullName()
0744:                                    + " lNewRecord = pNew" + pEntity.getName()
0745:                                    + "Records[i];");
0746:                            // InstanceId is mandatory
0747:                            lWriter
0748:                                    .println("            if (lNewRecord."
0749:                                            + lEntityStylesheet
0750:                                                    .getInstanceIdStorageStructureAttributeName()
0751:                                            + " == null)");
0752:                            lWriter
0753:                                    .println("                throw new PSAttributeConstraintViolationException(\""
0754:                                            + lEntityStylesheet
0755:                                                    .getStorageRecordFullName()
0756:                                            + "."
0757:                                            + lEntityStylesheet
0758:                                                    .getInstanceIdStorageStructureAttributeName()
0759:                                            + " is not expected to be undefined for insert() operation.\");");
0760:                            lWriter
0761:                                    .println("            if (lNewRecord."
0762:                                            + lEntityStylesheet
0763:                                                    .getInstanceIdStorageStructureAttributeName()
0764:                                            + ".isEmpty())");
0765:                            lWriter
0766:                                    .println("                throw new PSAttributeConstraintViolationException(\""
0767:                                            + lEntityStylesheet
0768:                                                    .getStorageRecordFullName()
0769:                                            + "."
0770:                                            + lEntityStylesheet
0771:                                                    .getInstanceIdStorageStructureAttributeName()
0772:                                            + " is not expected to be empty for insert() operation.\");");
0773:                            lWriter
0774:                                    .println("            if (lNewRecord."
0775:                                            + lEntityStylesheet
0776:                                                    .getInstanceIdStorageStructureAttributeName()
0777:                                            + ".isConcealed())");
0778:                            lWriter
0779:                                    .println("                throw new PSAttributeConstraintViolationException(\""
0780:                                            + lEntityStylesheet
0781:                                                    .getStorageRecordFullName()
0782:                                            + "."
0783:                                            + lEntityStylesheet
0784:                                                    .getInstanceIdStorageStructureAttributeName()
0785:                                            + " is not expected to be concealed for insert() operation.\");");
0786:                            // We might have to use associations to supertypes
0787:                            if (!lSupertypes.isEmpty()) {
0788:                                String lSupertypeRecordReference = "lNewRecord."
0789:                                        + lEntityStylesheet
0790:                                                .getSupertypeStorageStructureAttributeName();
0791:                                // Insert must have all supertypes too
0792:                                for (Iterator lSupertypesIterator = lSupertypes
0793:                                        .iterator(); lSupertypesIterator
0794:                                        .hasNext();) {
0795:                                    Entity lSupertype = (Entity) lSupertypesIterator
0796:                                            .next();
0797:                                    STEntityStylesheet lSupertypeEntityStylesheet = CodeGenerationStylesheetAccessor
0798:                                            .getEntityStylesheet(lSupertype);
0799:                                    lWriter.println("            if ("
0800:                                            + lSupertypeRecordReference
0801:                                            + " == null)");
0802:                                    lWriter
0803:                                            .println("                throw new PSIllegalArgumentException(\""
0804:                                                    + lSupertypeRecordReference
0805:                                                    + " is not expected to be undefined for insert() operation.\");");
0806:                                    // InstanceId is mandatory
0807:                                    lWriter
0808:                                            .println("            if ("
0809:                                                    + lSupertypeRecordReference
0810:                                                    + "."
0811:                                                    + lSupertypeEntityStylesheet
0812:                                                            .getInstanceIdStorageStructureAttributeName()
0813:                                                    + " == null)");
0814:                                    lWriter
0815:                                            .println("                throw new PSAttributeConstraintViolationException(\""
0816:                                                    + lSupertypeEntityStylesheet
0817:                                                            .getStorageRecordFullName()
0818:                                                    + "."
0819:                                                    + lSupertypeEntityStylesheet
0820:                                                            .getInstanceIdStorageStructureAttributeName()
0821:                                                    + " is not expected to be undefined for insert() operation.\");");
0822:                                    lWriter
0823:                                            .println("            if ("
0824:                                                    + lSupertypeRecordReference
0825:                                                    + "."
0826:                                                    + lSupertypeEntityStylesheet
0827:                                                            .getInstanceIdStorageStructureAttributeName()
0828:                                                    + ".isEmpty())");
0829:                                    lWriter
0830:                                            .println("                throw new PSAttributeConstraintViolationException(\""
0831:                                                    + lSupertypeEntityStylesheet
0832:                                                            .getStorageRecordFullName()
0833:                                                    + "."
0834:                                                    + lSupertypeEntityStylesheet
0835:                                                            .getInstanceIdStorageStructureAttributeName()
0836:                                                    + " is not expected to be empty for insert() operation.\");");
0837:                                    lWriter
0838:                                            .println("            if ("
0839:                                                    + lSupertypeRecordReference
0840:                                                    + "."
0841:                                                    + lSupertypeEntityStylesheet
0842:                                                            .getInstanceIdStorageStructureAttributeName()
0843:                                                    + ".isConcealed())");
0844:                                    lWriter
0845:                                            .println("                throw new PSAttributeConstraintViolationException(\""
0846:                                                    + lSupertypeEntityStylesheet
0847:                                                            .getStorageRecordFullName()
0848:                                                    + "."
0849:                                                    + lSupertypeEntityStylesheet
0850:                                                            .getInstanceIdStorageStructureAttributeName()
0851:                                                    + " is not expected to be concealed for insert() operation.\");");
0852:                                    lWriter
0853:                                            .println("            if (!"
0854:                                                    + lSupertypeRecordReference
0855:                                                    + "."
0856:                                                    + lSupertypeEntityStylesheet
0857:                                                            .getInstanceIdStorageStructureAttributeName()
0858:                                                    + ".toString().equals(lNewRecord."
0859:                                                    + lEntityStylesheet
0860:                                                            .getInstanceIdStorageStructureAttributeName()
0861:                                                    + ".toString()))");
0862:                                    lWriter
0863:                                            .println("                throw new PSAttributeConstraintViolationException(\"Supertype's "
0864:                                                    + lSupertypeEntityStylesheet
0865:                                                            .getStorageRecordFullName()
0866:                                                    + "."
0867:                                                    + lSupertypeEntityStylesheet
0868:                                                            .getInstanceIdStorageStructureAttributeName()
0869:                                                    + " is not expected to be different to subtype "
0870:                                                    + lEntityStylesheet
0871:                                                            .getStorageRecordFullName()
0872:                                                    + "."
0873:                                                    + lEntityStylesheet
0874:                                                            .getInstanceIdStorageStructureAttributeName()
0875:                                                    + ".\");");
0876:                                    lSupertypeRecordReference += "."
0877:                                            + lSupertypeEntityStylesheet
0878:                                                    .getSupertypeStorageStructureAttributeName();
0879:                                }
0880:                            }
0881:                            // Add map with string instance id, so we could sort easier
0882:                            lWriter
0883:                                    .println("            lRecordsMap.put(lNewRecord.InstanceId.toString(), lNewRecord);");
0884:                            lWriter.println("        }");
0885:                            // Now we will look for independent records and put them in front
0886:                            lWriter
0887:                                    .println("        java.util.ArrayList lRecordsInOrderOfInsertion = new java.util.ArrayList(pNew"
0888:                                            + pEntity.getName()
0889:                                            + "Records.length);");
0890:                            lWriter
0891:                                    .println("        for (int lRecordsMapSizeBeforeIteration = lRecordsMap.size(); lRecordsMapSizeBeforeIteration > 0; )");
0892:                            lWriter.println("        {");
0893:                            lWriter
0894:                                    .println("            java.util.Iterator lIter = lRecordsMap.values().iterator();");
0895:                            lWriter
0896:                                    .println("            while(lIter.hasNext())");
0897:                            lWriter.println("            {");
0898:                            lWriter.println("                "
0899:                                    + lEntityStylesheet
0900:                                            .getStorageRecordFullName()
0901:                                    + " lCandidate = ("
0902:                                    + lEntityStylesheet
0903:                                            .getStorageRecordFullName()
0904:                                    + ")lIter.next();");
0905:                            // Go through each selfreference role and ensure that it does not reference anything still in the map
0906:                            for (Iterator lSelfReferenceRolesIterator = lSelfReferenceRoles
0907:                                    .iterator(); lSelfReferenceRolesIterator
0908:                                    .hasNext();) {
0909:                                AssociationRole lSelfReferenceRole = (AssociationRole) lSelfReferenceRolesIterator
0910:                                        .next();
0911:                                // Work on generating an access variable
0912:                                String lRoleInstanceIdVariable = "lCandidate";
0913:                                AssociationRole lOppositeOfSelfReferenceRole = lSelfReferenceRole
0914:                                        .getOppositeRole();
0915:                                // Depending on which level the other side points to - generate different code
0916:                                if (lOppositeOfSelfReferenceRole.getEntity()
0917:                                        .equals(pEntity)) {
0918:                                    lRoleInstanceIdVariable += "."
0919:                                            + lSelfReferenceRole.getName()
0920:                                            + "InstanceId";
0921:                                } else {
0922:                                    // Need to move down along supertypes looking for the reference. Also perfrom the check along the way
0923:                                    STEntityStylesheet lPrevEntityStylesheet = lEntityStylesheet;
0924:                                    boolean lFoundReferencedEntity = false;
0925:                                    for (Entity lCurrEntity = pEntity
0926:                                            .getSupertype(); lCurrEntity != null; lCurrEntity = lCurrEntity
0927:                                            .getSupertype()) {
0928:                                        lRoleInstanceIdVariable += "."
0929:                                                + lPrevEntityStylesheet
0930:                                                        .getSupertypeStorageStructureAttributeName();
0931:                                        if (lSelfReferenceRole.isOptional()) {
0932:                                            // Skip the check if actual reference is not given
0933:                                            lWriter
0934:                                                    .println("                if ("
0935:                                                            + lRoleInstanceIdVariable
0936:                                                            + " == null)");
0937:                                            lWriter
0938:                                                    .println("                    continue;");
0939:                                        } else {
0940:                                            lWriter
0941:                                                    .println("                if ("
0942:                                                            + lRoleInstanceIdVariable
0943:                                                            + " == null)");
0944:                                            lWriter
0945:                                                    .println("                    throw new PSAssociationConstraintViolationException(\"Reference to "
0946:                                                            + lSelfReferenceRole
0947:                                                                    .getName()
0948:                                                            + " is not expected to be undefined for insert() operation.\");");
0949:                                        }
0950:
0951:                                        if (lOppositeOfSelfReferenceRole
0952:                                                .getEntity()
0953:                                                .equals(lCurrEntity)) {
0954:                                            STEntityStylesheet lCurrEntityStylesheet = CodeGenerationStylesheetAccessor
0955:                                                    .getEntityStylesheet(lCurrEntity);
0956:                                            lRoleInstanceIdVariable += "."
0957:                                                    + lSelfReferenceRole
0958:                                                            .getName()
0959:                                                    + "InstanceId";
0960:                                            lFoundReferencedEntity = true;
0961:                                            break;
0962:                                        }
0963:                                        // Save stylesheet for the next round
0964:                                        lPrevEntityStylesheet = CodeGenerationStylesheetAccessor
0965:                                                .getEntityStylesheet(lCurrEntity);
0966:                                    }
0967:                                    if (!lFoundReferencedEntity)
0968:                                        throw new BSUnexpectedProgramConditionException(
0969:                                                "Unable to find selfreferenced entity among supertypes.");
0970:                                }
0971:                            }
0972:                            // If we have reached this point - we have got ourselves an independent record - it does not contain any of yet uninserted references
0973:                            lWriter
0974:                                    .println("                lRecordsInOrderOfInsertion.add(lRecordsMap.remove(lCandidate.InstanceId.toString()));");
0975:                            lWriter.println("                break;");
0976:                            lWriter.println("            }");
0977:                            // Make sure that we have made a progress
0978:                            lWriter
0979:                                    .println("            int lRecordsMapSizeAfterIteration = lRecordsMap.size();");
0980:                            lWriter
0981:                                    .println("            if (lRecordsMapSizeBeforeIteration == lRecordsMapSizeAfterIteration )");
0982:                            lWriter
0983:                                    .println("                throw new com.metaboss.enterprise.ps.PSCircularRecordReferenceException(\"insert("
0984:                                            + lEntityStylesheet
0985:                                                    .getStorageRecordFullName()
0986:                                            + "[]) operation has encountered circularly dependent records, which it was unable to process.\");");
0987:                            lWriter
0988:                                    .println("            lRecordsMapSizeBeforeIteration = lRecordsMapSizeAfterIteration;");
0989:                            lWriter.println("        }");
0990:                            // If we have reached this point - we have successfully reordered the input array
0991:                            // All we need is to put it back
0992:                            lWriter
0993:                                    .println("        pNew"
0994:                                            + pEntity.getName()
0995:                                            + "Records = ("
0996:                                            + lEntityStylesheet
0997:                                                    .getStorageRecordFullName()
0998:                                            + "[])lRecordsInOrderOfInsertion.toArray(new "
0999:                                            + lEntityStylesheet
1000:                                                    .getStorageRecordFullName()
1001:                                            + "[lRecordsInOrderOfInsertion.size()]);");
1002:                        }
1003:                        if (!lSupertypes.isEmpty()) {
1004:                            // We will have to call entity insert helpers in the reverse order.
1005:                            // So first create and populate additional member arrays
1006:                            for (Iterator lSupertypesIterator = lSupertypes
1007:                                    .iterator(); lSupertypesIterator.hasNext();) {
1008:                                Entity lSupertype = (Entity) lSupertypesIterator
1009:                                        .next();
1010:                                STEntityStylesheet lSupertypeEntityStylesheet = CodeGenerationStylesheetAccessor
1011:                                        .getEntityStylesheet(lSupertype);
1012:                                lWriter.println("        "
1013:                                        + lSupertypeEntityStylesheet
1014:                                                .getStorageRecordFullName()
1015:                                        + "[] l"
1016:                                        + lSupertype.getName()
1017:                                        + "Records = new "
1018:                                        + lSupertypeEntityStylesheet
1019:                                                .getStorageRecordFullName()
1020:                                        + "[pNew" + pEntity.getName()
1021:                                        + "Records.length];");
1022:                            }
1023:                            lWriter.println("        for (int i = 0; i < pNew"
1024:                                    + pEntity.getName()
1025:                                    + "Records.length; i++)");
1026:                            lWriter.println("        {");
1027:                            lWriter.println("            "
1028:                                    + lEntityStylesheet
1029:                                            .getStorageRecordFullName()
1030:                                    + " lNewRecord = pNew" + pEntity.getName()
1031:                                    + "Records[i];");
1032:                            String lSupertypeRecordAccessExpression = "lNewRecord."
1033:                                    + lEntityStylesheet
1034:                                            .getSupertypeStorageStructureAttributeName();
1035:                            for (Iterator lSupertypesIterator = lSupertypes
1036:                                    .iterator(); lSupertypesIterator.hasNext();) {
1037:                                Entity lSupertype = (Entity) lSupertypesIterator
1038:                                        .next();
1039:                                STEntityStylesheet lSupertypeEntityStylesheet = CodeGenerationStylesheetAccessor
1040:                                        .getEntityStylesheet(lSupertype);
1041:                                // We might need to check for null here if we have not checked for null before
1042:                                if (lSelfReferenceRoles.isEmpty()) {
1043:                                    lWriter.println("            if ("
1044:                                            + lSupertypeRecordAccessExpression
1045:                                            + " == null)");
1046:                                    lWriter
1047:                                            .println("                throw new PSAttributeConstraintViolationException(\""
1048:                                                    + lSupertypeRecordAccessExpression
1049:                                                    + " is not expected to be undefined for insert() operation.\");");
1050:                                }
1051:
1052:                                lWriter.println("            l"
1053:                                        + lSupertype.getName()
1054:                                        + "Records[i] = "
1055:                                        + lSupertypeRecordAccessExpression
1056:                                        + ";");
1057:                                lSupertypeRecordAccessExpression += "."
1058:                                        + lSupertypeEntityStylesheet
1059:                                                .getSupertypeStorageStructureAttributeName();
1060:                            }
1061:                            lWriter.println("        }");
1062:                            lWriter
1063:                                    .println("        java.sql.Connection lDatabaseConnection = Util.getConnection();");
1064:                            lWriter.println("        try");
1065:                            lWriter.println("        {");
1066:                            // Now call helpers in reverse order, so the most basic base class is created first
1067:                            for (ListIterator lSupertypesIterator = lSupertypes
1068:                                    .listIterator(lSupertypes.size()); lSupertypesIterator
1069:                                    .hasPrevious();) {
1070:                                Entity lSupertype = (Entity) lSupertypesIterator
1071:                                        .previous();
1072:                                lWriter.println("            insert"
1073:                                        + lSupertype.getName()
1074:                                        + "Records(lDatabaseConnection, l"
1075:                                        + lSupertype.getName() + "Records);");
1076:                            }
1077:                            lWriter.println("            insert"
1078:                                    + pEntity.getName()
1079:                                    + "Records(lDatabaseConnection, pNew"
1080:                                    + pEntity.getName() + "Records);");
1081:                        } else {
1082:                            lWriter
1083:                                    .println("        java.sql.Connection lDatabaseConnection = Util.getConnection();");
1084:                            lWriter.println("        try");
1085:                            lWriter.println("        {");
1086:                            lWriter.println("            insert"
1087:                                    + pEntity.getName()
1088:                                    + "Records(lDatabaseConnection, pNew"
1089:                                    + pEntity.getName() + "Records);");
1090:                        }
1091:                        lWriter.println("        }");
1092:                        lWriter.println("        finally");
1093:                        lWriter.println("        {");
1094:                        lWriter
1095:                                .println("            if (lDatabaseConnection != null)");
1096:                        lWriter
1097:                                .println("                Util.closeConnection(lDatabaseConnection);");
1098:                        lWriter.println("        }");
1099:                        lWriter.println("    }");
1100:                    }
1101:                    // Only card file has update record
1102:                    if (lIsModifiable) {
1103:                        lWriter.println();
1104:                        lWriter.println("    // Updates one or more existing "
1105:                                + pEntity.getName()
1106:                                + " records in the database");
1107:                        lWriter.println("    public void update( "
1108:                                + lEntityStylesheet.getStorageRecordFullName()
1109:                                + "[] pModified" + pEntity.getName()
1110:                                + "Records) throws PSException");
1111:                        lWriter.println("    {");
1112:                        if (!lSupertypes.isEmpty()) {
1113:                            // We will have to call entity insert helpers in the reverse order.
1114:                            // So first create and populate additional member arrays
1115:                            for (Iterator lSupertypesIterator = lSupertypes
1116:                                    .iterator(); lSupertypesIterator.hasNext();) {
1117:                                Entity lSupertype = (Entity) lSupertypesIterator
1118:                                        .next();
1119:                                STEntityStylesheet lSupertypeEntityStylesheet = CodeGenerationStylesheetAccessor
1120:                                        .getEntityStylesheet(lSupertype);
1121:                                lWriter.println("        "
1122:                                        + lSupertypeEntityStylesheet
1123:                                                .getStorageRecordFullName()
1124:                                        + "[] l"
1125:                                        + lSupertype.getName()
1126:                                        + "Records = new "
1127:                                        + lSupertypeEntityStylesheet
1128:                                                .getStorageRecordFullName()
1129:                                        + "[pModified" + pEntity.getName()
1130:                                        + "Records.length];");
1131:                            }
1132:                            lWriter
1133:                                    .println("        for (int i = 0; i < pModified"
1134:                                            + pEntity.getName()
1135:                                            + "Records.length; i++)");
1136:                            lWriter.println("        {");
1137:                            lWriter.println("            "
1138:                                    + lEntityStylesheet
1139:                                            .getStorageRecordFullName()
1140:                                    + " lModifiedRecord = pModified"
1141:                                    + pEntity.getName() + "Records[i];");
1142:                            String lSupertypeRecordAccessExpression = "lModifiedRecord."
1143:                                    + lEntityStylesheet
1144:                                            .getSupertypeStorageStructureAttributeName();
1145:                            for (Iterator lSupertypesIterator = lSupertypes
1146:                                    .iterator(); lSupertypesIterator.hasNext();) {
1147:                                Entity lSupertype = (Entity) lSupertypesIterator
1148:                                        .next();
1149:                                STEntityStylesheet lSupertypeEntityStylesheet = CodeGenerationStylesheetAccessor
1150:                                        .getEntityStylesheet(lSupertype);
1151:                                // We might need to check for null here if we have not checked for null before
1152:                                if (lSelfReferenceRoles.isEmpty()) {
1153:                                    lWriter.println("            if ("
1154:                                            + lSupertypeRecordAccessExpression
1155:                                            + " == null)");
1156:                                    lWriter
1157:                                            .println("                throw new PSAttributeConstraintViolationException(\""
1158:                                                    + lSupertypeRecordAccessExpression
1159:                                                    + " is not expected to be undefined for update() operation.\");");
1160:                                }
1161:
1162:                                lWriter.println("            l"
1163:                                        + lSupertype.getName()
1164:                                        + "Records[i] = "
1165:                                        + lSupertypeRecordAccessExpression
1166:                                        + ";");
1167:                                lSupertypeRecordAccessExpression += "."
1168:                                        + lSupertypeEntityStylesheet
1169:                                                .getSupertypeStorageStructureAttributeName();
1170:                            }
1171:                            lWriter.println("        }");
1172:                            lWriter
1173:                                    .println("        java.sql.Connection lDatabaseConnection = Util.getConnection();");
1174:                            lWriter.println("        try");
1175:                            lWriter.println("        {");
1176:                            // Now call helpers in reverse order, so the most basic base class is created first
1177:                            for (ListIterator lSupertypesIterator = lSupertypes
1178:                                    .listIterator(lSupertypes.size()); lSupertypesIterator
1179:                                    .hasPrevious();) {
1180:                                Entity lSupertype = (Entity) lSupertypesIterator
1181:                                        .previous();
1182:                                lWriter.println("            update"
1183:                                        + lSupertype.getName()
1184:                                        + "Records(lDatabaseConnection, l"
1185:                                        + lSupertype.getName() + "Records);");
1186:                            }
1187:                            lWriter.println("            update"
1188:                                    + pEntity.getName()
1189:                                    + "Records(lDatabaseConnection, pModified"
1190:                                    + pEntity.getName() + "Records);");
1191:                        } else {
1192:                            lWriter
1193:                                    .println("        java.sql.Connection lDatabaseConnection = Util.getConnection();");
1194:                            lWriter.println("        try");
1195:                            lWriter.println("        {");
1196:                            lWriter.println("            update"
1197:                                    + pEntity.getName()
1198:                                    + "Records(lDatabaseConnection, pModified"
1199:                                    + pEntity.getName() + "Records);");
1200:                        }
1201:                        lWriter.println("        }");
1202:                        lWriter.println("        finally");
1203:                        lWriter.println("        {");
1204:                        lWriter
1205:                                .println("            if (lDatabaseConnection != null)");
1206:                        lWriter
1207:                                .println("                Util.closeConnection(lDatabaseConnection);");
1208:                        lWriter.println("        }");
1209:                        lWriter.println("    }");
1210:                    }
1211:                    // Delete existing records
1212:                    {
1213:                        lWriter.println();
1214:                        lWriter.print("    // Deletes one or more existing ");
1215:                        lWriter.print(pEntity.getName());
1216:                        lWriter.println(" records from the database");
1217:                        lWriter.print("    public void delete( ");
1218:                        lWriter.print(lInstanceIdDatatypeStylesheet
1219:                                .getClassFullName());
1220:                        lWriter
1221:                                .println("[] pInstanceIdsToDelete) throws PSException");
1222:                        lWriter.println("    {");
1223:                        // We will have to call entity delete in the straight order (from subclasses to superclasses).
1224:                        lWriter
1225:                                .println("        java.sql.Connection lDatabaseConnection = Util.getConnection();");
1226:                        lWriter.println("        try");
1227:                        lWriter.println("        {");
1228:                        // Call our entity delete first
1229:                        lWriter
1230:                                .println("            delete"
1231:                                        + pEntity.getName()
1232:                                        + "Records(lDatabaseConnection, pInstanceIdsToDelete);");
1233:                        for (Iterator lSupertypesIterator = lSupertypes
1234:                                .iterator(); lSupertypesIterator.hasNext();) {
1235:                            Entity lSupertype = (Entity) lSupertypesIterator
1236:                                    .next();
1237:                            lWriter
1238:                                    .println("            delete"
1239:                                            + lSupertype.getName()
1240:                                            + "Records(lDatabaseConnection, pInstanceIdsToDelete);");
1241:                        }
1242:                        lWriter.println("        }");
1243:                        lWriter.println("        finally");
1244:                        lWriter.println("        {");
1245:                        lWriter
1246:                                .println("            if (lDatabaseConnection != null)");
1247:                        lWriter
1248:                                .println("                Util.closeConnection(lDatabaseConnection);");
1249:                        lWriter.println("        }");
1250:                        lWriter.println("    }");
1251:                    }
1252:                    // Retrieve count method
1253:                    lWriter.println();
1254:                    lWriter
1255:                            .println("    // Returns count of entities matching supplied selector matrix.");
1256:                    lWriter
1257:                            .println("    public "
1258:                                    + lCollectionSizeDatatypeStylesheet
1259:                                            .getClassFullName()
1260:                                    + " getRecordsCollectionSize( STCollectionDetails[] pCollectionsDetails) throws PSException");
1261:                    lWriter.println("    {");
1262:                    lWriter.println("        try");
1263:                    lWriter.println("        {");
1264:                    lWriter
1265:                            .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
1266:                    lWriter.println("            try");
1267:                    lWriter.println("            {");
1268:                    // Build statement dynamically from selectors
1269:                    lWriter
1270:                            .println("                QueryContext lQueryContext = new QueryContext(QueryContext.QueryType.QUERYTYPE_COUNTRECORDS,\""
1271:                                    + lEntityTableName + "\");");
1272:                    // Even if there is a subset - sorting can be suppressed since we are only interested in count
1273:                    lWriter
1274:                            .println("                Selectors.SqlStatementParts lGeneratedSqlStatementParts = Selectors.getSqlStatementParts(Util.suppressSortingInstruction(pCollectionsDetails),lQueryContext);");
1275:                    lWriter
1276:                            .println("                StringBuffer lStatementText = new StringBuffer();");
1277:                    lWriter
1278:                            .println("                lStatementText.append(\"SELECT COUNT(\");");
1279:                    lWriter
1280:                            .println("                if (lGeneratedSqlStatementParts.needsDistinct())");
1281:                    lWriter
1282:                            .println("                    lStatementText.append(\"DISTINCT \");");
1283:                    lWriter.println("                lStatementText.append(\""
1284:                            + lEntityTableAlias + "." + lInstanceIdColumnName
1285:                            + "\");");
1286:                    lWriter
1287:                            .println("                lStatementText.append(\") FROM \");");
1288:                    lWriter
1289:                            .println("                lStatementText.append(lGeneratedSqlStatementParts.mFromClause);");
1290:                    lWriter
1291:                            .println("                if (lGeneratedSqlStatementParts.mWhereClause != null && lGeneratedSqlStatementParts.mWhereClause.length() > 0)");
1292:                    lWriter.println("                {");
1293:                    lWriter
1294:                            .println("                    lStatementText.append(\" WHERE \");");
1295:                    lWriter
1296:                            .println("                    lStatementText.append(lGeneratedSqlStatementParts.mWhereClause);");
1297:                    lWriter.println("                }");
1298:
1299:                    // Work on "order by" clause
1300:                    lWriter
1301:                            .println("                if (lGeneratedSqlStatementParts.mOrderByClause != null && lGeneratedSqlStatementParts.mOrderByClause.length() > 0)");
1302:                    lWriter.println("                {");
1303:                    lWriter
1304:                            .println("                    lStatementText.append(\" ORDER BY \");");
1305:                    lWriter
1306:                            .println("                    lStatementText.append(lGeneratedSqlStatementParts.mOrderByClause);");
1307:                    lWriter.println("                }");
1308:
1309:                    // Work on "limit" clause
1310:                    lWriter
1311:                            .println("                if (lGeneratedSqlStatementParts.mLimitClause != null && lGeneratedSqlStatementParts.mLimitClause.length() > 0)");
1312:                    lWriter.println("                {");
1313:                    lWriter
1314:                            .println("                    lStatementText.append(\" LIMIT \");");
1315:                    lWriter
1316:                            .println("                    lStatementText.append(lGeneratedSqlStatementParts.mLimitClause);");
1317:                    lWriter.println("                }");
1318:
1319:                    lWriter
1320:                            .println("                String lStatementString = lStatementText.toString();");
1321:                    lWriter
1322:                            .println("                if (sLogger.isDebugEnabled())");
1323:                    lWriter
1324:                            .println("                    sLogger.debug(\"About to execute SQL statement: \" + lStatementString + \";\");");
1325:                    lWriter
1326:                            .println("                java.sql.PreparedStatement lGetCountStatement = lDatabaseConnection.prepareStatement(lStatementString);");
1327:                    lWriter.println("                try");
1328:                    lWriter.println("                {");
1329:                    lWriter
1330:                            .println("                    Selectors.populatePreparedStatement(pCollectionsDetails,lGetCountStatement,1);");
1331:                    lWriter
1332:                            .println("                    java.sql.ResultSet lResultSet = lGetCountStatement.executeQuery();");
1333:                    lWriter
1334:                            .println("                    if (lResultSet.next())");
1335:                    lWriter.println("                    {");
1336:                    lWriter.println("                        "
1337:                            + lCollectionSizeDatatypeSqlType.getJavaType()
1338:                                    .getName()
1339:                            + " lCollectionSize = lResultSet."
1340:                            + getDataBaseMetaData().suggestResultSetGetMethod(
1341:                                    lCollectionSizeDatatype) + "(1);");
1342:                    lWriter
1343:                            .println("                        if (!lResultSet.wasNull())");
1344:                    lWriter
1345:                            .println("                            return TypesConvertor.create"
1346:                                    + getUniqueDatatypeName(lCollectionSizeDatatype)
1347:                                    + "FromSqlValue(lCollectionSize);");
1348:                    lWriter.println("                    }");
1349:                    lWriter.println("                    return "
1350:                            + lCollectionSizeDatatypeStylesheet
1351:                                    .getClassFullName() + ".createEmpty();");
1352:                    lWriter.println("                }");
1353:                    lWriter.println("                finally");
1354:                    lWriter.println("                {");
1355:                    lWriter
1356:                            .println("                    if (lGetCountStatement != null)");
1357:                    lWriter
1358:                            .println("                        lGetCountStatement.close();");
1359:                    lWriter.println("                }");
1360:                    lWriter.println("            }");
1361:                    lWriter.println("            finally");
1362:                    lWriter.println("            {");
1363:                    lWriter
1364:                            .println("                if (lDatabaseConnection != null)");
1365:                    lWriter
1366:                            .println("                    Util.closeConnection(lDatabaseConnection);");
1367:                    lWriter.println("            }");
1368:                    lWriter.println("        }");
1369:                    lWriter.println("        catch(java.sql.SQLException e)");
1370:                    lWriter.println("        {");
1371:                    lWriter
1372:                            .println("            throw new PSDataSourceOperationInvocationException(\"Error in getRecordsCollectionSize("
1373:                                    + lEntityStylesheet
1374:                                            .getStorageRecordFullName()
1375:                                    + ")\", e);");
1376:                    lWriter.println("        }");
1377:                    lWriter.println("    }");
1378:                    // Retrieve all records method
1379:                    {
1380:                        lWriter.println("");
1381:                        lWriter
1382:                                .println("    // Returns all entities matching supplied selector matrix.");
1383:                        lWriter
1384:                                .println("    public "
1385:                                        + lEntityStylesheet
1386:                                                .getStorageRecordFullName()
1387:                                        + "[] getAllRecords( STCollectionDetails[] pCollectionsDetails) throws PSException");
1388:                        lWriter.println("    {");
1389:                        lWriter.println("        try");
1390:                        lWriter.println("        {");
1391:                        lWriter
1392:                                .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
1393:                        lWriter.println("            try");
1394:                        lWriter.println("            {");
1395:                        // Build statement dynamically from selectors
1396:                        lWriter
1397:                                .println("                QueryContext lQueryContext = new QueryContext(QueryContext.QueryType.QUERYTYPE_GETALLRECORDS,\""
1398:                                        + lEntityTableName + "\");");
1399:                        // No suppressing of anything here - sorting and subset are both important 
1400:                        lWriter
1401:                                .println("                Selectors.SqlStatementParts lGeneratedSqlStatementParts = Selectors.getSqlStatementParts(pCollectionsDetails,lQueryContext);");
1402:                        lWriter
1403:                                .println("                StringBuffer lStatementText = new StringBuffer();");
1404:
1405:                        // Work on "what" clause
1406:                        lWriter
1407:                                .println("                lStatementText.append(\"SELECT \");");
1408:                        lWriter
1409:                                .println("                if (lGeneratedSqlStatementParts.needsDistinct())");
1410:                        lWriter
1411:                                .println("                    lStatementText.append(\"DISTINCT \");");
1412:                        lWriter
1413:                                .println("                lStatementText.append(lGeneratedSqlStatementParts.getWhatClause());");
1414:
1415:                        // Work on "from" clause
1416:                        lWriter
1417:                                .println("                if (lGeneratedSqlStatementParts.mFromClause != null && lGeneratedSqlStatementParts.mFromClause.length() > 0)");
1418:                        lWriter.println("                {");
1419:                        lWriter
1420:                                .println("                  lStatementText.append(\" FROM \");");
1421:                        lWriter
1422:                                .println("                  lStatementText.append(lGeneratedSqlStatementParts.mFromClause);");
1423:                        lWriter.println("                }");
1424:
1425:                        // Work on "where" clause
1426:                        lWriter
1427:                                .println("                if (lGeneratedSqlStatementParts.mWhereClause != null && lGeneratedSqlStatementParts.mWhereClause.length() > 0)");
1428:                        lWriter.println("                {");
1429:                        lWriter
1430:                                .println("                    lStatementText.append(\" WHERE \");");
1431:                        lWriter
1432:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mWhereClause);");
1433:                        lWriter.println("                }");
1434:
1435:                        // Work on "order by" clause
1436:                        lWriter
1437:                                .println("                if (lGeneratedSqlStatementParts.mOrderByClause != null && lGeneratedSqlStatementParts.mOrderByClause.length() > 0)");
1438:                        lWriter.println("                {");
1439:                        lWriter
1440:                                .println("                    lStatementText.append(\" ORDER BY \");");
1441:                        lWriter
1442:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mOrderByClause);");
1443:                        lWriter.println("                }");
1444:
1445:                        // Work on "limit" clause
1446:                        lWriter
1447:                                .println("                if (lGeneratedSqlStatementParts.mLimitClause != null && lGeneratedSqlStatementParts.mLimitClause.length() > 0)");
1448:                        lWriter.println("                {");
1449:                        lWriter
1450:                                .println("                    lStatementText.append(\" LIMIT \");");
1451:                        lWriter
1452:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mLimitClause);");
1453:                        lWriter.println("                }");
1454:
1455:                        lWriter
1456:                                .println("                String lStatementString = lStatementText.toString();");
1457:                        lWriter
1458:                                .println("                if (sLogger.isDebugEnabled())");
1459:                        lWriter
1460:                                .println("                    sLogger.debug(\"About to execute SQL statement: \" + lStatementString + \";\");");
1461:                        lWriter
1462:                                .println("                java.sql.PreparedStatement lGetAllRecordsStatement = lDatabaseConnection.prepareStatement(lStatementString);");
1463:                        lWriter.println("                try");
1464:                        lWriter.println("                {");
1465:                        lWriter
1466:                                .println("                    Selectors.populatePreparedStatement(pCollectionsDetails,lGetAllRecordsStatement,1);");
1467:                        lWriter
1468:                                .println("                    java.sql.ResultSet lResultSet = lGetAllRecordsStatement.executeQuery();");
1469:                        lWriter.println("                    try");
1470:                        lWriter.println("                    {");
1471:                        lWriter
1472:                                .println("                        ArrayList lReturnedRecords = new ArrayList();");
1473:                        lWriter
1474:                                .println("                        while(lResultSet.next())");
1475:                        // If we have clobs or blobs - result set does not contain them in this case
1476:                        if (lHasClobs || lHasBlobs)
1477:                            lWriter
1478:                                    .println("                            lReturnedRecords.add(unpackRecordFromResultSet(lResultSet, false));");
1479:                        else
1480:                            lWriter
1481:                                    .println("                            lReturnedRecords.add(unpackRecordFromResultSet(lResultSet));");
1482:                        lWriter.println("                        return ("
1483:                                + lEntityStylesheet.getStorageRecordFullName()
1484:                                + "[])lReturnedRecords.toArray( new "
1485:                                + lEntityStylesheet.getStorageRecordFullName()
1486:                                + "[lReturnedRecords.size()]);");
1487:                        lWriter.println("                    }");
1488:                        lWriter.println("                    finally");
1489:                        lWriter.println("                    {");
1490:                        lWriter
1491:                                .println("                        if (lResultSet != null)");
1492:                        lWriter
1493:                                .println("                            lResultSet.close();");
1494:                        lWriter.println("                    }");
1495:                        lWriter.println("                }");
1496:                        lWriter.println("                finally");
1497:                        lWriter.println("                {");
1498:                        lWriter
1499:                                .println("                    if (lGetAllRecordsStatement != null)");
1500:                        lWriter
1501:                                .println("                        lGetAllRecordsStatement.close();");
1502:                        lWriter.println("                }");
1503:                        lWriter.println("            }");
1504:                        lWriter.println("            finally");
1505:                        lWriter.println("            {");
1506:                        lWriter
1507:                                .println("                if (lDatabaseConnection != null)");
1508:                        lWriter
1509:                                .println("                    Util.closeConnection(lDatabaseConnection);");
1510:                        lWriter.println("            }");
1511:                        lWriter.println("        }");
1512:                        lWriter
1513:                                .println("        catch(java.sql.SQLException e)");
1514:                        lWriter.println("        {");
1515:                        lWriter
1516:                                .println("            throw new PSDataSourceOperationInvocationException(\"Error on getAllRecords("
1517:                                        + lEntityStylesheet
1518:                                                .getStorageRecordFullName()
1519:                                        + ")\", e);");
1520:                        lWriter.println("        }");
1521:                        lWriter.println("    }");
1522:                    }
1523:
1524:                    // Retrieve all record ids method
1525:                    {
1526:                        lWriter.println();
1527:                        lWriter
1528:                                .println("    // Returns instance ids of all entities matching supplied selector matrix.");
1529:                        lWriter
1530:                                .println("    public "
1531:                                        + lInstanceIdDatatypeStylesheet
1532:                                                .getClassFullName()
1533:                                        + "[] getAllInstanceIds( STCollectionDetails[] pCollectionsDetails) throws PSException");
1534:                        lWriter.println("    {");
1535:                        lWriter.println("        try");
1536:                        lWriter.println("        {");
1537:                        lWriter
1538:                                .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
1539:                        lWriter.println("            try");
1540:                        lWriter.println("            {");
1541:                        // Build statement dynamically from selectors
1542:                        lWriter
1543:                                .println("                QueryContext lQueryContext = new QueryContext(QueryContext.QueryType.QUERYTYPE_GETALLRECORDIDS,\""
1544:                                        + lEntityTableName + "\");");
1545:                        // No suppressing of anything here - sorting and subset are both important 
1546:                        lWriter
1547:                                .println("                Selectors.SqlStatementParts lGeneratedSqlStatementParts = Selectors.getSqlStatementParts(pCollectionsDetails,lQueryContext);");
1548:                        lWriter
1549:                                .println("                StringBuffer lStatementText = new StringBuffer();");
1550:                        lWriter
1551:                                .println("                lStatementText.append(\"SELECT \");");
1552:                        lWriter
1553:                                .println("                if (lGeneratedSqlStatementParts.needsDistinct())");
1554:                        lWriter
1555:                                .println("                    lStatementText.append(\"DISTINCT \");");
1556:                        lWriter
1557:                                .println("                lStatementText.append(lGeneratedSqlStatementParts.getWhatClause());");
1558:                        lWriter
1559:                                .println("                lStatementText.append(\" FROM \");");
1560:                        lWriter
1561:                                .println("                lStatementText.append(lGeneratedSqlStatementParts.mFromClause);");
1562:                        // Work on "where" clause
1563:                        lWriter
1564:                                .println("                if (lGeneratedSqlStatementParts.mWhereClause != null && lGeneratedSqlStatementParts.mWhereClause.length() > 0)");
1565:                        lWriter.println("                {");
1566:                        lWriter
1567:                                .println("                    lStatementText.append(\" WHERE \");");
1568:                        lWriter
1569:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mWhereClause);");
1570:                        lWriter.println("                }");
1571:                        // Work on "order by" clause
1572:                        lWriter
1573:                                .println("                if (lGeneratedSqlStatementParts.mOrderByClause != null && lGeneratedSqlStatementParts.mOrderByClause.length() > 0)");
1574:                        lWriter.println("                {");
1575:                        lWriter
1576:                                .println("                    lStatementText.append(\" ORDER BY \");");
1577:                        lWriter
1578:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mOrderByClause);");
1579:                        lWriter.println("                }");
1580:                        // Work on "limit" clause
1581:                        lWriter
1582:                                .println("                if (lGeneratedSqlStatementParts.mLimitClause != null && lGeneratedSqlStatementParts.mLimitClause.length() > 0)");
1583:                        lWriter.println("                {");
1584:                        lWriter
1585:                                .println("                    lStatementText.append(\" LIMIT \");");
1586:                        lWriter
1587:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mLimitClause);");
1588:                        lWriter.println("                }");
1589:
1590:                        lWriter
1591:                                .println("                String lStatementString = lStatementText.toString();");
1592:                        lWriter
1593:                                .println("                if (sLogger.isDebugEnabled())");
1594:                        lWriter
1595:                                .println("                    sLogger.debug(\"About to execute SQL statement: \" + lStatementString + \";\");");
1596:                        lWriter
1597:                                .println("                java.sql.PreparedStatement lGetAllInstanceIdsStatement = lDatabaseConnection.prepareStatement(lStatementString);");
1598:                        lWriter.println("                try");
1599:                        lWriter.println("                {");
1600:                        lWriter
1601:                                .println("                    Selectors.populatePreparedStatement(pCollectionsDetails,lGetAllInstanceIdsStatement,1);");
1602:                        lWriter
1603:                                .println("                    java.sql.ResultSet lResultSet = lGetAllInstanceIdsStatement.executeQuery();");
1604:                        lWriter.println("                    try");
1605:                        lWriter.println("                    {");
1606:                        lWriter
1607:                                .println("                        ArrayList lReturnedIds = new ArrayList();");
1608:                        lWriter
1609:                                .println("                        while(lResultSet.next())");
1610:                        lWriter
1611:                                .print("                            lReturnedIds.add( lResultSet.");
1612:                        lWriter
1613:                                .print(getDataBaseMetaData()
1614:                                        .suggestResultSetGetMethod(
1615:                                                lInstanceIdDatatype));
1616:                        lWriter.println("(1));");
1617:                        lWriter.print("                        return (");
1618:                        lWriter.print(lInstanceIdDatatypeStylesheet
1619:                                .getClassFullName());
1620:                        lWriter.print("[])lReturnedIds.toArray( new ");
1621:                        lWriter.print(lInstanceIdDatatypeStylesheet
1622:                                .getClassFullName());
1623:                        lWriter.println("[lReturnedIds.size()]);");
1624:                        lWriter.println("                    }");
1625:                        lWriter.println("                    finally");
1626:                        lWriter.println("                    {");
1627:                        lWriter
1628:                                .println("                        if (lResultSet != null)");
1629:                        lWriter
1630:                                .println("                            lResultSet.close();");
1631:                        lWriter.println("                    }");
1632:                        lWriter.println("                }");
1633:                        lWriter.println("                finally");
1634:                        lWriter.println("                {");
1635:                        lWriter
1636:                                .println("                    if (lGetAllInstanceIdsStatement != null)");
1637:                        lWriter
1638:                                .println("                        lGetAllInstanceIdsStatement.close();");
1639:                        lWriter.println("                }");
1640:                        lWriter.println("            }");
1641:                        lWriter.println("            finally");
1642:                        lWriter.println("            {");
1643:                        lWriter
1644:                                .println("                if (lDatabaseConnection != null)");
1645:                        lWriter
1646:                                .println("                    Util.closeConnection(lDatabaseConnection);");
1647:                        lWriter.println("            }");
1648:                        lWriter.println("        }");
1649:                        lWriter
1650:                                .println("        catch(java.sql.SQLException e)");
1651:                        lWriter.println("        {");
1652:                        lWriter
1653:                                .print("            throw new PSDataSourceOperationInvocationException(\"Error on getAllRecords("
1654:                                        + lEntityStylesheet
1655:                                                .getStorageRecordFullName()
1656:                                        + ")\", e);");
1657:                        lWriter.println("        }");
1658:                        lWriter.println("    }");
1659:                    }
1660:
1661:                    // Get record by system id
1662:                    {
1663:                        lWriter.println();
1664:                        lWriter.print("    // Retrieves ");
1665:                        lWriter.print(pEntity.getName());
1666:                        lWriter.println(" record by its instance id");
1667:                        lWriter.print("    public ");
1668:                        lWriter.print(lEntityStylesheet
1669:                                .getStorageRecordFullName());
1670:                        lWriter.print(" getByInstanceId( ");
1671:                        lWriter.print(lInstanceIdDatatypeStylesheet
1672:                                .getClassFullName());
1673:                        lWriter
1674:                                .println(" pInstanceId, STCollectionDetails[] pCollectionsDetails) throws PSException");
1675:                        lWriter.println("    {");
1676:                        lWriter.println("        if (pInstanceId == null)");
1677:                        lWriter.print("            throw new PSException(\"");
1678:                        lWriter.print(lEntityStylesheet
1679:                                .getStorageRecordFullName());
1680:                        lWriter
1681:                                .println(".InstanceId is not expected to be null for getByInstanceId() operation.\");");
1682:                        lWriter.println("        if (pInstanceId.isEmpty())");
1683:                        lWriter.print("            throw new PSException(\"");
1684:                        lWriter.print(lEntityStylesheet
1685:                                .getStorageRecordFullName());
1686:                        lWriter
1687:                                .println(".InstanceId is not expected to be empty for getByInstanceId() operation.\");");
1688:                        lWriter
1689:                                .println("        if (pInstanceId.isConcealed())");
1690:                        lWriter.print("            throw new PSException(\"");
1691:                        lWriter.print(lEntityStylesheet
1692:                                .getStorageRecordFullName());
1693:                        lWriter
1694:                                .println(".InstanceId is not expected to be concealed for getByInstanceId() operation.\");");
1695:                        lWriter.println("        try");
1696:                        lWriter.println("        {");
1697:                        lWriter
1698:                                .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
1699:                        lWriter.println("            try");
1700:                        lWriter.println("            {");
1701:                        // Build statement dynamically from selectors
1702:                        lWriter
1703:                                .println("                QueryContext lQueryContext = new QueryContext(QueryContext.QueryType.QUERYTYPE_GETSINGLERECORD,\""
1704:                                        + lEntityTableName + "\");");
1705:                        lWriter
1706:                                .println("                Selectors.SqlStatementParts lGeneratedSqlStatementParts = Selectors.getSqlStatementParts(pCollectionsDetails,lQueryContext);");
1707:                        lWriter
1708:                                .println("                StringBuffer lStatementText = new StringBuffer();");
1709:                        // No need to specify distinct - there can be at most one match any way
1710:                        // In fact we are better of not to have distinct because it does not work with lobs
1711:                        lWriter
1712:                                .println("                lStatementText.append(\"SELECT "
1713:                                        + lSelectStatementParts.WhatClauseForGetInstance
1714:                                        + " FROM \");");
1715:                        lWriter
1716:                                .println("                lStatementText.append(lGeneratedSqlStatementParts.mFromClause);");
1717:                        lWriter
1718:                                .println("                lStatementText.append(\" WHERE "
1719:                                        + lEntityTableAlias
1720:                                        + "."
1721:                                        + lInstanceIdColumnName + " = ?\");");
1722:                        lWriter
1723:                                .println("                if (lGeneratedSqlStatementParts.mWhereClause != null && lGeneratedSqlStatementParts.mWhereClause.length() > 0)");
1724:                        lWriter.println("                {");
1725:                        lWriter
1726:                                .println("                    // If there is a where clause - there are possibly some arguments too");
1727:                        lWriter
1728:                                .println("                    lStatementText.append(\" AND \");");
1729:                        lWriter
1730:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mWhereClause);");
1731:                        lWriter.println("                }");
1732:                        // Limit and orderby can be ignored because this is a single instance getter
1733:
1734:                        lWriter
1735:                                .println("                String lStatementString = lStatementText.toString();");
1736:                        lWriter
1737:                                .println("                if (sLogger.isDebugEnabled())");
1738:                        lWriter
1739:                                .println("                    sLogger.debug(\"About to execute SQL statement: \" + lStatementString + \";\");");
1740:                        lWriter
1741:                                .println("                java.sql.PreparedStatement lGetByInstanceIdStatement = lDatabaseConnection.prepareStatement(lStatementString);");
1742:                        lWriter.println("                try");
1743:                        lWriter.println("                {");
1744:                        lWriter
1745:                                .println("                    lGetByInstanceIdStatement."
1746:                                        + getDataBaseMetaData()
1747:                                                .suggestStatementSetMethod(
1748:                                                        lInstanceIdDatatype)
1749:                                        + "( 1, TypesConvertor.getSqlValueFrom"
1750:                                        + getUniqueDatatypeName(lInstanceIdDatatype)
1751:                                        + "(pInstanceId));");
1752:                        lWriter
1753:                                .println("                    Selectors.populatePreparedStatement(pCollectionsDetails,lGetByInstanceIdStatement,2);");
1754:                        lWriter
1755:                                .println("                    java.sql.ResultSet lResultSet = lGetByInstanceIdStatement.executeQuery();");
1756:                        lWriter.println("                    try");
1757:                        lWriter.println("                    {");
1758:                        lWriter
1759:                                .println("                        if(lResultSet.next())");
1760:                        // If we have clobs or blobs - result set does contain them in this case
1761:                        if (lHasClobs || lHasBlobs)
1762:                            lWriter
1763:                                    .println("                            return unpackRecordFromResultSet(lResultSet, true);");
1764:                        else
1765:                            lWriter
1766:                                    .println("                            return unpackRecordFromResultSet(lResultSet);");
1767:                        lWriter.println("                        return null;");
1768:                        lWriter.println("                    }");
1769:                        lWriter.println("                    finally");
1770:                        lWriter.println("                    {");
1771:                        lWriter
1772:                                .println("                        if (lResultSet != null)");
1773:                        lWriter
1774:                                .println("                            lResultSet.close();");
1775:                        lWriter.println("                    }");
1776:                        lWriter.println("                }");
1777:                        lWriter.println("                finally");
1778:                        lWriter.println("                {");
1779:                        lWriter
1780:                                .println("                    if (lGetByInstanceIdStatement != null)");
1781:                        lWriter
1782:                                .println("                        lGetByInstanceIdStatement.close();");
1783:                        lWriter.println("                }");
1784:                        lWriter.println("            }");
1785:                        lWriter.println("            finally");
1786:                        lWriter.println("            {");
1787:                        lWriter
1788:                                .println("                if (lDatabaseConnection != null)");
1789:                        lWriter
1790:                                .println("                    Util.closeConnection(lDatabaseConnection);");
1791:                        lWriter.println("            }");
1792:                        lWriter.println("        }");
1793:                        lWriter
1794:                                .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
1795:                        lWriter.println("        {");
1796:                        lWriter
1797:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for empty instance\",e);");
1798:                        lWriter.println("        }");
1799:                        lWriter
1800:                                .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
1801:                        lWriter.println("        {");
1802:                        lWriter
1803:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for concealed instance\",e);");
1804:                        lWriter.println("        }");
1805:                        lWriter
1806:                                .println("        catch(java.sql.SQLException e)");
1807:                        lWriter.println("        {");
1808:                        lWriter
1809:                                .print("            throw new PSDataSourceOperationInvocationException(\"Error on getByInstanceId(");
1810:                        lWriter.print(lEntityStylesheet
1811:                                .getStorageRecordFullName());
1812:                        lWriter.println(")\", e);");
1813:                        lWriter.println("        }");
1814:                        lWriter.println("    }");
1815:                    }
1816:
1817:                    // Get record by primary key (if there is one)
1818:                    if (lHasPrimaryKey) {
1819:                        lWriter.println();
1820:                        lWriter.print("   // Retrieves ");
1821:                        lWriter.print(pEntity.getName());
1822:                        lWriter.println(" record by primary key");
1823:                        lWriter.print("   public ");
1824:                        lWriter.print(lEntityStylesheet
1825:                                .getStorageRecordFullName());
1826:                        lWriter.print(" getByPrimaryKey( ");
1827:                        lWriter
1828:                                .print(EntityUtils
1829:                                        .generatePrimaryKeyArgumentsForStorageMethodDeclaration(pEntity));
1830:                        lWriter
1831:                                .println(", STCollectionDetails[] pCollectionsDetails) throws PSException");
1832:                        lWriter.println("    {");
1833:                        Collection lPrimaryKeyElements = pEntity
1834:                                .getPrimaryKeyElements();
1835:                        if (lPrimaryKeyElements.isEmpty())
1836:                            throw new BSException(
1837:                                    "Undefined PrimaryKey. EntityRef : "
1838:                                            + pEntity.getRef());
1839:                        for (Iterator lPrimaryKeyElementsIterator = lPrimaryKeyElements
1840:                                .iterator(); lPrimaryKeyElementsIterator
1841:                                .hasNext();) {
1842:                            PrimaryKeyElement lPrimaryKeyElement = (PrimaryKeyElement) lPrimaryKeyElementsIterator
1843:                                    .next();
1844:                            String lParameterName = null;
1845:                            if (lPrimaryKeyElement instanceof  Attribute) {
1846:                                Attribute lAttribute = (Attribute) lPrimaryKeyElement;
1847:                                STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
1848:                                        .getAttributeStylesheet(lAttribute);
1849:                                lParameterName = "p"
1850:                                        + lAttribute.getEntity().getName()
1851:                                        + lAttributeStylesheet
1852:                                                .getNormalisedName();
1853:                            } else if (lPrimaryKeyElement instanceof  AssociationRole) {
1854:                                AssociationRole lRole = (AssociationRole) lPrimaryKeyElement;
1855:                                if (!lRole.getCardinality().equals(
1856:                                        AssociationRoleCardinalityEnum.ONE))
1857:                                    throw new BSException(
1858:                                            "For Association to be part of PrimaryKey, the other entity's role must have cardinality of \"exactly one\". Entity : "
1859:                                                    + pEntity.getName()
1860:                                                    + ", Element "
1861:                                                    + lRole.getName());
1862:                                lParameterName = "p" + lRole.getName()
1863:                                        + "InstanceId";
1864:                            }
1865:                            lWriter.write("        if (");
1866:                            lWriter.write(lParameterName);
1867:                            lWriter.write(" == null)\r\n");
1868:                            lWriter
1869:                                    .write("            throw new PSException(\"Parameter ");
1870:                            lWriter.write(lParameterName);
1871:                            lWriter
1872:                                    .write(" is not expected to be null for getByPrimaryKey() operation.\");\r\n");
1873:                            lWriter.write("        if (");
1874:                            lWriter.write(lParameterName);
1875:                            lWriter.write(".isEmpty())\r\n");
1876:                            lWriter
1877:                                    .write("            throw new PSException(\"Parameter ");
1878:                            lWriter.write(lParameterName);
1879:                            lWriter
1880:                                    .write(" is not expected to be empty for getByInstanceId() operation.\");\r\n");
1881:                            lWriter.write("        if (");
1882:                            lWriter.write(lParameterName);
1883:                            lWriter.write(".isConcealed())\r\n");
1884:                            lWriter
1885:                                    .write("            throw new PSException(\"Parameter ");
1886:                            lWriter.write(lParameterName);
1887:                            lWriter
1888:                                    .write(" is not expected to be concealed for getByInstanceId() operation.\");\r\n");
1889:                        }
1890:                        lWriter.println("        try");
1891:                        lWriter.println("        {");
1892:                        lWriter
1893:                                .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
1894:                        lWriter.println("            try");
1895:                        lWriter.println("            {");
1896:                        // Build primary key where clause, taking into account possibility that
1897:                        // primary key fields span multiple tables (this one and supertables)
1898:                        lWriter
1899:                                .println("                StringBuffer lPrimaryKeyWhereText = new StringBuffer();");
1900:                        lWriter
1901:                                .println("                QueryContext lQueryContext = new QueryContext(QueryContext.QueryType.QUERYTYPE_GETSINGLERECORD,\""
1902:                                        + lEntityTableName + "\");");
1903:                        Map lPrimaryKeyElementsPerTableMap = SQLJDBCUtil
1904:                                .getPrimaryKeyElementsPerTableMap(pEntity);
1905:                        boolean lHasElementsOfPrimaryKeyInMainEntity = lPrimaryKeyElementsPerTableMap
1906:                                .containsKey(pEntity);
1907:                        boolean lHasElementsOfPrimaryKeyInSuperentities = lPrimaryKeyElementsPerTableMap
1908:                                .size() > (lHasElementsOfPrimaryKeyInMainEntity ? 1
1909:                                : 0);
1910:                        // Build where clause
1911:                        {
1912:                            // Add conditions for this entity if there are some
1913:                            if (lHasElementsOfPrimaryKeyInMainEntity)
1914:                                writePartOfPrimaryKeyWhereClause(lWriter, null,
1915:                                        pEntity,
1916:                                        (List) lPrimaryKeyElementsPerTableMap
1917:                                                .get(pEntity), pDomainStorage);
1918:
1919:                            if (lHasElementsOfPrimaryKeyInSuperentities) {
1920:                                lWriter
1921:                                        .println("                lQueryContext.saveCurrentToTable();");
1922:                                // First write out superentities, than main entity.
1923:                                // Note that there might be the case when there are no primary key elements in the superentiies
1924:                                // or that thre are no primary key elements in the main entity
1925:                                // the writePartOfPrimaryKeyWhereClause() helper takes care of writing
1926:                                // all joins and compares. The only thing we need to do is to make sure
1927:                                // that main entity is processed last. This will ensure that it is "taken" and 
1928:                                // is the current entity by the time we start to worry about selectors
1929:                                Entity lPreviousEntity = pEntity;
1930:                                String lPreviousSuperEntityInstanceIdColumnName = null; // Used for linking
1931:                                for (Iterator lPrimaryKeyElementsPerTableMapIterator = lPrimaryKeyElementsPerTableMap
1932:                                        .entrySet().iterator(); lPrimaryKeyElementsPerTableMapIterator
1933:                                        .hasNext();) {
1934:                                    Map.Entry lEntry = (Map.Entry) lPrimaryKeyElementsPerTableMapIterator
1935:                                            .next();
1936:                                    Entity lSuperEntity = (Entity) lEntry
1937:                                            .getKey();
1938:                                    // Leave main table for last, iterate through all others
1939:                                    if (lSuperEntity.equals(pEntity))
1940:                                        continue;
1941:                                    writePartOfPrimaryKeyWhereClause(lWriter,
1942:                                            lPreviousEntity, lSuperEntity,
1943:                                            (List) lEntry.getValue(),
1944:                                            pDomainStorage);
1945:                                    lPreviousEntity = lSuperEntity;
1946:                                }
1947:                                lWriter
1948:                                        .println("                lQueryContext.restoreCurrentToTable();");
1949:                            }
1950:                        }
1951:
1952:                        // Build statement dynamically from selectors
1953:                        lWriter
1954:                                .println("                Selectors.SqlStatementParts lGeneratedSqlStatementParts = Selectors.getSqlStatementParts(pCollectionsDetails, lQueryContext);");
1955:                        lWriter
1956:                                .println("                StringBuffer lStatementText = new StringBuffer();");
1957:                        // No need to specify distinct - there can be at most one match any way
1958:                        // In fact we are better of not to have distinct because it does not work with lobs
1959:                        lWriter
1960:                                .println("                lStatementText.append(\"SELECT "
1961:                                        + lSelectStatementParts.WhatClauseForGetInstance
1962:                                        + " FROM \");");
1963:                        lWriter
1964:                                .println("                lStatementText.append(lGeneratedSqlStatementParts.mFromClause);");
1965:                        lWriter
1966:                                .println("                lStatementText.append(\" WHERE \");");
1967:                        lWriter
1968:                                .println("                lStatementText.append(lPrimaryKeyWhereText.toString());");
1969:                        lWriter
1970:                                .println("                if (lGeneratedSqlStatementParts.mWhereClause != null && lGeneratedSqlStatementParts.mWhereClause.length() > 0)");
1971:                        lWriter.println("                {");
1972:                        lWriter
1973:                                .println("                    // If there is a where clause - there are possibly some arguments too");
1974:                        lWriter
1975:                                .println("                    lStatementText.append(\" AND \");");
1976:                        lWriter
1977:                                .println("                    lStatementText.append(lGeneratedSqlStatementParts.mWhereClause);");
1978:                        lWriter.println("                }");
1979:                        // Limit and orderby can be ignored because this is a single instance getter
1980:                        lWriter
1981:                                .println("                String lStatementString = lStatementText.toString();");
1982:                        lWriter
1983:                                .println("                if (sLogger.isDebugEnabled())");
1984:                        lWriter
1985:                                .println("                    sLogger.debug(\"About to execute SQL statement: \" + lStatementString + \";\");");
1986:                        lWriter
1987:                                .println("                java.sql.PreparedStatement lGetByPrimaryKeyStatement = lDatabaseConnection.prepareStatement(lStatementString);");
1988:                        lWriter.println("                try");
1989:                        lWriter.println("                {");
1990:                        // Set up primary key parameters
1991:                        int lNextParameterIndex = 1;
1992:                        {
1993:                            // Work on main entity if required
1994:                            if (lHasElementsOfPrimaryKeyInMainEntity)
1995:                                lNextParameterIndex = writePartOfPrimaryKeyParameterSet(
1996:                                        lWriter, lNextParameterIndex,
1997:                                        (List) lPrimaryKeyElementsPerTableMap
1998:                                                .get(pEntity));
1999:                            // Work on supertypes if required
2000:                            if (lHasElementsOfPrimaryKeyInSuperentities) {
2001:                                for (Iterator lPrimaryKeyElementsPerTableMapIterator = lPrimaryKeyElementsPerTableMap
2002:                                        .entrySet().iterator(); lPrimaryKeyElementsPerTableMapIterator
2003:                                        .hasNext();) {
2004:                                    Map.Entry lEntry = (Map.Entry) lPrimaryKeyElementsPerTableMapIterator
2005:                                            .next();
2006:                                    Entity lSuperEntity = (Entity) lEntry
2007:                                            .getKey();
2008:                                    // Leave main table for last, iterate through all others
2009:                                    if (lSuperEntity.equals(pEntity))
2010:                                        continue;
2011:                                    lNextParameterIndex = writePartOfPrimaryKeyParameterSet(
2012:                                            lWriter, lNextParameterIndex,
2013:                                            (List) lEntry.getValue());
2014:                                }
2015:                            }
2016:                        }
2017:                        // Now set additional parameters
2018:                        lWriter
2019:                                .println("                    Selectors.populatePreparedStatement(pCollectionsDetails,lGetByPrimaryKeyStatement,"
2020:                                        + Integer.toString(lNextParameterIndex)
2021:                                        + ");");
2022:                        lWriter
2023:                                .println("                    java.sql.ResultSet lResultSet = lGetByPrimaryKeyStatement.executeQuery();");
2024:                        lWriter.println("                    try");
2025:                        lWriter.println("                    {");
2026:                        lWriter
2027:                                .println("                        if(lResultSet.next())");
2028:                        // If we have clobs or blobs - result set does contain them in this case
2029:                        if (lHasClobs || lHasBlobs)
2030:                            lWriter
2031:                                    .println("                            return unpackRecordFromResultSet(lResultSet, true);");
2032:                        else
2033:                            lWriter
2034:                                    .println("                            return unpackRecordFromResultSet(lResultSet);");
2035:                        lWriter.println("                        return null;");
2036:                        lWriter.println("                    }");
2037:                        lWriter.println("                    finally");
2038:                        lWriter.println("                    {");
2039:                        lWriter
2040:                                .println("                        if (lResultSet != null)");
2041:                        lWriter
2042:                                .println("                            lResultSet.close();");
2043:                        lWriter.println("                    }");
2044:                        lWriter.println("                }");
2045:                        lWriter.println("                finally");
2046:                        lWriter.println("                {");
2047:                        lWriter
2048:                                .println("                    if (lGetByPrimaryKeyStatement != null)");
2049:                        lWriter
2050:                                .println("                        lGetByPrimaryKeyStatement.close();");
2051:                        lWriter.println("                }");
2052:                        lWriter.println("            }");
2053:                        lWriter.println("            finally");
2054:                        lWriter.println("            {");
2055:                        lWriter
2056:                                .println("                if (lDatabaseConnection != null)");
2057:                        lWriter
2058:                                .println("                    Util.closeConnection(lDatabaseConnection);");
2059:                        lWriter.println("            }");
2060:                        lWriter.println("        }");
2061:                        lWriter
2062:                                .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
2063:                        lWriter.println("        {");
2064:                        lWriter
2065:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for empty instance\",e);");
2066:                        lWriter.println("        }");
2067:                        lWriter
2068:                                .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
2069:                        lWriter.println("        {");
2070:                        lWriter
2071:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for concealed instance\",e);");
2072:                        lWriter.println("        }");
2073:                        lWriter
2074:                                .println("        catch(java.sql.SQLException e)");
2075:                        lWriter.println("        {");
2076:                        lWriter
2077:                                .print("            throw new PSDataSourceOperationInvocationException(\"Error on getByPrimaryKey(");
2078:                        lWriter.print(lEntityStylesheet
2079:                                .getStorageRecordFullName());
2080:                        lWriter.println(")\", e);");
2081:                        lWriter.println("        }");
2082:                        lWriter.println("    }");
2083:                    }
2084:
2085:                    // Many-to-many associations for which we are agregators - we need to have crud methods
2086:                    // Possibly need to generate special many-to-many relationship structures
2087:                    // For each many-to-many association where we are aggregators - have two hashsets - one with ids to add another with ids to remove
2088:                    for (Iterator lAgregatedManyToManyReferencesIterator = lAgregatedManyToManyReferences
2089:                            .iterator(); lAgregatedManyToManyReferencesIterator
2090:                            .hasNext();) {
2091:                        AssociationRole lReference = (AssociationRole) lAgregatedManyToManyReferencesIterator
2092:                                .next();
2093:                        Association lAssociation = lReference.getAssociation();
2094:                        AssociationRole lReferencorRole = lReference
2095:                                .getOppositeRole();
2096:                        // At this point we have many-to-many association and we are aggregators - generate structure
2097:                        String lRolePluralName = lReference.getPluralName();
2098:                        STAssociationStylesheet lAssociationStylesheet = CodeGenerationStylesheetAccessor
2099:                                .getAssociationStylesheet(lAssociation);
2100:                        DataType lReferencedEntityInstanceIdDatatype = lReference
2101:                                .getEntity().getInstanceIdDataType();
2102:                        STDatatypeTranslationStylesheet lReferencedEntityInstanceIdDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
2103:                                .getDatatypeTranslationStylesheet(lReferencedEntityInstanceIdDatatype);
2104:                        DataTypeTranslationMetadata.SqlType lReferencedEntityInstanceIdDatatypeSqlType = DataTypeTranslationMetadata.SqlType
2105:                                .createFromName(lReferencedEntityInstanceIdDatatypeTranslationStylesheet
2106:                                        .getSqlTypeName());
2107:
2108:                        RelationalAssociationTable lRelationalAssociationTable = pDomainStorage
2109:                                .getAssociationTable(lAssociation);
2110:
2111:                        String lAssociationTableColumnName = lRelationalAssociationTable
2112:                                .getNameOverride();
2113:                        if (lAssociationTableColumnName == null
2114:                                || lAssociationTableColumnName.length() == 0)
2115:                            lAssociationTableColumnName = lRelationalAssociationTable
2116:                                    .getNameSuggestion();
2117:                        String lRoleInstanceIdColumnName = null;
2118:                        String lOppositeRoleInstanceIdColumnName = null;
2119:                        if (lAssociation.getRoles().get(0).equals(lReference)) {
2120:                            lRoleInstanceIdColumnName = lRelationalAssociationTable
2121:                                    .getFirstRoleColumnNameOverride();
2122:                            if (lRoleInstanceIdColumnName == null
2123:                                    || lRoleInstanceIdColumnName.length() == 0)
2124:                                lRoleInstanceIdColumnName = lRelationalAssociationTable
2125:                                        .getFirstRoleColumnNameSuggestion();
2126:
2127:                            lOppositeRoleInstanceIdColumnName = lRelationalAssociationTable
2128:                                    .getSecondRoleColumnNameOverride();
2129:                            if (lOppositeRoleInstanceIdColumnName == null
2130:                                    || lOppositeRoleInstanceIdColumnName
2131:                                            .length() == 0)
2132:                                lOppositeRoleInstanceIdColumnName = lRelationalAssociationTable
2133:                                        .getSecondRoleColumnNameSuggestion();
2134:                        } else {
2135:                            lRoleInstanceIdColumnName = lRelationalAssociationTable
2136:                                    .getSecondRoleColumnNameOverride();
2137:                            if (lRoleInstanceIdColumnName == null
2138:                                    || lRoleInstanceIdColumnName.length() == 0)
2139:                                lRoleInstanceIdColumnName = lRelationalAssociationTable
2140:                                        .getSecondRoleColumnNameSuggestion();
2141:
2142:                            lOppositeRoleInstanceIdColumnName = lRelationalAssociationTable
2143:                                    .getFirstRoleColumnNameOverride();
2144:                            if (lOppositeRoleInstanceIdColumnName == null
2145:                                    || lOppositeRoleInstanceIdColumnName
2146:                                            .length() == 0)
2147:                                lOppositeRoleInstanceIdColumnName = lRelationalAssociationTable
2148:                                        .getFirstRoleColumnNameSuggestion();
2149:                        }
2150:                        // Generate insert statement
2151:                        lWriter.println();
2152:                        lWriter
2153:                                .print("    private static final String sTextOfInsert"
2154:                                        + lRolePluralName
2155:                                        + "Statement = \"INSERT INTO ");
2156:                        lWriter.print(lAssociationTableColumnName);
2157:                        lWriter.print(" ( ");
2158:                        lWriter.print(lRoleInstanceIdColumnName);
2159:                        lWriter.print(", ");
2160:                        lWriter.print(lOppositeRoleInstanceIdColumnName);
2161:                        lWriter.println(") VALUES ( ?, ?)\";");
2162:                        // Generate insert operation
2163:                        lWriter.println();
2164:                        lWriter.println("    /* Inserts one or more new "
2165:                                + lAssociation.getName()
2166:                                + " association records into the database */");
2167:                        lWriter.println("    public void insert"
2168:                                + lRolePluralName
2169:                                + "( "
2170:                                + lAssociationStylesheet
2171:                                        .getStorageRecordFullName() + "[] pNew"
2172:                                + lRolePluralName + ") throws PSException");
2173:                        lWriter.println("    {");
2174:                        lWriter.println("        try");
2175:                        lWriter.println("        {");
2176:                        lWriter
2177:                                .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
2178:                        lWriter.println("            try");
2179:                        lWriter.println("            {");
2180:                        lWriter
2181:                                .println("                if (sLogger.isDebugEnabled())");
2182:                        lWriter
2183:                                .println("                    sLogger.debug(\"About to execute SQL statement: \" + sTextOfInsert"
2184:                                        + lRolePluralName
2185:                                        + "Statement + \";\");");
2186:                        lWriter
2187:                                .println("                java.sql.PreparedStatement lStatement = lDatabaseConnection.prepareStatement(sTextOfInsert"
2188:                                        + lRolePluralName + "Statement);");
2189:                        lWriter.println("                try");
2190:                        lWriter.println("                {");
2191:                        lWriter
2192:                                .println("                    for (int i = 0; i < pNew"
2193:                                        + lRolePluralName + ".length; i++)");
2194:                        lWriter.println("                    {");
2195:                        lWriter.println("                        "
2196:                                + lAssociationStylesheet
2197:                                        .getStorageRecordFullName()
2198:                                + " lNewAssociationRecord = pNew"
2199:                                + lRolePluralName + "[i];");
2200:                        // Both instance IDs are mandatory
2201:                        lWriter
2202:                                .println("                        if (lNewAssociationRecord."
2203:                                        + lReference.getName()
2204:                                        + "InstanceId == null)");
2205:                        lWriter
2206:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2207:                                        + lAssociationStylesheet
2208:                                                .getStorageRecordFullName()
2209:                                        + "."
2210:                                        + lReference.getName()
2211:                                        + "InstanceId is not expected to be undefined for insert"
2212:                                        + lRolePluralName + "() operation.\");");
2213:                        lWriter
2214:                                .println("                        if (lNewAssociationRecord."
2215:                                        + lReference.getName()
2216:                                        + "InstanceId.isEmpty())");
2217:                        lWriter
2218:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2219:                                        + lAssociationStylesheet
2220:                                                .getStorageRecordFullName()
2221:                                        + "."
2222:                                        + lReference.getName()
2223:                                        + "InstanceId is not expected to be empty for insert"
2224:                                        + lRolePluralName + "() operation.\");");
2225:                        lWriter
2226:                                .println("                        if (lNewAssociationRecord."
2227:                                        + lReference.getName()
2228:                                        + "InstanceId.isConcealed())");
2229:                        lWriter
2230:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2231:                                        + lAssociationStylesheet
2232:                                                .getStorageRecordFullName()
2233:                                        + "."
2234:                                        + lReference.getName()
2235:                                        + "InstanceId is not expected to be concealed for insert"
2236:                                        + lRolePluralName + "() operation.\");");
2237:                        lWriter
2238:                                .println("                        if (sLogger.isDebugEnabled())");
2239:                        lWriter
2240:                                .println("                            sLogger.debug(\"Parameter 1 value: \" + lNewAssociationRecord."
2241:                                        + lReference.getName() + "InstanceId);");
2242:                        lWriter
2243:                                .println("                        lStatement."
2244:                                        + getDataBaseMetaData()
2245:                                                .suggestStatementSetMethod(
2246:                                                        lReferencedEntityInstanceIdDatatype)
2247:                                        + "( 1, TypesConvertor.getSqlValueFrom"
2248:                                        + getUniqueDatatypeName(lReferencedEntityInstanceIdDatatype)
2249:                                        + "(lNewAssociationRecord."
2250:                                        + lReference.getName()
2251:                                        + "InstanceId));");
2252:                        lWriter
2253:                                .println("                        if (lNewAssociationRecord."
2254:                                        + lReferencorRole.getName()
2255:                                        + "InstanceId == null)");
2256:                        lWriter
2257:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2258:                                        + lAssociationStylesheet
2259:                                                .getStorageRecordFullName()
2260:                                        + "."
2261:                                        + lReferencorRole.getName()
2262:                                        + "InstanceId is not expected to be undefined for insert"
2263:                                        + lRolePluralName + "() operation.\");");
2264:                        lWriter
2265:                                .println("                        if (lNewAssociationRecord."
2266:                                        + lReferencorRole.getName()
2267:                                        + "InstanceId.isEmpty())");
2268:                        lWriter
2269:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2270:                                        + lAssociationStylesheet
2271:                                                .getStorageRecordFullName()
2272:                                        + "."
2273:                                        + lReferencorRole.getName()
2274:                                        + "InstanceId is not expected to be empty for insert"
2275:                                        + lRolePluralName + "() operation.\");");
2276:                        lWriter
2277:                                .println("                        if (lNewAssociationRecord."
2278:                                        + lReferencorRole.getName()
2279:                                        + "InstanceId.isConcealed())");
2280:                        lWriter
2281:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2282:                                        + lAssociationStylesheet
2283:                                                .getStorageRecordFullName()
2284:                                        + "."
2285:                                        + lReferencorRole.getName()
2286:                                        + "InstanceId is not expected to be concealed for insert"
2287:                                        + lRolePluralName + "() operation.\");");
2288:                        lWriter
2289:                                .println("                        if (sLogger.isDebugEnabled())");
2290:                        lWriter
2291:                                .println("                          sLogger.debug(\"Parameter 2 value: \" + lNewAssociationRecord."
2292:                                        + lReferencorRole.getName()
2293:                                        + "InstanceId);");
2294:                        lWriter.println("                        lStatement."
2295:                                + getDataBaseMetaData()
2296:                                        .suggestStatementSetMethod(
2297:                                                lInstanceIdDatatype)
2298:                                + "( 2, TypesConvertor.getSqlValueFrom"
2299:                                + getUniqueDatatypeName(lInstanceIdDatatype)
2300:                                + "(lNewAssociationRecord."
2301:                                + lReferencorRole.getName() + "InstanceId));");
2302:                        lWriter
2303:                                .println("                        lStatement.addBatch();");
2304:                        lWriter.println("                    }");
2305:                        lWriter
2306:                                .println("                    lStatement.executeBatch();");
2307:                        lWriter
2308:                                .println("                    lStatement.close();");
2309:                        lWriter
2310:                                .println("                    lStatement = null;");
2311:                        lWriter.println("                }");
2312:                        lWriter.println("                finally");
2313:                        lWriter.println("                {");
2314:                        lWriter
2315:                                .println("                    if (lStatement != null)");
2316:                        lWriter
2317:                                .println("                        lStatement.close();");
2318:                        lWriter.println("                }");
2319:                        lWriter.println("            }");
2320:                        lWriter.println("            finally");
2321:                        lWriter.println("            {");
2322:                        lWriter
2323:                                .println("                if (lDatabaseConnection != null)");
2324:                        lWriter
2325:                                .println("                    Util.closeConnection(lDatabaseConnection);");
2326:                        lWriter.println("            }");
2327:                        lWriter.println("        }");
2328:                        lWriter
2329:                                .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
2330:                        lWriter.println("        {");
2331:                        lWriter
2332:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for empty instance\",e);");
2333:                        lWriter.println("        }");
2334:                        lWriter
2335:                                .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
2336:                        lWriter.println("        {");
2337:                        lWriter
2338:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for concealed instance\",e);");
2339:                        lWriter.println("        }");
2340:                        lWriter
2341:                                .println("        catch(java.sql.SQLException e)");
2342:                        lWriter.println("        {");
2343:                        lWriter
2344:                                .println("            throw new PSDataSourceOperationInvocationException(\"Error on insert("
2345:                                        + lEntityStylesheet
2346:                                                .getStorageRecordFullName()
2347:                                        + ")\", e);");
2348:                        lWriter.println("        }");
2349:                        lWriter.println("    }");
2350:                        lWriter.println();
2351:                        // Generate delete statement
2352:                        lWriter.println();
2353:                        lWriter
2354:                                .print("    private static final String sTextOfDelete"
2355:                                        + lRolePluralName
2356:                                        + "Statement = \"DELETE FROM ");
2357:                        lWriter.print(lAssociationTableColumnName);
2358:                        lWriter.print(" WHERE ");
2359:                        lWriter.print(lRoleInstanceIdColumnName);
2360:                        lWriter.print(" = ? AND ");
2361:                        lWriter.print(lOppositeRoleInstanceIdColumnName);
2362:                        lWriter.println(" = ?\";");
2363:                        // Generate insert operation
2364:                        lWriter.println();
2365:                        lWriter.println("    /* Removes one or more existing "
2366:                                + lAssociation.getName()
2367:                                + " association records from the database */");
2368:                        lWriter.println("    public void remove"
2369:                                + lRolePluralName
2370:                                + "( "
2371:                                + lAssociationStylesheet
2372:                                        .getStorageRecordFullName() + "[] pOld"
2373:                                + lRolePluralName + ") throws PSException");
2374:                        lWriter.println("    {");
2375:                        lWriter.println("        try");
2376:                        lWriter.println("        {");
2377:                        lWriter
2378:                                .println("            java.sql.Connection lDatabaseConnection = Util.getConnection();");
2379:                        lWriter.println("            try");
2380:                        lWriter.println("            {");
2381:                        lWriter
2382:                                .println("                if (sLogger.isDebugEnabled())");
2383:                        lWriter
2384:                                .println("                    sLogger.debug(\"About to execute SQL statement: \" + sTextOfDelete"
2385:                                        + lRolePluralName
2386:                                        + "Statement + \";\");");
2387:                        lWriter
2388:                                .println("                java.sql.PreparedStatement lStatement = lDatabaseConnection.prepareStatement(sTextOfDelete"
2389:                                        + lRolePluralName + "Statement);");
2390:                        lWriter.println("                try");
2391:                        lWriter.println("                {");
2392:                        lWriter
2393:                                .println("                    for (int i = 0; i < pOld"
2394:                                        + lRolePluralName + ".length; i++)");
2395:                        lWriter.println("                    {");
2396:                        lWriter.println("                        "
2397:                                + lAssociationStylesheet
2398:                                        .getStorageRecordFullName()
2399:                                + " lOldAssociationRecord = pOld"
2400:                                + lRolePluralName + "[i];");
2401:                        // Both instance IDs are mandatory
2402:                        lWriter
2403:                                .println("                        if (lOldAssociationRecord."
2404:                                        + lReference.getName()
2405:                                        + "InstanceId == null)");
2406:                        lWriter
2407:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2408:                                        + lAssociationStylesheet
2409:                                                .getStorageRecordFullName()
2410:                                        + "."
2411:                                        + lReference.getName()
2412:                                        + "InstanceId is not expected to be undefined for insert"
2413:                                        + lRolePluralName + "() operation.\");");
2414:                        lWriter
2415:                                .println("                        if (lOldAssociationRecord."
2416:                                        + lReference.getName()
2417:                                        + "InstanceId.isEmpty())");
2418:                        lWriter
2419:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2420:                                        + lAssociationStylesheet
2421:                                                .getStorageRecordFullName()
2422:                                        + "."
2423:                                        + lReference.getName()
2424:                                        + "InstanceId is not expected to be empty for insert"
2425:                                        + lRolePluralName + "() operation.\");");
2426:                        lWriter
2427:                                .println("                        if (lOldAssociationRecord."
2428:                                        + lReference.getName()
2429:                                        + "InstanceId.isConcealed())");
2430:                        lWriter
2431:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2432:                                        + lAssociationStylesheet
2433:                                                .getStorageRecordFullName()
2434:                                        + "."
2435:                                        + lReference.getName()
2436:                                        + "InstanceId is not expected to be concealed for insert"
2437:                                        + lRolePluralName + "() operation.\");");
2438:                        lWriter
2439:                                .println("                        if (sLogger.isDebugEnabled())");
2440:                        lWriter
2441:                                .println("                            sLogger.debug(\"Parameter 1 value: \" + lOldAssociationRecord."
2442:                                        + lReference.getName() + "InstanceId);");
2443:                        lWriter
2444:                                .println("                        lStatement."
2445:                                        + getDataBaseMetaData()
2446:                                                .suggestStatementSetMethod(
2447:                                                        lReferencedEntityInstanceIdDatatype)
2448:                                        + "( 1, TypesConvertor.getSqlValueFrom"
2449:                                        + getUniqueDatatypeName(lReferencedEntityInstanceIdDatatype)
2450:                                        + "(lOldAssociationRecord."
2451:                                        + lReference.getName()
2452:                                        + "InstanceId));");
2453:                        lWriter
2454:                                .println("                        if (lOldAssociationRecord."
2455:                                        + lReferencorRole.getName()
2456:                                        + "InstanceId == null)");
2457:                        lWriter
2458:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2459:                                        + lAssociationStylesheet
2460:                                                .getStorageRecordFullName()
2461:                                        + "."
2462:                                        + lReferencorRole.getName()
2463:                                        + "InstanceId is not expected to be undefined for insert"
2464:                                        + lRolePluralName + "() operation.\");");
2465:                        lWriter
2466:                                .println("                        if (lOldAssociationRecord."
2467:                                        + lReferencorRole.getName()
2468:                                        + "InstanceId.isEmpty())");
2469:                        lWriter
2470:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2471:                                        + lAssociationStylesheet
2472:                                                .getStorageRecordFullName()
2473:                                        + "."
2474:                                        + lReferencorRole.getName()
2475:                                        + "InstanceId is not expected to be empty for insert"
2476:                                        + lRolePluralName + "() operation.\");");
2477:                        lWriter
2478:                                .println("                        if (lOldAssociationRecord."
2479:                                        + lReferencorRole.getName()
2480:                                        + "InstanceId.isConcealed())");
2481:                        lWriter
2482:                                .println("                            throw new PSAttributeConstraintViolationException(\""
2483:                                        + lAssociationStylesheet
2484:                                                .getStorageRecordFullName()
2485:                                        + "."
2486:                                        + lReferencorRole.getName()
2487:                                        + "InstanceId is not expected to be concealed for insert"
2488:                                        + lRolePluralName + "() operation.\");");
2489:                        lWriter
2490:                                .println("                        if (sLogger.isDebugEnabled())");
2491:                        lWriter
2492:                                .println("                            sLogger.debug(\"Parameter 2 value: \" + lOldAssociationRecord."
2493:                                        + lReferencorRole.getName()
2494:                                        + "InstanceId);");
2495:                        lWriter.println("                        lStatement."
2496:                                + getDataBaseMetaData()
2497:                                        .suggestStatementSetMethod(
2498:                                                lInstanceIdDatatype)
2499:                                + "( 2, TypesConvertor.getSqlValueFrom"
2500:                                + getUniqueDatatypeName(lInstanceIdDatatype)
2501:                                + "(lOldAssociationRecord."
2502:                                + lReferencorRole.getName() + "InstanceId));");
2503:                        lWriter
2504:                                .println("                        lStatement.addBatch();");
2505:                        lWriter.println("                    }");
2506:                        lWriter
2507:                                .println("                    lStatement.executeBatch();");
2508:                        lWriter
2509:                                .println("                    lStatement.close();");
2510:                        lWriter
2511:                                .println("                    lStatement = null;");
2512:                        lWriter.println("                }");
2513:                        lWriter.println("                finally");
2514:                        lWriter.println("                {");
2515:                        lWriter
2516:                                .println("                    if (lStatement != null)");
2517:                        lWriter
2518:                                .println("                        lStatement.close();");
2519:                        lWriter.println("                }");
2520:                        lWriter.println("            }");
2521:                        lWriter.println("            finally");
2522:                        lWriter.println("            {");
2523:                        lWriter
2524:                                .println("                if (lDatabaseConnection != null)");
2525:                        lWriter
2526:                                .println("                    Util.closeConnection(lDatabaseConnection);");
2527:                        lWriter.println("            }");
2528:                        lWriter.println("        }");
2529:                        lWriter
2530:                                .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
2531:                        lWriter.println("        {");
2532:                        lWriter
2533:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for empty instance\",e);");
2534:                        lWriter.println("        }");
2535:                        lWriter
2536:                                .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
2537:                        lWriter.println("        {");
2538:                        lWriter
2539:                                .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for concealed instance\",e);");
2540:                        lWriter.println("        }");
2541:                        lWriter
2542:                                .println("        catch(java.sql.SQLException e)");
2543:                        lWriter.println("        {");
2544:                        lWriter
2545:                                .println("            throw new PSDataSourceOperationInvocationException(\"Error on insert("
2546:                                        + lEntityStylesheet
2547:                                                .getStorageRecordFullName()
2548:                                        + ")\", e);");
2549:                        lWriter.println("        }");
2550:                        lWriter.println("    }");
2551:                    }
2552:
2553:                    // Write out the unpacking helper
2554:                    writeUnpackEntityHelperOperation(lWriter, pEntity,
2555:                            pDomainStorage);
2556:                    // Write out possible optional helper methods
2557:                    writeOptionalServiceImplementationHelpers(lWriter, pEntity,
2558:                            pDomainStorage);
2559:                    // For the entity, and each subtype - create helper methods
2560:                    for (Iterator lSupertypesAndSelfIterator = lSupertypesAndSelf
2561:                            .iterator(); lSupertypesAndSelfIterator.hasNext();) {
2562:                        Entity lSupertypesAndSelfEntity = (Entity) lSupertypesAndSelfIterator
2563:                                .next();
2564:                        writeInsertEntityHelperOperation(lWriter,
2565:                                lSupertypesAndSelfEntity, pDomainStorage);
2566:                        writeDeleteEntityHelperOperation(lWriter, pEntity,
2567:                                lSupertypesAndSelfEntity, pDomainStorage);
2568:                        writeOptionalUpdateEntityHelperOperation(lWriter,
2569:                                lSupertypesAndSelfEntity, pDomainStorage);
2570:                    }
2571:                    lWriter.println("}");
2572:                } catch (IOException e) {
2573:                    throw new BSException(e);
2574:                } catch (BOException e) {
2575:                    throw new BSDomainObjectInvocationException(e);
2576:                } finally {
2577:                    if (lWriter != null) {
2578:                        lWriter.flush();
2579:                        lWriter.close();
2580:                    }
2581:                    if (lFileWriter != null) {
2582:                        try {
2583:                            lFileWriter.flush();
2584:                        } catch (IOException e) {
2585:                            // Ignore
2586:                        }
2587:                        try {
2588:                            lFileWriter.close();
2589:                        } catch (IOException e) {
2590:                            // Ignore
2591:                        }
2592:                    }
2593:                }
2594:            }
2595:
2596:            private static void generateImplementationForUtilities(
2597:                    String pImplementationDir, String pImplementationPackage,
2598:                    Domain pDomain) throws BSException {
2599:                PrintWriter lWriter = null;
2600:                FileWriter lFileWriter = null;
2601:                // Generate services interface
2602:                try {
2603:                    String lUtilitiesFileName = pImplementationDir
2604:                            + File.separator + "Util.java";
2605:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
2606:                            lUtilitiesFileName));
2607:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
2608:                    // Package statement
2609:                    lWriter.println("package " + pImplementationPackage + ";");
2610:                    lWriter.println();
2611:                    lWriter.println("import java.sql.ResultSet;");
2612:                    lWriter.println("import java.sql.SQLException;");
2613:                    lWriter.println("import java.sql.Connection;");
2614:                    lWriter.println("import java.sql.PreparedStatement;");
2615:                    lWriter.println("import javax.transaction.Status;");
2616:                    lWriter.println("import javax.transaction.Transaction;");
2617:                    lWriter
2618:                            .println("import javax.transaction.TransactionManager;");
2619:                    lWriter.println("import org.apache.commons.logging.Log;");
2620:                    lWriter
2621:                            .println("import org.apache.commons.logging.LogFactory;");
2622:                    lWriter
2623:                            .println("import com.metaboss.enterprise.spi.JDBCConnectionProvider;");
2624:                    lWriter
2625:                            .println("import com.metaboss.enterprise.spi.JTAImplementationProvider;");
2626:                    lWriter
2627:                            .println("import com.metaboss.enterprise.ps.PSException;");
2628:                    lWriter
2629:                            .println("import com.metaboss.enterprise.ps.STCollectionDetails;");
2630:                    lWriter
2631:                            .println("import com.metaboss.enterprise.ps.PSUnexpectedProgramConditionException;");
2632:                    lWriter
2633:                            .println("import com.metaboss.enterprise.ps.PSTransactionServiceInvocationException;");
2634:                    lWriter
2635:                            .println("import com.metaboss.enterprise.ps.PSDataSourceOperationInvocationException;");
2636:                    lWriter
2637:                            .println("import com.metaboss.enterprise.ps.PSNamingAndDirectoryServiceInvocationException;");
2638:                    lWriter.println();
2639:                    lWriter.println("public class Util");
2640:                    lWriter.println("{");
2641:                    // Commons Logging instance.
2642:                    lWriter
2643:                            .println("    private static final Log sLogger = LogFactory.getLog(Util.class);");
2644:                    // The logical name of the datasource representing the database we are working with in this package
2645:                    com.metaboss.sdlctools.models.metabossmodel.enterprisemodel.System lSystem = pDomain
2646:                            .getSystem();
2647:                    Enterprise lEnterprise = lSystem.getEnterprise();
2648:                    lWriter
2649:                            .println("    private static final String DATASOURCE_NAME = \"DataSources_"
2650:                                    + lEnterprise.getName()
2651:                                    + "_"
2652:                                    + lSystem.getName()
2653:                                    + "_"
2654:                                    + pDomain.getName() + "\";");
2655:                    lWriter
2656:                            .println("    private static Object sJDBCConnectionProviderSemaphore = new Object();");
2657:                    lWriter
2658:                            .println("    private static JDBCConnectionProvider sJDBCConnectionProvider = null;");
2659:                    lWriter
2660:                            .println("    private static Object sJTAImplementationProviderSemaphore = new Object();");
2661:                    lWriter
2662:                            .println("    private static JTAImplementationProvider sJTAImplementationProvider = null;");
2663:                    lWriter
2664:                            .println("    private static final String sSelectNextAvailableSessionIdStatementString = \"SELECT next_available_session_id FROM idregistry WHERE table_name = ?\";");
2665:                    lWriter
2666:                            .println("    private static final String sIncrementNextAvailableSessionIdStatementString = \"UPDATE idregistry SET next_available_session_id = ? WHERE table_name = ? AND next_available_session_id = ?\";");
2667:                    lWriter.println();
2668:                    lWriter
2669:                            .println("    /** Retireves next available session id for the specified table. */");
2670:                    lWriter
2671:                            .println("    public static long getNextAvailableSessionId( String pEntityTableName) throws PSException");
2672:                    lWriter.println("    {");
2673:                    lWriter.println("        try");
2674:                    lWriter.println("        {");
2675:                    lWriter
2676:                            .println("            TransactionManager lTransactionManager = getTransactionManager();");
2677:                    lWriter
2678:                            .println("            Transaction lSuspendedTransaction = lTransactionManager.suspend();");
2679:                    lWriter.println("            try");
2680:                    lWriter.println("            {");
2681:                    lWriter
2682:                            .println("                lTransactionManager.begin();");
2683:                    lWriter.println("                try");
2684:                    lWriter.println("                {");
2685:                    lWriter
2686:                            .println("                    Connection lDatabaseConnection = getConnection();");
2687:                    lWriter.println("                    try");
2688:                    lWriter.println("                    {");
2689:                    lWriter
2690:                            .println("                        PreparedStatement lSelectStatement = lDatabaseConnection.prepareStatement(sSelectNextAvailableSessionIdStatementString);");
2691:                    lWriter
2692:                            .println("                        PreparedStatement lUpdateStatement = lDatabaseConnection.prepareStatement(sIncrementNextAvailableSessionIdStatementString);");
2693:                    lWriter
2694:                            .println("                        boolean lSuccess = false;");
2695:                    lWriter.println("                        try");
2696:                    lWriter.println("                        {");
2697:                    lWriter
2698:                            .println("                            lSelectStatement.setString(1,pEntityTableName);");
2699:                    lWriter
2700:                            .println("                            // Will retry getting the number forever till successfull");
2701:                    lWriter.println("                            while(true)");
2702:                    lWriter.println("                            {");
2703:                    lWriter
2704:                            .println("                                if (sLogger.isDebugEnabled())");
2705:                    lWriter
2706:                            .println("                                    sLogger.debug(\"About to execute SQL statement: \" + sSelectNextAvailableSessionIdStatementString + \";\");");
2707:                    lWriter
2708:                            .println("                                ResultSet lSelectResultSet =  lSelectStatement.executeQuery();");
2709:                    lWriter.println("                                try");
2710:                    lWriter.println("                                {");
2711:                    lWriter
2712:                            .println("                                    if (!lSelectResultSet.next())");
2713:                    lWriter
2714:                            .println("                                        throw new PSUnexpectedProgramConditionException(\"Table \" + pEntityTableName + \" appears to be undefined in the database \" + DATASOURCE_NAME + \". Unable to find idregistry record for it.\");");
2715:                    lWriter
2716:                            .println("                                    long lNextAvailableSessionId = lSelectResultSet.getLong(1);");
2717:                    lWriter
2718:                            .println("                                    long lPostNextAvailableSessionId = lNextAvailableSessionId+1;");
2719:
2720:                    lWriter
2721:                            .println("                                    if (sLogger.isDebugEnabled())");
2722:                    lWriter
2723:                            .println("                                        sLogger.debug(\"About to execute SQL statement: \" + sIncrementNextAvailableSessionIdStatementString + \";\");");
2724:                    lWriter
2725:                            .println("                                    lUpdateStatement.clearParameters();");
2726:
2727:                    lWriter
2728:                            .println("                                    if (sLogger.isDebugEnabled())");
2729:                    lWriter
2730:                            .println("                                        sLogger.debug(\"Parameter 1 value: \" + lPostNextAvailableSessionId);");
2731:                    lWriter
2732:                            .println("                                    lUpdateStatement.setLong(1,lPostNextAvailableSessionId);");
2733:
2734:                    lWriter
2735:                            .println("                                    if (sLogger.isDebugEnabled())");
2736:                    lWriter
2737:                            .println("                                        sLogger.debug(\"Parameter 2 value: \" + pEntityTableName);");
2738:                    lWriter
2739:                            .println("                                    lUpdateStatement.setString(2,pEntityTableName);");
2740:
2741:                    lWriter
2742:                            .println("                                    if (sLogger.isDebugEnabled())");
2743:                    lWriter
2744:                            .println("                                        sLogger.debug(\"Parameter 3 value: \" + lNextAvailableSessionId);");
2745:                    lWriter
2746:                            .println("                                    lUpdateStatement.setLong(3,lNextAvailableSessionId);");
2747:
2748:                    lWriter
2749:                            .println("                                    int lRowCount = lUpdateStatement.executeUpdate();");
2750:                    lWriter
2751:                            .println("                                    if (sLogger.isDebugEnabled())");
2752:                    lWriter
2753:                            .println("                                        sLogger.debug(\"Actual updated rows count: \" + lRowCount);");
2754:                    lWriter
2755:                            .println("                                    if (lRowCount == 1)");
2756:                    lWriter.println("                                    {");
2757:                    lWriter
2758:                            .println("                                       lSuccess = true;");
2759:                    lWriter
2760:                            .println("                                       return lNextAvailableSessionId;");
2761:                    lWriter.println("                                    }");
2762:                    lWriter.println("                                }");
2763:                    lWriter.println("                                finally");
2764:                    lWriter.println("                                {");
2765:                    lWriter
2766:                            .println("                                    if (lSelectResultSet != null)");
2767:                    lWriter
2768:                            .println("                                        lSelectResultSet.close();");
2769:                    lWriter.println("                                }");
2770:                    lWriter.println("                            }");
2771:                    lWriter.println("                        }");
2772:                    lWriter.println("                        finally");
2773:                    lWriter.println("                        {");
2774:                    // Allways set fo rollback if no success (eg. exception was thrown)
2775:                    lWriter
2776:                            .println("                            if (!lSuccess)");
2777:                    lWriter
2778:                            .println("                                lTransactionManager.setRollbackOnly();");
2779:                    // Close statements
2780:                    lWriter
2781:                            .println("                            if (lSelectStatement != null)");
2782:                    lWriter
2783:                            .println("                                lSelectStatement.close();");
2784:                    lWriter
2785:                            .println("                            if (lUpdateStatement != null)");
2786:                    lWriter
2787:                            .println("                                lUpdateStatement.close();");
2788:                    lWriter.println("                        }");
2789:                    lWriter.println("                    }");
2790:                    lWriter.println("                    finally");
2791:                    lWriter.println("                    {");
2792:                    lWriter
2793:                            .println("                        if (lDatabaseConnection != null)");
2794:                    lWriter
2795:                            .println("                            closeConnection(lDatabaseConnection);");
2796:                    lWriter.println("                    }");
2797:                    lWriter.println("                }");
2798:                    lWriter
2799:                            .println("                catch(java.sql.SQLException e)");
2800:                    lWriter.println("                {");
2801:                    lWriter
2802:                            .println("                    throw new PSDataSourceOperationInvocationException(\"Unable to obtain next available session id for the \" + pEntityTableName + \" table.\", e);");
2803:                    lWriter.println("                }");
2804:                    lWriter.println("                finally");
2805:                    lWriter.println("                {");
2806:                    lWriter
2807:                            .println("                    int lStatus = lTransactionManager.getStatus();");
2808:                    lWriter
2809:                            .println("                    if (lStatus == Status.STATUS_ACTIVE)");
2810:                    lWriter
2811:                            .println("                        lTransactionManager.commit();");
2812:                    lWriter.println("                    else");
2813:                    lWriter
2814:                            .println("                    if (lStatus == Status.STATUS_MARKED_ROLLBACK)");
2815:                    lWriter
2816:                            .println("                        lTransactionManager.rollback();");
2817:                    lWriter.println("                    else");
2818:                    lWriter
2819:                            .println("                        throw new com.metaboss.enterprise.ps.PSUnexpectedProgramConditionException(\"Invalid Transaction status : \" + lStatus);");
2820:                    lWriter.println("                }");
2821:                    lWriter.println("            }");
2822:                    lWriter.println("            finally");
2823:                    lWriter.println("            {");
2824:                    lWriter
2825:                            .println("                if (lSuspendedTransaction != null)");
2826:                    lWriter
2827:                            .println("                    lTransactionManager.resume(lSuspendedTransaction);");
2828:                    lWriter.println("            }");
2829:                    lWriter.println("        }");
2830:                    lWriter
2831:                            .println("        catch( javax.transaction.SystemException e )");
2832:                    lWriter.println("        {");
2833:                    lWriter
2834:                            .println("            throw new PSTransactionServiceInvocationException(e);");
2835:                    lWriter.println("        }");
2836:                    lWriter
2837:                            .println("        catch( javax.transaction.InvalidTransactionException e )");
2838:                    lWriter.println("        {");
2839:                    lWriter
2840:                            .println("            throw new PSTransactionServiceInvocationException(e);");
2841:                    lWriter.println("        }");
2842:                    lWriter
2843:                            .println("        catch( javax.transaction.HeuristicRollbackException e )");
2844:                    lWriter.println("        {");
2845:                    lWriter
2846:                            .println("            throw new PSTransactionServiceInvocationException(e);");
2847:                    lWriter.println("        }");
2848:                    lWriter
2849:                            .println("        catch( javax.transaction.NotSupportedException e )");
2850:                    lWriter.println("        {");
2851:                    lWriter
2852:                            .println("            throw new PSTransactionServiceInvocationException(e);");
2853:                    lWriter.println("        }");
2854:                    lWriter
2855:                            .println("        catch( javax.transaction.HeuristicMixedException e )");
2856:                    lWriter.println("        {");
2857:                    lWriter
2858:                            .println("            throw new PSTransactionServiceInvocationException(e);");
2859:                    lWriter.println("        }");
2860:                    lWriter
2861:                            .println("        catch( javax.transaction.RollbackException e )");
2862:                    lWriter.println("        {");
2863:                    lWriter
2864:                            .println("            throw new PSTransactionServiceInvocationException(e);");
2865:                    lWriter.println("        }");
2866:                    lWriter.println("    }");
2867:                    lWriter.println();
2868:                    lWriter
2869:                            .println("    /** Retireves datasource connection applicable to the caller. */");
2870:                    lWriter
2871:                            .println("    public static Connection getConnection() throws PSException");
2872:                    lWriter.println("    {");
2873:                    lWriter.println("        try");
2874:                    lWriter.println("        {");
2875:                    lWriter
2876:                            .println("            if (sJDBCConnectionProvider == null)");
2877:                    lWriter.println("            {");
2878:                    lWriter
2879:                            .println("                synchronized(sJDBCConnectionProviderSemaphore)");
2880:                    lWriter.println("                {");
2881:                    lWriter
2882:                            .println("                    if (sJDBCConnectionProvider == null)");
2883:                    lWriter.println("                    {");
2884:                    lWriter.println("                        try");
2885:                    lWriter.println("                        {");
2886:                    lWriter
2887:                            .println("                            javax.naming.Context lContext = new javax.naming.InitialContext();");
2888:                    lWriter
2889:                            .println("                            sJDBCConnectionProvider = (JDBCConnectionProvider)lContext.lookup(JDBCConnectionProvider.COMPONENT_URL);");
2890:                    lWriter.println("                        }");
2891:                    lWriter
2892:                            .println("                        catch( javax.naming.NamingException e )");
2893:                    lWriter.println("                        {");
2894:                    lWriter
2895:                            .println("                            throw new com.metaboss.enterprise.ps.PSNamingAndDirectoryServiceInvocationException(\"Unable to obtain JDBCConnectionProvider instance\", e);");
2896:                    lWriter.println("                        }");
2897:                    lWriter.println("                    }");
2898:                    lWriter.println("                }");
2899:                    lWriter.println("            }");
2900:                    lWriter
2901:                            .println("            return sJDBCConnectionProvider.getConnection(DATASOURCE_NAME);");
2902:                    lWriter.println("        }");
2903:                    lWriter.println("        catch(java.sql.SQLException e)");
2904:                    lWriter.println("        {");
2905:                    lWriter
2906:                            .println("            throw new PSDataSourceOperationInvocationException(\"Unable to obtain SQL Connection\", e);");
2907:                    lWriter.println("        }");
2908:                    lWriter.println("    }");
2909:                    lWriter.println();
2910:                    lWriter
2911:                            .println("    /** Closes previously obtained datasource connection. */");
2912:                    lWriter
2913:                            .println("    public static void closeConnection(Connection pConnection) throws PSException");
2914:                    lWriter.println("    {");
2915:                    lWriter.println("        try");
2916:                    lWriter.println("        {");
2917:                    lWriter
2918:                            .println("            if (sJDBCConnectionProvider == null)");
2919:                    lWriter
2920:                            .println("                throw new com.metaboss.enterprise.ps.PSUnexpectedProgramConditionException(\"Connection object pased for closing even before JDBC access has been initialised\");");
2921:                    lWriter
2922:                            .println("            sJDBCConnectionProvider.closeConnection(pConnection);");
2923:                    lWriter.println("        }");
2924:                    lWriter.println("        catch(java.sql.SQLException e)");
2925:                    lWriter.println("        {");
2926:                    lWriter
2927:                            .println("            throw new PSDataSourceOperationInvocationException(\"Unable to close SQL Connection\", e);");
2928:                    lWriter.println("        }");
2929:                    lWriter.println("    }");
2930:                    lWriter.println();
2931:                    lWriter
2932:                            .println("    // Helper. Retireves TransactionManager instance");
2933:                    lWriter
2934:                            .println("    private static TransactionManager getTransactionManager() throws PSException");
2935:                    lWriter.println("    {");
2936:                    lWriter.println("        try");
2937:                    lWriter.println("        {");
2938:                    lWriter
2939:                            .println("            if (sJTAImplementationProvider == null)");
2940:                    lWriter.println("            {");
2941:                    lWriter
2942:                            .println("                synchronized(sJTAImplementationProviderSemaphore)");
2943:                    lWriter.println("                {");
2944:                    lWriter
2945:                            .println("                    if (sJTAImplementationProvider == null)");
2946:                    lWriter.println("                    {");
2947:                    lWriter.println("                        try");
2948:                    lWriter.println("                        {");
2949:                    lWriter
2950:                            .println("                            javax.naming.Context lContext = new javax.naming.InitialContext();");
2951:                    lWriter
2952:                            .println("                            sJTAImplementationProvider = (JTAImplementationProvider)lContext.lookup(JTAImplementationProvider.COMPONENT_URL);");
2953:                    lWriter.println("                        }");
2954:                    lWriter
2955:                            .println("                        catch( javax.naming.NamingException e )");
2956:                    lWriter.println("                        {");
2957:                    lWriter
2958:                            .println("                            throw new com.metaboss.enterprise.ps.PSNamingAndDirectoryServiceInvocationException(\"Unable to obtain JTAImplementationProvider instance\", e);");
2959:                    lWriter.println("                        }");
2960:                    lWriter.println("                    }");
2961:                    lWriter.println("                }");
2962:                    lWriter.println("            }");
2963:                    lWriter
2964:                            .println("            return sJTAImplementationProvider.getTransactionManager();");
2965:                    lWriter.println("        }");
2966:                    lWriter
2967:                            .println("        catch(javax.transaction.SystemException e)");
2968:                    lWriter.println("        {");
2969:                    lWriter
2970:                            .println("            throw new PSTransactionServiceInvocationException(\"Unable to obtain Transaction Manager instance\", e);");
2971:                    lWriter.println("        }");
2972:                    lWriter.println("    }");
2973:
2974:                    lWriter.println();
2975:                    lWriter
2976:                            .println("    // Helper. Returns STCollectionDetails where the subset instruction is suppressed even if there was one");
2977:                    lWriter
2978:                            .println("    // This is called by methods wishing to obtain sql statement without subset of the last query");
2979:                    lWriter
2980:                            .println("    public static STCollectionDetails[] suppressSubsetInstruction(STCollectionDetails[] pOriginalCollectionDetails) throws PSException");
2981:                    lWriter.println("    {");
2982:                    lWriter
2983:                            .println("        if (pOriginalCollectionDetails == null)");
2984:                    lWriter.println("            return null;"); // Nothing to do
2985:                    lWriter
2986:                            .println("        int lLength = pOriginalCollectionDetails.length;");
2987:                    lWriter.println("        if (lLength == 0)"); // Nothing to do
2988:                    lWriter
2989:                            .println("            return pOriginalCollectionDetails;");
2990:                    lWriter
2991:                            .println("        STCollectionDetails lTopDetails = pOriginalCollectionDetails[lLength-1];");
2992:                    lWriter
2993:                            .println("        if (lTopDetails.ResultStartOffset == null)");
2994:                    lWriter
2995:                            .println("            return pOriginalCollectionDetails;"); // Nothing to do
2996:                    // Looks like we need to suppress. Do it by shallow copying whole array except 
2997:                    // top element, then deep copying top element and setting start offset and max size to null in the new top element 
2998:                    lWriter
2999:                            .println("        STCollectionDetails[] lModifiedDetails = new STCollectionDetails[lLength];");
3000:                    lWriter.println("        if (lLength > 1)");
3001:                    lWriter
3002:                            .println("            System.arraycopy(pOriginalCollectionDetails, 0, lModifiedDetails, 0, lLength-1);");
3003:                    lWriter
3004:                            .println("        STCollectionDetails lNewTopDetails = lModifiedDetails[lLength-1] = new STCollectionDetails(lTopDetails);");
3005:                    lWriter
3006:                            .println("        lNewTopDetails.ResultStartOffset = null;");
3007:                    lWriter
3008:                            .println("        lNewTopDetails.ResultMaximumSize = null;");
3009:                    lWriter.println("        return lModifiedDetails;");
3010:                    lWriter.println("    }");
3011:                    lWriter.println();
3012:                    lWriter
3013:                            .println("    // Helper. Returns STCollectionDetails where the sorting instruction is suppressed even if there was one");
3014:                    lWriter
3015:                            .println("    // This is called by methods wishing to obtain sql statement without sorting of the last query");
3016:                    lWriter
3017:                            .println("    public static STCollectionDetails[] suppressSortingInstruction(STCollectionDetails[] pOriginalCollectionDetails) throws PSException");
3018:                    lWriter.println("    {");
3019:                    lWriter
3020:                            .println("        if (pOriginalCollectionDetails == null)");
3021:                    lWriter.println("            return null;"); // Nothing to do
3022:                    lWriter
3023:                            .println("        int lLength = pOriginalCollectionDetails.length;");
3024:                    lWriter.println("        if (lLength == 0)"); // Nothing to do
3025:                    lWriter
3026:                            .println("            return pOriginalCollectionDetails;");
3027:                    lWriter
3028:                            .println("        STCollectionDetails lTopDetails = pOriginalCollectionDetails[lLength-1];");
3029:                    lWriter
3030:                            .println("        if (lTopDetails.Sorters == null || lTopDetails.Sorters.length == 0)");
3031:                    lWriter
3032:                            .println("            return pOriginalCollectionDetails;"); // Nothing to do
3033:                    // Looks like we need to suppress. Do it by shallow copying whole array except 
3034:                    // top element, then deep copying top element and setting sorters to null in the new top element 
3035:                    lWriter
3036:                            .println("        STCollectionDetails[] lModifiedDetails = new STCollectionDetails[lLength];");
3037:                    lWriter.println("        if (lLength > 1)");
3038:                    lWriter
3039:                            .println("            System.arraycopy(pOriginalCollectionDetails, 0, lModifiedDetails, 0, lLength-1);");
3040:                    lWriter
3041:                            .println("        STCollectionDetails lNewTopDetails = lModifiedDetails[lLength-1] = new STCollectionDetails(lTopDetails);");
3042:                    lWriter.println("        lNewTopDetails.Sorters = null;");
3043:                    lWriter.println("        return lModifiedDetails;");
3044:                    lWriter.println("    }");
3045:                    //			lWriter.println();
3046:                    //			lWriter.println("    // Helper. Returns STCollectionDetails where the sorting instruction is suppressed even if there was one");
3047:                    //			lWriter.println("    // This is called by methods wishing to obtain sql statement without sorting of the last query");
3048:                    //			lWriter.println("    public static STCollectionDetails suppressSortingInstruction(STCollectionDetails pOriginalCollectionDetails) throws PSException");
3049:                    //			lWriter.println("    {");
3050:                    //			lWriter.println("        if (pOriginalCollectionDetails == null)");
3051:                    //			lWriter.println("            return null;"); // Nothing to do
3052:                    //			lWriter.println("        if (pOriginalCollectionDetails.Sorters == null || pOriginalCollectionDetails.Sorters.length == 0)");
3053:                    //			lWriter.println("            return pOriginalCollectionDetails;"); // Nothing to do
3054:                    //			// Looks like we need to suppress do it by shallow copying whole array
3055:                    //			// and setting sorters to null in the new top element 
3056:                    //			lWriter.println("        STCollectionDetails lModifiedDetails = new STCollectionDetails(pOriginalCollectionDetails);");
3057:                    //			lWriter.println("        lModifiedDetails.Sorters = null;");
3058:                    //			lWriter.println("        return lModifiedDetails;");
3059:                    //			lWriter.println("    }");
3060:
3061:                    lWriter.println();
3062:                    lWriter
3063:                            .println("    // Helper. Returns STCollectionDetails where the sorting instruction is suppressed if there was one");
3064:                    lWriter
3065:                            .println("    // and if there is no sorting. This is called by methods not wishing to have final collection sorted unless there is a subset");
3066:                    lWriter
3067:                            .println("    // Since subset is taken after ordering some operations might want ordering - some might not");
3068:                    lWriter
3069:                            .println("    public static STCollectionDetails[] suppressSortingIfNoSubsetInstruction(STCollectionDetails[] pOriginalCollectionDetails) throws PSException");
3070:                    lWriter.println("    {");
3071:                    lWriter
3072:                            .println("        if (pOriginalCollectionDetails == null)");
3073:                    lWriter.println("            return null;"); // Nothing to do
3074:                    lWriter
3075:                            .println("        int lLength = pOriginalCollectionDetails.length;");
3076:                    lWriter.println("        if (lLength == 0)"); // Nothing to do
3077:                    lWriter
3078:                            .println("            return pOriginalCollectionDetails;");
3079:                    lWriter
3080:                            .println("        STCollectionDetails lTopDetails = pOriginalCollectionDetails[lLength-1];");
3081:                    lWriter
3082:                            .println("        if (lTopDetails.Sorters == null || lTopDetails.Sorters.length == 0)");
3083:                    lWriter
3084:                            .println("            return pOriginalCollectionDetails;"); // Nothing to do since there is no ordering any way
3085:                    lWriter
3086:                            .println("        if (lTopDetails.ResultStartOffset != null)");
3087:                    lWriter
3088:                            .println("            return pOriginalCollectionDetails;"); // Nothing to do since there is subset - so ordering must stay 
3089:                    // Looks like we need to suppress. Do it by shallow copying whole array except 
3090:                    // top element, then deep copying top element and setting sorters to null in the new top element 
3091:                    lWriter
3092:                            .println("        STCollectionDetails[] lModifiedDetails = new STCollectionDetails[lLength];");
3093:                    lWriter.println("        if (lLength > 1)");
3094:                    lWriter
3095:                            .println("            System.arraycopy(pOriginalCollectionDetails, 0, lModifiedDetails, 0, lLength-1);");
3096:                    lWriter
3097:                            .println("        STCollectionDetails lNewTopDetails = lModifiedDetails[lLength-1] = new STCollectionDetails(lTopDetails);");
3098:                    lWriter.println("        lNewTopDetails.Sorters = null;");
3099:                    lWriter.println("        return lModifiedDetails;");
3100:                    lWriter.println("    }");
3101:                    lWriter.println("}");
3102:                } catch (IOException e) {
3103:                    throw new BSException(e);
3104:                } catch (JmiException e) {
3105:                    throw new BSServiceProviderException(e);
3106:                } finally {
3107:                    if (lFileWriter != null) {
3108:                        try {
3109:                            lFileWriter.flush();
3110:                        } catch (IOException e) {
3111:                            // Ignore
3112:                        }
3113:                        try {
3114:                            lFileWriter.close();
3115:                        } catch (IOException e) {
3116:                            // Ignore
3117:                        }
3118:                    }
3119:                    if (lWriter != null) {
3120:                        lWriter.flush();
3121:                        lWriter.close();
3122:                    }
3123:                }
3124:            }
3125:
3126:            // Generate table names dictionary class
3127:            // This class contains static names maps. Its instances also have
3128:            // a mechanism to keep a dynamic list of used tables with aliases
3129:            private static void generateQueryContext(String pImplementationDir,
3130:                    String pImplementationPackage, Domain pDomain,
3131:                    DomainRelationalStorageDefinition pDomainStorage)
3132:                    throws BSException {
3133:                PrintWriter lWriter = null;
3134:                FileWriter lFileWriter = null;
3135:                // Generate full data structure
3136:                try {
3137:                    STDomainStylesheet lDomainStylesheet = CodeGenerationStylesheetAccessor
3138:                            .getDomainStylesheet(pDomain);
3139:                    String lDomainServiceFileName = pImplementationDir
3140:                            + File.separator + "QueryContext.java";
3141:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
3142:                            lDomainServiceFileName));
3143:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
3144:                    // Package statement
3145:                    lWriter.println("package " + pImplementationPackage + ";");
3146:                    lWriter.println();
3147:                    lWriter.println("import java.util.Map;");
3148:                    lWriter.println("import java.util.List;");
3149:                    lWriter.println("import java.util.HashMap;");
3150:                    lWriter.println("import java.util.ArrayList;");
3151:                    lWriter.println("import java.util.Iterator;");
3152:                    lWriter.println();
3153:                    lWriter.println("public class QueryContext");
3154:                    lWriter.println("{");
3155:                    // This enumerable class holds possible types of queries
3156:                    lWriter.println();
3157:                    lWriter.println("    public static final class QueryType");
3158:                    lWriter.println("    {");
3159:                    lWriter.println("        private String mTypeName = null;");
3160:                    lWriter.println();
3161:                    lWriter
3162:                            .println("        private QueryType(String pTypeName)");
3163:                    lWriter.println("        {");
3164:                    lWriter.println("            mTypeName = pTypeName;");
3165:                    lWriter.println("        }");
3166:                    lWriter.println();
3167:                    lWriter
3168:                            .println("        public boolean equals(Object pOther)");
3169:                    lWriter.println("        {");
3170:                    lWriter.println("            if (pOther == null)");
3171:                    lWriter.println("                return false;");
3172:                    lWriter
3173:                            .println("            if ((pOther instanceof QueryType) == false)");
3174:                    lWriter.println("                return false;");
3175:                    lWriter
3176:                            .println("            return mTypeName.equals(((QueryType)pOther).mTypeName);");
3177:                    lWriter.println("        }");
3178:                    // SELECT COUNT(RECORDID)
3179:                    lWriter
3180:                            .println("        public static final QueryType QUERYTYPE_COUNTRECORDS = new QueryType(\"COUNTRECORDS\");");
3181:                    // SELECT RECORDID
3182:                    lWriter
3183:                            .println("        public static final QueryType QUERYTYPE_GETALLRECORDIDS = new QueryType(\"GETALLRECORDIDS\");");
3184:                    // SELECT LIST OF ALL NON LOB FIELDS
3185:                    lWriter
3186:                            .println("        public static final QueryType QUERYTYPE_GETALLRECORDS = new QueryType(\"GETALLRECORDS\");");
3187:                    // SELECT LIST OF ALL FIELDS
3188:                    lWriter
3189:                            .println("        public static final QueryType QUERYTYPE_GETSINGLERECORD = new QueryType(\"GETSINGLERECORD\");");
3190:                    lWriter.println("    }");
3191:
3192:                    lWriter
3193:                            .println("    private static Map sTableAliasesMap = new HashMap();");
3194:                    lWriter
3195:                            .println("    private static Map sTableNamesMap = new HashMap();");
3196:                    lWriter
3197:                            .println("    private static Map sEntityTableInstanceIdColumnNamesMap = new HashMap();");
3198:                    lWriter
3199:                            .println("    private static Map sEntityTableAllColumnNamesMap = new HashMap();"); // List of column names used in individual entity query
3200:                    lWriter
3201:                            .println("    private static Map sEntityTableLightColumnNamesMap = new HashMap();"); // List of column names used in the collection query
3202:                    lWriter.println("    static");
3203:                    lWriter.println("    {");
3204:                    // Iterate through entities and populate entity table metadata
3205:                    // as well as reference tables metadata
3206:                    Set lAlreadyProcessedDataTypes = new HashSet();
3207:                    TypeTemplate lEnumerableValueTypeTemplate = pDomain
3208:                            .getSystem().getEnterprise().getDesignLibrary()
3209:                            .getDataDictionary("core").getTypeTemplate(
3210:                                    "EnumerableValueField");
3211:                    for (Iterator lEntitiesIterator = pDomain.getEntities()
3212:                            .iterator(); lEntitiesIterator.hasNext();) {
3213:                        Entity lEntity = (Entity) lEntitiesIterator.next();
3214:                        RelationalEntityTable lEntityTable = pDomainStorage
3215:                                .getEntityTable(lEntity);
3216:                        String lEntityTableName = lEntityTable
3217:                                .getNameOverride();
3218:                        if (lEntityTableName == null
3219:                                || lEntityTableName.length() == 0)
3220:                            lEntityTableName = lEntityTable.getNameSuggestion();
3221:                        String lEntityTableAlias = lEntityTable.getTableAlias();
3222:                        String lEntityTableInstanceIdColumnName = lEntityTable
3223:                                .getInstanceIdColumnNameOverride();
3224:                        if (lEntityTableInstanceIdColumnName == null
3225:                                || lEntityTableInstanceIdColumnName.length() == 0)
3226:                            lEntityTableInstanceIdColumnName = lEntityTable
3227:                                    .getInstanceIdColumnNameSuggestion();
3228:                        lWriter.println("        sTableNamesMap.put(\""
3229:                                + lEntity.getRef() + "\", \""
3230:                                + lEntityTableName + "\");");
3231:                        lWriter.println("        sTableAliasesMap.put(\""
3232:                                + lEntityTableName + "\", \""
3233:                                + lEntityTableAlias + "\");");
3234:                        lWriter
3235:                                .println("        sEntityTableInstanceIdColumnNamesMap.put(\""
3236:                                        + lEntityTableName
3237:                                        + "\", \""
3238:                                        + lEntityTableInstanceIdColumnName
3239:                                        + "\");");
3240:                        lWriter
3241:                                .println("        sEntityTableAllColumnNamesMap.put(\""
3242:                                        + lEntityTableName
3243:                                        + "\", new String[] {"
3244:                                        + generateEntityColumnsArrayInitialiser(
3245:                                                lEntity, pDomainStorage, false)
3246:                                        + "});");
3247:                        lWriter
3248:                                .println("        sEntityTableLightColumnNamesMap.put(\""
3249:                                        + lEntityTableName
3250:                                        + "\", new String[] {"
3251:                                        + generateEntityColumnsArrayInitialiser(
3252:                                                lEntity, pDomainStorage, true)
3253:                                        + "});");
3254:                        for (Iterator lAttributesIterator = lEntity
3255:                                .getAttributes().iterator(); lAttributesIterator
3256:                                .hasNext();) {
3257:                            Attribute lAttribute = (Attribute) lAttributesIterator
3258:                                    .next();
3259:                            DataType lAttributeDatatype = lAttribute
3260:                                    .getDataType();
3261:                            if (!lAlreadyProcessedDataTypes
3262:                                    .contains(lAttributeDatatype)) {
3263:                                TypeTemplate lTypetemplate = lAttributeDatatype
3264:                                        .getTypetemplate();
3265:                                if (lTypetemplate != null
3266:                                        && lTypetemplate
3267:                                                .equals(lEnumerableValueTypeTemplate)) {
3268:                                    // This data type has a reference table - we have to note it's alias
3269:                                    RelationalReferenceTable lReferenceTable = pDomainStorage
3270:                                            .getReferenceTable(lAttributeDatatype);
3271:                                    String lReferenceTableName = lReferenceTable
3272:                                            .getNameOverride();
3273:                                    if (lReferenceTableName == null
3274:                                            || lReferenceTableName.length() == 0)
3275:                                        lReferenceTableName = lReferenceTable
3276:                                                .getNameSuggestion();
3277:                                    String lReferenceTableAlias = lReferenceTable
3278:                                            .getTableAlias();
3279:                                    lWriter
3280:                                            .println("        sTableNamesMap.put(\""
3281:                                                    + lAttributeDatatype
3282:                                                            .getRef()
3283:                                                    + "\", \""
3284:                                                    + lReferenceTableName
3285:                                                    + "\");");
3286:                                    lWriter
3287:                                            .println("        sTableAliasesMap.put(\""
3288:                                                    + lReferenceTableName
3289:                                                    + "\", \""
3290:                                                    + lReferenceTableAlias
3291:                                                    + "\");");
3292:                                    lAlreadyProcessedDataTypes
3293:                                            .add(lAttributeDatatype);
3294:                                }
3295:                            }
3296:                        }
3297:                    }
3298:                    // Iterate through associationsand populate association table metadata
3299:                    for (Iterator lAssociationsIterator = pDomain
3300:                            .getAssociations().iterator(); lAssociationsIterator
3301:                            .hasNext();) {
3302:                        Association lAssociation = (Association) lAssociationsIterator
3303:                                .next();
3304:                        if (!CommonUtil.doEntitiesStoreReference(lAssociation)) {
3305:                            // Load optional middle table metadata
3306:                            RelationalAssociationTable lAssociationTable = pDomainStorage
3307:                                    .getAssociationTable(lAssociation);
3308:                            String lMiddleTableName = lAssociationTable
3309:                                    .getNameOverride();
3310:                            if (lMiddleTableName == null
3311:                                    || lMiddleTableName.length() == 0)
3312:                                lMiddleTableName = lAssociationTable
3313:                                        .getNameSuggestion();
3314:                            String lMiddleTableAlias = lAssociationTable
3315:                                    .getTableAlias();
3316:                            lWriter.println("        sTableNamesMap.put(\""
3317:                                    + lAssociation.getRef() + "\", \""
3318:                                    + lMiddleTableName + "\");");
3319:                            lWriter.println("        sTableAliasesMap.put(\""
3320:                                    + lMiddleTableName + "\", \""
3321:                                    + lMiddleTableAlias + "\");");
3322:                        }
3323:                    }
3324:                    lWriter.println("    }");
3325:                    // Returns the name of the entity table given entity reference
3326:                    lWriter.println();
3327:                    lWriter
3328:                            .println("    static String getTableNameByModelRef(String pModelElementRef)");
3329:                    lWriter.println("    {");
3330:                    lWriter
3331:                            .println("        return (String)sTableNamesMap.get(pModelElementRef);");
3332:                    lWriter.println("    }");
3333:                    // Returns the table alias given table name
3334:                    lWriter.println();
3335:                    lWriter
3336:                            .println("    static String getTableAliasByTableName(String pTableName)");
3337:                    lWriter.println("    {");
3338:                    lWriter
3339:                            .println("        return (String)sTableAliasesMap.get(pTableName);");
3340:                    lWriter.println("    }");
3341:                    // Returns the table alias given table name
3342:                    lWriter.println();
3343:                    lWriter
3344:                            .println("    static String getEntityTableInstanceIdColumnNameByTableName(String pTableName)");
3345:                    lWriter.println("    {");
3346:                    lWriter
3347:                            .println("        return (String)sEntityTableInstanceIdColumnNamesMap.get(pTableName);");
3348:                    lWriter.println("    }");
3349:
3350:                    // Returns all table names given table name
3351:                    lWriter.println();
3352:                    lWriter
3353:                            .println("    static String[] getEntityTableAllColumnNamesByTableName(String pTableName)");
3354:                    lWriter.println("    {");
3355:                    lWriter
3356:                            .println("        return (String[])sEntityTableAllColumnNamesMap.get(pTableName);");
3357:                    lWriter.println("    }");
3358:
3359:                    // Returns all table names given table name
3360:                    lWriter.println();
3361:                    lWriter
3362:                            .println("    static String[] getEntityTableLightColumnNamesByTableName(String pTableName)");
3363:                    lWriter.println("    {");
3364:                    lWriter
3365:                            .println("        return (String[])sEntityTableLightColumnNamesMap.get(pTableName);");
3366:                    lWriter.println("    }");
3367:
3368:                    lWriter.println();
3369:                    lWriter.println("    private static class TableDef");
3370:                    lWriter.println("    {");
3371:                    lWriter.println("        public String Name = null;");
3372:                    lWriter.println("        public String Alias = null;");
3373:                    lWriter
3374:                            .println("        public String InstanceIdColumnName = null;");
3375:                    lWriter.println("    }");
3376:                    lWriter.println("    private QueryType mQueryType = null;");
3377:                    lWriter
3378:                            .println("    private QueryContext mParentQuery = null;");
3379:                    lWriter
3380:                            .println("    private List mSavedTables = new ArrayList();");
3381:                    lWriter
3382:                            .println("    private TableDef mCurrentToTable = null;");
3383:                    lWriter
3384:                            .println("    private Map mNextAliasCountsMap = new HashMap();");
3385:                    lWriter
3386:                            .println("    private List mUsedTableNames = new ArrayList();");
3387:                    lWriter
3388:                            .println("    private List mUsedTableAliases = new ArrayList();");
3389:                    // This is the hidden default constructor
3390:                    lWriter.println();
3391:                    lWriter.println("    private QueryContext()");
3392:                    lWriter.println("    {");
3393:                    lWriter.println("    }");
3394:                    // This constructor creates a top level query of the known type, but with as yet undefined main table
3395:                    lWriter.println();
3396:                    lWriter
3397:                            .println("    public QueryContext(QueryContext.QueryType pQueryType)");
3398:                    lWriter.println("    {");
3399:                    lWriter.println("        mQueryType = pQueryType;");
3400:                    lWriter.println("    }");
3401:                    // This constructor creates a top level query of the known type with defined main table
3402:                    lWriter.println();
3403:                    lWriter
3404:                            .println("    public QueryContext(QueryContext.QueryType pQueryType, String pMainTableName)");
3405:                    lWriter.println("    {");
3406:                    lWriter.println("        mQueryType = pQueryType;");
3407:                    lWriter.println("        takeTableForUse(pMainTableName);");
3408:                    lWriter.println("    }");
3409:                    // This constructor creates a subquery of known type
3410:                    lWriter.println();
3411:                    lWriter
3412:                            .println("    private QueryContext(QueryContext.QueryType pQueryType, QueryContext pParentQuery)");
3413:                    lWriter.println("    {");
3414:                    lWriter.println("        mQueryType = pQueryType;");
3415:                    lWriter.println("        mParentQuery = pParentQuery;");
3416:                    lWriter.println("    }");
3417:
3418:                    // This method returns a query type
3419:                    lWriter.println();
3420:                    lWriter
3421:                            .println("    public QueryContext.QueryType getType()");
3422:                    lWriter.println("    {");
3423:                    lWriter.println("        return mQueryType;");
3424:                    lWriter.println("    }");
3425:
3426:                    // This method returns true if this is a subquery
3427:                    lWriter.println();
3428:                    lWriter.println("    public boolean isSubquery()");
3429:                    lWriter.println("    {");
3430:                    lWriter.println("        return mParentQuery != null;");
3431:                    lWriter.println("    }");
3432:                    lWriter.println();
3433:                    lWriter
3434:                            .println("    public String getCurrentToTableName()");
3435:                    lWriter.println("    {");
3436:                    lWriter.println("        return mCurrentToTable.Name;");
3437:                    lWriter.println("    }");
3438:                    lWriter.println();
3439:                    lWriter
3440:                            .println("    public String getCurrentToTableAlias()");
3441:                    lWriter.println("    {");
3442:                    lWriter.println("        return mCurrentToTable.Alias;");
3443:                    lWriter.println("    }");
3444:                    lWriter.println();
3445:                    lWriter
3446:                            .println("    public String getCurrentToTableInstanceIdColumnName()");
3447:                    lWriter.println("    {");
3448:                    lWriter
3449:                            .println("       return mCurrentToTable.InstanceIdColumnName;");
3450:                    lWriter.println("    }");
3451:                    // Following two operations allow to "put aside" the table and restore it latter
3452:                    lWriter.println();
3453:                    lWriter.println("    public void saveCurrentToTable()");
3454:                    lWriter.println("    {");
3455:                    lWriter
3456:                            .println("        mSavedTables.add(mCurrentToTable);");
3457:                    lWriter.println("    }");
3458:                    lWriter.println();
3459:                    lWriter.println("    public void restoreCurrentToTable()");
3460:                    lWriter.println("    {");
3461:                    lWriter
3462:                            .println("        mCurrentToTable = (TableDef)mSavedTables.remove(mSavedTables.size()-1);");
3463:                    lWriter.println("    }");
3464:
3465:                    // This method is used to set subquery in the from clause instead of the table name			
3466:                    lWriter.println();
3467:                    lWriter
3468:                            .println("    public void setTableNameOverride(String pTableAlias, String pTableNameOverride)");
3469:                    lWriter.println("    {");
3470:                    // Find the position of the alias and replace the table name at the same position
3471:                    lWriter
3472:                            .println("        for (int lPosition = 0; lPosition < mUsedTableAliases.size(); lPosition++)");
3473:                    lWriter.println("        {");
3474:                    lWriter
3475:                            .println("            if (mUsedTableAliases.get(lPosition).equals(pTableAlias))");
3476:                    lWriter.println("            {");
3477:                    lWriter
3478:                            .println("                mUsedTableNames.remove(lPosition);");
3479:                    lWriter
3480:                            .println("                mUsedTableNames.add(pTableNameOverride);");
3481:                    lWriter.println("                return;");
3482:                    lWriter.println("            }");
3483:                    lWriter.println("        }");
3484:                    lWriter
3485:                            .println("        throw new IllegalArgumentException(\"Alias '\" + pTableAlias + \"' is not registered.\");");
3486:                    lWriter.println("    }");
3487:
3488:                    // Return a number of tables collected for use in from clause			
3489:                    lWriter.println();
3490:                    lWriter
3491:                            .println("    public int getNumberOfTablesInFromClause()");
3492:                    lWriter.println("    {");
3493:                    lWriter.println("        return mUsedTableNames.size();");
3494:                    lWriter.println("    }");
3495:                    // Produce from clause			
3496:                    lWriter.println();
3497:                    lWriter.println("    public String getFromClause()");
3498:                    lWriter.println("    {");
3499:                    lWriter
3500:                            .println("        StringBuffer lSqlFromClause = new StringBuffer();");
3501:                    lWriter.println("        boolean lNeedComma = false;");
3502:                    lWriter
3503:                            .println("        String[] lTableNames = getUsedTableNames();");
3504:                    lWriter
3505:                            .println("        String[] lTableAliases = getUsedTableAliases();");
3506:                    lWriter
3507:                            .println("        for (int i = 0; i < lTableNames.length; i++)");
3508:                    lWriter.println("        {");
3509:                    lWriter.println("            if (lNeedComma)");
3510:                    lWriter
3511:                            .println("                lSqlFromClause.append(\",\");");
3512:                    lWriter.println("            else");
3513:                    lWriter.println("                lNeedComma = true;");
3514:                    lWriter
3515:                            .println("            lSqlFromClause.append(lTableNames[i]);");
3516:                    lWriter
3517:                            .println("            lSqlFromClause.append(\" \");");
3518:                    lWriter
3519:                            .println("            lSqlFromClause.append(lTableAliases[i]);");
3520:                    lWriter.println("        }");
3521:                    lWriter
3522:                            .println("        return lSqlFromClause.toString();");
3523:                    lWriter.println("    }");
3524:
3525:                    lWriter.println();
3526:                    lWriter.println("    public String[] getUsedTableNames()");
3527:                    lWriter.println("    {");
3528:                    lWriter
3529:                            .println("        return (String[])mUsedTableNames.toArray(new String[mUsedTableNames.size()]);");
3530:                    lWriter.println("    }");
3531:                    lWriter.println();
3532:                    lWriter
3533:                            .println("    public String[] getUsedTableAliases()");
3534:                    lWriter.println("    {");
3535:                    lWriter
3536:                            .println("        return (String[])mUsedTableAliases.toArray(new String[mUsedTableAliases.size()]);");
3537:                    lWriter.println("    }");
3538:                    // Generate copy of the clause for subquery 
3539:                    lWriter
3540:                            .println("    public QueryContext openSubquery(QueryContext.QueryType pQueryType, String pMainTableName)");
3541:                    lWriter.println("    {");
3542:                    lWriter
3543:                            .println("        QueryContext lReturn = new QueryContext(pQueryType, this);");
3544:                    lWriter
3545:                            .println("        lReturn.mNextAliasCountsMap.putAll(mNextAliasCountsMap);");
3546:                    lWriter
3547:                            .println("        lReturn.takeTableForUse(pMainTableName);");
3548:                    lWriter.println("        return lReturn;");
3549:                    lWriter.println("    }");
3550:                    // Ememebr all necessary info about subquery 
3551:                    lWriter
3552:                            .println("    public void closeSubquery(QueryContext pSubqueryClause)");
3553:                    lWriter.println("    {");
3554:                    lWriter
3555:                            .println("        mNextAliasCountsMap.putAll(pSubqueryClause.mNextAliasCountsMap);");
3556:                    lWriter.println("    }");
3557:                    // Generate method which registers the new table 
3558:                    // but does not make it the currenly used one. Returns alias to the taken table
3559:                    lWriter
3560:                            .println("    public String takeTable(String pTableName)");
3561:                    lWriter.println("    {");
3562:                    lWriter.println("        String lTableAlias = null;");
3563:                    lWriter
3564:                            .println("        Integer lNextCount = (Integer)mNextAliasCountsMap.get(pTableName);");
3565:                    // Alias generated here always has a number. This leaves first aliases free for use
3566:                    // by generated code.
3567:                    lWriter.println("        if (lNextCount == null)");
3568:                    lWriter.println("        {");
3569:                    lWriter
3570:                            .println("            lTableAlias = getTableAliasByTableName(pTableName);");
3571:                    lWriter
3572:                            .println("            mNextAliasCountsMap.put(pTableName, new Integer(1));");
3573:                    lWriter.println("        }");
3574:                    lWriter.println("        else");
3575:                    lWriter.println("        {");
3576:                    lWriter
3577:                            .println("            lTableAlias = getTableAliasByTableName(pTableName) + lNextCount.toString();");
3578:                    lWriter
3579:                            .println("            mNextAliasCountsMap.put(pTableName, new Integer(lNextCount.intValue() + 1));");
3580:                    lWriter.println("        }");
3581:                    lWriter.println("        mUsedTableNames.add(pTableName);");
3582:                    lWriter
3583:                            .println("        mUsedTableAliases.add(lTableAlias);");
3584:                    lWriter.println("        return lTableAlias;");
3585:                    lWriter.println("    }");
3586:                    // Generate method which registers the new table 
3587:                    // and makes it currenly used one. Returns alias to the taken table
3588:                    lWriter
3589:                            .println("    public String takeTableForUse(String pTableName)");
3590:                    lWriter.println("    {");
3591:                    // Set this table to be the current table
3592:                    lWriter
3593:                            .println("        mCurrentToTable = new TableDef();");
3594:                    lWriter
3595:                            .println("        mCurrentToTable.Name = pTableName;");
3596:                    lWriter
3597:                            .println("        mCurrentToTable.Alias = takeTable(pTableName);");
3598:                    lWriter
3599:                            .println("        mCurrentToTable.InstanceIdColumnName = getEntityTableInstanceIdColumnNameByTableName(pTableName);");
3600:                    lWriter.println("        return mCurrentToTable.Alias;");
3601:                    lWriter.println("    }");
3602:                    lWriter.println("}");
3603:                } catch (IOException e) {
3604:                    throw new BSException(e);
3605:                } finally {
3606:                    if (lFileWriter != null) {
3607:                        try {
3608:                            lFileWriter.flush();
3609:                        } catch (IOException e) {
3610:                            // Ignore
3611:                        }
3612:                        try {
3613:                            lFileWriter.close();
3614:                        } catch (IOException e) {
3615:                            // Ignore
3616:                        }
3617:                    }
3618:                    if (lWriter != null) {
3619:                        lWriter.flush();
3620:                        lWriter.close();
3621:                    }
3622:                }
3623:            }
3624:
3625:            private static void generateImplementationForTypesConvertor(
3626:                    String pImplementationDir, String pImplementationPackage,
3627:                    Domain pDomain) throws BSException {
3628:                PrintWriter lWriter = null;
3629:                FileWriter lFileWriter = null;
3630:                // Generate services interface
3631:                try {
3632:                    HashMap lDatatypesMap = new HashMap();
3633:                    // Collect all datatypes used in this domain
3634:                    Collection lEntities = pDomain.getEntities();
3635:                    for (Iterator lEntitiesIterator = lEntities.iterator(); lEntitiesIterator
3636:                            .hasNext();) {
3637:                        Entity lEntity = (Entity) lEntitiesIterator.next();
3638:                        Collection lAttributes = lEntity.getAttributes();
3639:                        Collection lSelectors = lEntity.getSelectors();
3640:                        // Collection Offset
3641:                        {
3642:                            DataType lDatatype = lEntity
3643:                                    .getCollectionOffsetDataType();
3644:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3645:                        }
3646:                        // Collection Size
3647:                        {
3648:                            DataType lDatatype = lEntity
3649:                                    .getCollectionSizeDataType();
3650:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3651:                        }
3652:                        // Subset Size
3653:                        {
3654:                            DataType lDatatype = lEntity
3655:                                    .getSubsetSizeDataType();
3656:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3657:                        }
3658:                        // Instance id
3659:                        {
3660:                            DataType lDatatype = lEntity
3661:                                    .getInstanceIdDataType();
3662:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3663:                        }
3664:                        // Version id only if necessary
3665:                        if (lEntity.isModifiable()) {
3666:                            DataType lDatatype = lEntity.getVersionIdDataType();
3667:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3668:                        }
3669:                        // State only if necessary
3670:                        if (lEntity.getStateMachine() != null) {
3671:                            DataType lDatatype = lEntity.getStateDataType();
3672:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3673:                        }
3674:                        // Attribute types
3675:                        for (Iterator lAttributesIterator = lAttributes
3676:                                .iterator(); lAttributesIterator.hasNext();) {
3677:                            Attribute lAttribute = (Attribute) lAttributesIterator
3678:                                    .next();
3679:                            DataType lDatatype = lAttribute.getDataType();
3680:                            lDatatypesMap.put(lDatatype.getRef(), lDatatype);
3681:                        }
3682:
3683:                        // Selector inputs
3684:                        for (Iterator lSelectorsIterator = lSelectors
3685:                                .iterator(); lSelectorsIterator.hasNext();) {
3686:                            Selector lSelector = (Selector) lSelectorsIterator
3687:                                    .next();
3688:                            Collection lInputFields = lSelector
3689:                                    .getInputFields();
3690:                            for (Iterator lInputFieldsIterator = lInputFields
3691:                                    .iterator(); lInputFieldsIterator.hasNext();) {
3692:                                SelectorInputField lInputField = (SelectorInputField) lInputFieldsIterator
3693:                                        .next();
3694:                                DataType lDatatype = lInputField.getDataType();
3695:                                lDatatypesMap
3696:                                        .put(lDatatype.getRef(), lDatatype);
3697:                            }
3698:                        }
3699:                    }
3700:                    String lTypesConvertorFileName = pImplementationDir
3701:                            + File.separator + "TypesConvertor.java";
3702:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
3703:                            lTypesConvertorFileName));
3704:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
3705:                    // Package statement
3706:                    lWriter.println("package " + pImplementationPackage + ";");
3707:                    lWriter.println();
3708:                    lWriter
3709:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInstanceCreationFailureException;");
3710:                    lWriter
3711:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForEmptyInstanceException;");
3712:                    lWriter
3713:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForConcealedInstanceException;");
3714:                    lWriter.println();
3715:                    lWriter
3716:                            .println("/* This class contains conversion utility methods to and from datatypes */");
3717:                    lWriter.println("public class TypesConvertor");
3718:                    lWriter.println("{");
3719:                    // Iterate through datatypes generating static member variables and convertors
3720:                    {
3721:                        Iterator lIter = lDatatypesMap.values().iterator();
3722:                        while (lIter.hasNext()) {
3723:                            DataType lDatatype = (DataType) lIter.next();
3724:                            String lUniqueName = getUniqueDatatypeName(lDatatype);
3725:                            STDatatypeStylesheet lStylesheet = CodeGenerationStylesheetAccessor
3726:                                    .getDatatypeStylesheet(lDatatype);
3727:                            STDatatypeTranslationStylesheet lTranslationStylesheet = CodeGenerationStylesheetAccessor
3728:                                    .getDatatypeTranslationStylesheet(lDatatype);
3729:                            DataTypeTranslationMetadata.SqlType lSqlType = DataTypeTranslationMetadata.SqlType
3730:                                    .createFromName(lTranslationStylesheet
3731:                                            .getSqlTypeName());
3732:                            lWriter
3733:                                    .println("    private static "
3734:                                            + lTranslationStylesheet
3735:                                                    .getSqlTranslatorClassName()
3736:                                            + " s"
3737:                                            + lUniqueName
3738:                                            + "Translator = "
3739:                                            + "("
3740:                                            + lTranslationStylesheet
3741:                                                    .getSqlTranslatorClassName()
3742:                                            + ")"
3743:                                            + lStylesheet.getClassFullName()
3744:                                            + ".getTranslationMetadata().getSqlTranslator();");
3745:                            lWriter
3746:                                    .println("    public static "
3747:                                            + lSqlType.getJavaType().getName()
3748:                                            + (lSqlType.isArray() ? "[]" : "")
3749:                                            + " getSqlValueFrom"
3750:                                            + lUniqueName
3751:                                            + "("
3752:                                            + lStylesheet.getClassFullName()
3753:                                            + " pDatatypeInstance ) throws DataTypeInvalidOperationForEmptyInstanceException, DataTypeInvalidOperationForConcealedInstanceException");
3754:                            lWriter.println("    {");
3755:                            lWriter
3756:                                    .println("        return s"
3757:                                            + lUniqueName
3758:                                            + "Translator.getSqlValue(pDatatypeInstance);");
3759:                            lWriter.println("    }");
3760:                            lWriter
3761:                                    .println("    public static "
3762:                                            + lStylesheet.getClassFullName()
3763:                                            + " create"
3764:                                            + lUniqueName
3765:                                            + "FromSqlValue("
3766:                                            + lSqlType.getJavaType().getName()
3767:                                            + (lSqlType.isArray() ? "[]" : "")
3768:                                            + " pSqlValue) throws DataTypeInstanceCreationFailureException");
3769:                            lWriter.println("    {");
3770:                            lWriter
3771:                                    .println("        return ("
3772:                                            + lStylesheet.getClassFullName()
3773:                                            + ")s"
3774:                                            + lUniqueName
3775:                                            + "Translator.createFromSqlValue(pSqlValue);");
3776:                            lWriter.println("    }");
3777:                        }
3778:                    }
3779:                    lWriter.println("}");
3780:                } catch (IOException e) {
3781:                    throw new BSException(e);
3782:                } catch (BOException e) {
3783:                    throw new BSDomainObjectInvocationException(e);
3784:                } finally {
3785:                    if (lFileWriter != null) {
3786:                        try {
3787:                            lFileWriter.flush();
3788:                        } catch (IOException e) {
3789:                            // Ignore
3790:                        }
3791:                        try {
3792:                            lFileWriter.close();
3793:                        } catch (IOException e) {
3794:                            // Ignore
3795:                        }
3796:                    }
3797:                    if (lWriter != null) {
3798:                        lWriter.flush();
3799:                        lWriter.close();
3800:                    }
3801:                }
3802:            }
3803:
3804:            protected void generateImplementationForSelectors(
3805:                    String pImplementationDir, String pImplementationPackage,
3806:                    Domain pDomain,
3807:                    DomainRelationalStorageDefinition pDomainStorage)
3808:                    throws BSException {
3809:                PrintWriter lWriter = null;
3810:                FileWriter lFileWriter = null;
3811:                // Generate services interface
3812:                try {
3813:                    Collection lEntities = pDomain.getEntities();
3814:                    Collection lAssociations = pDomain.getAssociations();
3815:                    Enterprise lEnterprise = pDomain.getSystem()
3816:                            .getEnterprise();
3817:                    // Setup necessary typetemplates and data types
3818:                    TypeTemplate lEnumerableValueTypeTemplate = lEnterprise
3819:                            .getDesignLibrary().getDataDictionary("core")
3820:                            .getTypeTemplate("EnumerableValueField");
3821:
3822:                    DataType lCollectionOffsetDatatype = lEnterprise
3823:                            .getDesignLibrary().getDataDictionary("core")
3824:                            .getDataType("CollectionOffset");
3825:                    STDatatypeStylesheet lCollectionOffsetDatatypeStylesheet = CodeGenerationStylesheetAccessor
3826:                            .getDatatypeStylesheet(lCollectionOffsetDatatype);
3827:                    STDatatypeTranslationStylesheet lCollectionOffsetDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
3828:                            .getDatatypeTranslationStylesheet(lCollectionOffsetDatatype);
3829:                    DataTypeTranslationMetadata.SqlType lCollectionOffsetDatatypeSqlType = DataTypeTranslationMetadata.SqlType
3830:                            .createFromName(lCollectionOffsetDatatypeTranslationStylesheet
3831:                                    .getSqlTypeName());
3832:
3833:                    DataType lSubsetSizeDatatype = lEnterprise
3834:                            .getDesignLibrary().getDataDictionary("core")
3835:                            .getDataType("SubsetSize");
3836:                    STDatatypeStylesheet lSubsetSizeDatatypeStylesheet = CodeGenerationStylesheetAccessor
3837:                            .getDatatypeStylesheet(lSubsetSizeDatatype);
3838:                    STDatatypeTranslationStylesheet lSubsetSizeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
3839:                            .getDatatypeTranslationStylesheet(lSubsetSizeDatatype);
3840:                    DataTypeTranslationMetadata.SqlType lSubsetSizeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
3841:                            .createFromName(lSubsetSizeDatatypeTranslationStylesheet
3842:                                    .getSqlTypeName());
3843:
3844:                    String lUtilitiesFileName = pImplementationDir
3845:                            + File.separator + "Selectors.java";
3846:                    lWriter = new PrintWriter(lFileWriter = new FileWriter(
3847:                            lUtilitiesFileName));
3848:                    CopyrightUtils.writeCopyrightToGeneratedJavaSource(lWriter);
3849:                    // Package statement
3850:                    lWriter.println("package " + pImplementationPackage + ";");
3851:                    lWriter.println();
3852:                    lWriter.println("import java.util.HashMap;");
3853:                    lWriter.println("import java.sql.PreparedStatement;");
3854:                    lWriter.println("import org.apache.commons.logging.Log;");
3855:                    lWriter
3856:                            .println("import org.apache.commons.logging.LogFactory;");
3857:                    lWriter
3858:                            .println("import com.metaboss.enterprise.datatypes.DataType;");
3859:                    lWriter
3860:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForEmptyInstanceException;");
3861:                    lWriter
3862:                            .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForConcealedInstanceException;");
3863:                    lWriter
3864:                            .println("import com.metaboss.enterprise.ps.PSException;");
3865:                    lWriter
3866:                            .println("import com.metaboss.enterprise.ps.STCollectionDetails;");
3867:                    lWriter
3868:                            .println("import com.metaboss.enterprise.ps.STFilteringDetails;");
3869:                    lWriter
3870:                            .println("import com.metaboss.enterprise.ps.STOrderingDetails;");
3871:                    lWriter
3872:                            .println("import com.metaboss.enterprise.ps.PSDatatypeOperationException;");
3873:                    lWriter
3874:                            .println("import com.metaboss.enterprise.ps.PSUnexpectedProgramConditionException;");
3875:                    lWriter
3876:                            .println("import com.metaboss.enterprise.ps.PSSelectorConstraintViolationException;");
3877:                    lWriter
3878:                            .println("import com.metaboss.enterprise.ps.PSDataSourceOperationInvocationException;");
3879:
3880:                    lWriter.println();
3881:                    lWriter.println("public class Selectors");
3882:                    lWriter.println("{");
3883:                    // Logger instance
3884:                    lWriter
3885:                            .println("    private static final Log sLogger = LogFactory.getLog(Selectors.class);");
3886:
3887:                    lWriter
3888:                            .println("    /** This structure contains parts of sql statement */");
3889:                    lWriter
3890:                            .println("    public static class SqlStatementParts");
3891:                    lWriter.println("    {");
3892:                    lWriter
3893:                            .println("        private int mNumberOfTablesInFromClause = 0;");
3894:                    lWriter
3895:                            .println("        private java.util.Set mWhatClauseElements = new java.util.HashSet();");
3896:                    lWriter
3897:                            .println("        private StringBuffer mWhatClause = new StringBuffer();");
3898:                    lWriter
3899:                            .println("        public String mFromClause = null;");
3900:                    lWriter
3901:                            .println("        public String mWhereClause = null;");
3902:                    lWriter
3903:                            .println("        public String mOrderByClause = null;");
3904:                    lWriter
3905:                            .println("        public String mLimitClause = null;");
3906:                    // What clause related methods - there is a need to preserve order, but there is no need to add same column twice
3907:                    lWriter.println();
3908:                    lWriter
3909:                            .println("        public void appendWhatClauseElement(String pWhatClauseElement)");
3910:                    lWriter.println("        {");
3911:                    lWriter
3912:                            .println("            if (pWhatClauseElement != null && pWhatClauseElement.trim().length() > 0)");
3913:                    lWriter.println("            {");
3914:                    lWriter
3915:                            .println("                String[] lClauses = pWhatClauseElement.split(\",\");");
3916:                    lWriter
3917:                            .println("                for (int i = 0; i < lClauses.length; i++)");
3918:                    lWriter.println("                {");
3919:                    lWriter
3920:                            .println("                    String lClause = lClauses[i].trim();");
3921:                    lWriter
3922:                            .println("                    if (mWhatClauseElements.add(lClause))");
3923:                    lWriter.println("                    {");
3924:                    lWriter
3925:                            .println("                        if (mWhatClauseElements.size() > 1)");
3926:                    lWriter
3927:                            .println("                            mWhatClause.append(\",\");");
3928:                    lWriter
3929:                            .println("                        mWhatClause.append(lClause);");
3930:                    lWriter.println("                    }");
3931:                    lWriter.println("                }");
3932:                    lWriter.println("            }");
3933:                    lWriter.println("        }");
3934:                    lWriter.println("        public boolean hasWhatClause()");
3935:                    lWriter.println("        {");
3936:                    lWriter
3937:                            .println("            return mWhatClauseElements.isEmpty() == false;");
3938:                    lWriter.println("        }");
3939:                    lWriter.println("        public String getWhatClause()");
3940:                    lWriter.println("        {");
3941:                    lWriter
3942:                            .println("            return mWhatClause.toString();");
3943:                    lWriter.println("        }");
3944:                    // From clause related methods for now more than one table in the from statement will trigger the DISTINCT keyword
3945:                    lWriter.println();
3946:                    lWriter
3947:                            .println("        public void setNumberOfTablesInFromClause(int pNumberOfTablesInFromClause)");
3948:                    lWriter.println("        {");
3949:                    lWriter
3950:                            .println("            mNumberOfTablesInFromClause = pNumberOfTablesInFromClause;");
3951:                    lWriter.println("        }");
3952:                    lWriter.println();
3953:                    lWriter.println("        public boolean needsDistinct()");
3954:                    lWriter.println("        {");
3955:                    lWriter
3956:                            .println("            return mNumberOfTablesInFromClause > 1;");
3957:                    lWriter.println("        }");
3958:                    lWriter.println("    }");
3959:                    lWriter
3960:                            .println("    /** This structure contains parts of sql statement dealing with ordering */");
3961:                    lWriter
3962:                            .println("    public static class OrderByStatementParts");
3963:                    lWriter.println("    {");
3964:                    lWriter
3965:                            .println("        public String mWhatClause = null;");
3966:                    lWriter
3967:                            .println("        public String mFromClause = null;");
3968:                    lWriter
3969:                            .println("        public String mWhereClause = null;");
3970:                    lWriter
3971:                            .println("        public String mOrderByClause = null;");
3972:                    lWriter.println("    }");
3973:
3974:                    lWriter
3975:                            .println("    /** The collection details interpreter is an abstract mechanism, which");
3976:                    lWriter
3977:                            .println("     * performs run-time interpretation of the STCollectionDetails structure.");
3978:                    lWriter
3979:                            .println("     * Although interface provides for SelectorDetails structure to be interpreted");
3980:                    lWriter
3981:                            .println("     * 'on a fly', we are mindfull that it reduces performance. Therefore");
3982:                    lWriter
3983:                            .println("     * implementations are encouraged to preprocess selector metadata as much as possible");
3984:                    lWriter
3985:                            .println("     * and do as little as possible work at run time */");
3986:                    lWriter
3987:                            .println("    private interface CollectionDetailsInterpreter");
3988:                    lWriter.println("    {");
3989:                    lWriter
3990:                            .println("        /** Returns the text of sql where clause and updates the QueryContext to contain used tables.");
3991:                    lWriter
3992:                            .println("          * @param pCollectionDetails the details of the collection");
3993:                    lWriter
3994:                            .println("          * @param pQueryContext the details of the tables and the aliases used so far */");
3995:                    lWriter
3996:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException;");
3997:
3998:                    lWriter
3999:                            .println("        /** Sets all arguments into the supplied java.sql.prepared statement");
4000:                    lWriter
4001:                            .println("          * @param pCollectionDetails the details of the collection");
4002:                    lWriter
4003:                            .println("          * @param pStartIndex index to start populating from ");
4004:                    lWriter
4005:                            .println("          * (i.e use on first PreparedStatement.setXXXX() and keep incrementing it for the subsequent ones)");
4006:                    lWriter
4007:                            .println("          * @return the number of arguments set into the prepared statement */");
4008:                    lWriter
4009:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException;");
4010:                    lWriter.println("    }");
4011:
4012:                    lWriter
4013:                            .println("    /** The filtering details interpreter is an abstract mechanism, which");
4014:                    lWriter
4015:                            .println("     * performs run-time interpretation of the STFilteringDetails structure.");
4016:                    lWriter
4017:                            .println("     * Although interface provides for SelectorDetails structure to be interpreted");
4018:                    lWriter
4019:                            .println("     * 'on a fly', we are mindfull that it reduces performance. Therefore");
4020:                    lWriter
4021:                            .println("     * implementations are encouraged to preprocess selector metadata as much as possible");
4022:                    lWriter
4023:                            .println("     * and do as little as possible work at run time */");
4024:                    lWriter
4025:                            .println("    private interface FilteringDetailsInterpreter");
4026:                    lWriter.println("    {");
4027:                    lWriter
4028:                            .println("        /** Returns the text of sql where clause and updates the QueryContext to contain used tables.");
4029:                    lWriter
4030:                            .println("          * @param pFilteringDetails the details of the filtering");
4031:                    lWriter
4032:                            .println("          * @param pQueryContext the details of the tables and the aliases used so far */");
4033:                    lWriter
4034:                            .println("        public String getSqlWhereClause(STFilteringDetails pFilteringDetails, QueryContext pQueryContext) throws PSException;");
4035:
4036:                    lWriter
4037:                            .println("        /** Sets all arguments into the supplied java.sql.prepared statement");
4038:                    lWriter
4039:                            .println("          * @param pFilteringDetails the details of the filtering");
4040:                    lWriter
4041:                            .println("          * @param pStartIndex index to start populating from ");
4042:                    lWriter
4043:                            .println("          * (i.e use on first PreparedStatement.setXXXX() and keep incrementing it for the subsequent ones)");
4044:                    lWriter
4045:                            .println("          * @return the number of arguments set into the prepared statement */");
4046:                    lWriter
4047:                            .println("        public int populatePreparedStatement(STFilteringDetails pFilteringDetails, PreparedStatement pStatement, int pStartIndex) throws PSException;");
4048:                    lWriter.println("    }");
4049:
4050:                    lWriter
4051:                            .println("    /** The ordering details interpreter is an abstract mechanism, which");
4052:                    lWriter
4053:                            .println("     * performs run-time interpretation of the STOrderingDetails structure.");
4054:                    lWriter
4055:                            .println("     * Although interface provides for SelectorDetails structure to be interpreted");
4056:                    lWriter
4057:                            .println("     * 'on a fly', we are mindfull that it reduces performance. Therefore");
4058:                    lWriter
4059:                            .println("     * implementations are encouraged to preprocess selector metadata as much as possible");
4060:                    lWriter
4061:                            .println("     * and do as little as possible work at run time */");
4062:                    lWriter
4063:                            .println("    private interface OrderingDetailsInterpreter");
4064:                    lWriter.println("    {");
4065:                    lWriter.println("        public class SqlClauses");
4066:                    lWriter.println("        {");
4067:                    lWriter
4068:                            .println("            public String WhatClause = null;");
4069:                    lWriter
4070:                            .println("            public String WhereClause = null;");
4071:                    lWriter
4072:                            .println("            public String OrderByClause = null;");
4073:                    lWriter.println("        }");
4074:                    lWriter
4075:                            .println("        /** Returns the text of sql clauses and updates the QueryContext to contain used tables.");
4076:                    lWriter
4077:                            .println("          * @param pOrderingDetails the details of the ordering");
4078:                    lWriter
4079:                            .println("          * @param pQueryContext the details of the tables and the aliases used so far */");
4080:                    lWriter
4081:                            .println("        public SqlClauses getSqlClauses(STOrderingDetails pOrderingDetails, QueryContext pQueryContext) throws PSException;");
4082:                    lWriter.println("    }");
4083:
4084:                    lWriter
4085:                            .println("    // All entity selectors defined in this domain. The key is selector ref");
4086:                    lWriter
4087:                            .println("    private static HashMap sEntitySelectorMetadataMap = new HashMap();");
4088:                    lWriter
4089:                            .println("    // All entity ordering interpreters defined in this domain. The key is attribute ref");
4090:                    lWriter
4091:                            .println("    private static HashMap sEntityOrderingMetadataMap = new HashMap();");
4092:                    lWriter
4093:                            .println("    // All association selectors defined in this domain. The key is association model ref");
4094:                    lWriter
4095:                            .println("    private static HashMap sAssociationSelectorMetadataMap = new HashMap();");
4096:                    lWriter.println();
4097:                    lWriter.println("    static");
4098:                    lWriter.println("    {");
4099:                    // Iterate through entities and populate selector metadata
4100:                    for (Iterator lEntitiesIterator = lEntities.iterator(); lEntitiesIterator
4101:                            .hasNext();) {
4102:                        Entity lEntity = (Entity) lEntitiesIterator.next();
4103:                        RelationalEntityTable lEntityTable = pDomainStorage
4104:                                .getEntityTable(lEntity);
4105:                        String lEntityTableName = lEntityTable
4106:                                .getNameOverride();
4107:                        if (lEntityTableName == null
4108:                                || lEntityTableName.length() == 0)
4109:                            lEntityTableName = lEntityTable.getNameSuggestion();
4110:                        Collection lSelectors = lEntity.getSelectors();
4111:                        for (Iterator lSelectorsIterator = lSelectors
4112:                                .iterator(); lSelectorsIterator.hasNext();) {
4113:                            Selector lSelector = (Selector) lSelectorsIterator
4114:                                    .next();
4115:                            Collection lInputFields = lSelector
4116:                                    .getInputFields();
4117:                            // Prepare input properties and parse velocity template
4118:                            // Here is a problem : we want to support array input fields and velocity's #foreach
4119:                            // construct. However we do not want to spend time parsing velocity templates run-time
4120:                            // (it is only run-time when the size of array is known. This drives decision to have our own little
4121:                            // purpose built parser of velocity instructions. Following is the list of what it will do :
4122:                            // (1) Each expression ${EntAttributes.<attribute name>} will be converted to qualified column name
4123:                            // and each expression ${Attributes.<attribute name>} will be converted to unqualified column name
4124:                            // all attributes plus instance id, version id and state will be avilable. Singular cardinality
4125:                            // association ids (foreighn keys) will not be available. Also note that only this entity's attributes are allowed
4126:                            // (2) Each ${Inputs.<input name} will be converted to ? and the statement.setXXX method will be added to the
4127:                            // statement setter
4128:                            // (3) Each #foreach ( $<any variablename> in ${Inputs.<input name} ) ........ #end will
4129:                            // be parsed separately
4130:                            String lSQLSelector = lSelector
4131:                                    .getTextOfSqlSelect();
4132:                            if (lSQLSelector == null
4133:                                    || lSQLSelector.length() == 0) {
4134:                                lSQLSelector = "";
4135:                                sLogger
4136:                                        .warn("Selector does not have SQL defined. The database query code for it will not be generated. SelectorRef: "
4137:                                                + lSelector.getRef());
4138:                            }
4139:                            // Scan the statement and get input fields array in exact same order as
4140:                            // they will be used (allow for duplicate occurrences
4141:                            SelectorInputField[] lInputFieldsInOrderOfUse = getInputFieldsInOrderOfUse(
4142:                                    lSQLSelector, lEntity, lSelector);
4143:
4144:                            // Process the statement text. Perform colum name and statement parameters substitution
4145:                            // First replace attribute names with column names i.e '${Attributes.Price}' becomes 'T.Price'
4146:                            String lSqlWhereClause = convertSQLSelectorTextToStringConstant(
4147:                                    lSQLSelector, pDomain, lEntity, lSelector,
4148:                                    pDomainStorage);
4149:                            // Write out the creation and registration of this selector
4150:                            lWriter
4151:                                    .println("        // Generate and store metadata for the "
4152:                                            + lSelector.getRef()
4153:                                            + " entity selector");
4154:                            lWriter
4155:                                    .println("        sEntitySelectorMetadataMap.put(\""
4156:                                            + lSelector.getRef()
4157:                                            + "\", new FilteringDetailsInterpreter()");
4158:                            lWriter.println("        {");
4159:                            lWriter
4160:                                    .println("            public String getSqlWhereClause(STFilteringDetails pFilteringDetails, QueryContext pQueryContext) throws PSException");
4161:                            lWriter.println("            {");
4162:                            // Check if selector was called in context
4163:                            lWriter
4164:                                    .println("                if (pQueryContext.getCurrentToTableName() == null || pQueryContext.getCurrentToTableName().equals(\""
4165:                                            + lEntityTableName
4166:                                            + "\") == false)");
4167:                            lWriter
4168:                                    .println("                    throw new PSUnexpectedProgramConditionException(\"Selector is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
4169:                            // Because getSqlWhereClause is called first and may potentially refer to the input parameters (eg. array parameters)
4170:                            // we are validating all input parameters here and not in the populatePreparedStatement()
4171:                            if (lInputFieldsInOrderOfUse.length > 0) {
4172:                                lWriter
4173:                                        .println("                // Set up and validate input fields");
4174:                                int k = 0;
4175:                                for (Iterator lInputFieldsIterator = lInputFields
4176:                                        .iterator(); lInputFieldsIterator
4177:                                        .hasNext(); k++) {
4178:                                    SelectorInputField lInputField = (SelectorInputField) lInputFieldsIterator
4179:                                            .next();
4180:                                    STSelectorInputFieldStylesheet lSelectorInputFieldStylesheet = CodeGenerationStylesheetAccessor
4181:                                            .getSelectorInputFieldStylesheet(lInputField);
4182:                                    STDatatypeStylesheet lInputFieldDatatypeStylesheet = CodeGenerationStylesheetAccessor
4183:                                            .getDatatypeStylesheet(lInputField
4184:                                                    .getDataType());
4185:                                    if (lInputField.isArray()) {
4186:                                        lWriter
4187:                                                .println("                // Presence of each element of the "
4188:                                                        + lInputField.getName()
4189:                                                        + " array input parameter is mandatory");
4190:                                        lWriter
4191:                                                .println("                DataType[] l"
4192:                                                        + lSelectorInputFieldStylesheet
4193:                                                                .getNormalisedName()
4194:                                                        + " = pFilteringDetails.SelectorArguments["
4195:                                                        + k + "];");
4196:                                        lWriter
4197:                                                .println("                if ( l"
4198:                                                        + lSelectorInputFieldStylesheet
4199:                                                                .getNormalisedName()
4200:                                                        + " == null || l"
4201:                                                        + lSelectorInputFieldStylesheet
4202:                                                                .getNormalisedName()
4203:                                                        + ".length == 0)");
4204:                                        lWriter
4205:                                                .println("                    throw new PSSelectorConstraintViolationException(\""
4206:                                                        + lInputField.getName()
4207:                                                        + " field in the "
4208:                                                        + lSelector.getRef()
4209:                                                        + " selector is not expected to be undefined for query operation.\");");
4210:                                        lWriter
4211:                                                .println("                for (int i = 0; i < l"
4212:                                                        + lSelectorInputFieldStylesheet
4213:                                                                .getNormalisedName()
4214:                                                        + ".length; i++)");
4215:                                        lWriter.println("                {");
4216:
4217:                                        lWriter.println("                    "
4218:                                                + lInputFieldDatatypeStylesheet
4219:                                                        .getClassFullName()
4220:                                                + " l"
4221:                                                + lSelectorInputFieldStylesheet
4222:                                                        .getNormalisedName()
4223:                                                + "Element = ("
4224:                                                + lInputFieldDatatypeStylesheet
4225:                                                        .getClassFullName()
4226:                                                + ")l"
4227:                                                + lSelectorInputFieldStylesheet
4228:                                                        .getNormalisedName()
4229:                                                + "[i];");
4230:                                        lWriter
4231:                                                .println("                    if ( l"
4232:                                                        + lSelectorInputFieldStylesheet
4233:                                                                .getNormalisedName()
4234:                                                        + "Element == null)");
4235:                                        lWriter
4236:                                                .println("                        throw new PSSelectorConstraintViolationException(\""
4237:                                                        + lInputField.getName()
4238:                                                        + "[\" + i + \"] field in the "
4239:                                                        + lSelector.getRef()
4240:                                                        + " selector is not expected to be null for query operation.\");");
4241:                                        lWriter
4242:                                                .println("                    if (l"
4243:                                                        + lSelectorInputFieldStylesheet
4244:                                                                .getNormalisedName()
4245:                                                        + "Element.isEmpty())");
4246:                                        lWriter
4247:                                                .println("                        throw new PSSelectorConstraintViolationException(\""
4248:                                                        + lInputField.getName()
4249:                                                        + "[\" + i + \"] field in the "
4250:                                                        + lSelector.getRef()
4251:                                                        + " selector is not expected to be empty for query operation.\");");
4252:                                        lWriter
4253:                                                .println("                    if (l"
4254:                                                        + lSelectorInputFieldStylesheet
4255:                                                                .getNormalisedName()
4256:                                                        + "Element.isConcealed())");
4257:                                        lWriter
4258:                                                .println("                        throw new PSSelectorConstraintViolationException(\""
4259:                                                        + lInputField.getName()
4260:                                                        + "[\" + i + \"] field in the "
4261:                                                        + lSelector.getRef()
4262:                                                        + " selector is not expected to be undefined for query operation.\");");
4263:                                        lWriter.println("                }");
4264:                                    } else {
4265:                                        lWriter
4266:                                                .println("                // Presence of the "
4267:                                                        + lInputField.getName()
4268:                                                        + " input parameter is mandatory");
4269:                                        lWriter
4270:                                                .println("                DataType[] l"
4271:                                                        + lSelectorInputFieldStylesheet
4272:                                                                .getNormalisedName()
4273:                                                        + "Array = pFilteringDetails.SelectorArguments["
4274:                                                        + k + "];");
4275:                                        lWriter
4276:                                                .println("                if ( l"
4277:                                                        + lSelectorInputFieldStylesheet
4278:                                                                .getNormalisedName()
4279:                                                        + "Array == null || l"
4280:                                                        + lSelectorInputFieldStylesheet
4281:                                                                .getNormalisedName()
4282:                                                        + "Array.length != 1)");
4283:                                        lWriter
4284:                                                .println("                    throw new PSSelectorConstraintViolationException(\""
4285:                                                        + lInputField.getName()
4286:                                                        + " field in the "
4287:                                                        + lSelector.getRef()
4288:                                                        + " selector is not expected to be undefined for query operation.\");");
4289:                                        lWriter.println("                "
4290:                                                + lInputFieldDatatypeStylesheet
4291:                                                        .getClassFullName()
4292:                                                + " l"
4293:                                                + lSelectorInputFieldStylesheet
4294:                                                        .getNormalisedName()
4295:                                                + " = ("
4296:                                                + lInputFieldDatatypeStylesheet
4297:                                                        .getClassFullName()
4298:                                                + ")l"
4299:                                                + lSelectorInputFieldStylesheet
4300:                                                        .getNormalisedName()
4301:                                                + "Array[0];");
4302:                                        lWriter
4303:                                                .println("                if ( l"
4304:                                                        + lSelectorInputFieldStylesheet
4305:                                                                .getNormalisedName()
4306:                                                        + " == null)");
4307:                                        lWriter
4308:                                                .println("                    throw new PSSelectorConstraintViolationException(\""
4309:                                                        + lInputField.getName()
4310:                                                        + " field in the "
4311:                                                        + lSelector.getRef()
4312:                                                        + " selector is not expected to be null for query operation.\");");
4313:                                        lWriter.println("                if (l"
4314:                                                + lSelectorInputFieldStylesheet
4315:                                                        .getNormalisedName()
4316:                                                + ".isEmpty())");
4317:                                        lWriter
4318:                                                .println("                    throw new PSSelectorConstraintViolationException(\""
4319:                                                        + lInputField.getName()
4320:                                                        + " field in the "
4321:                                                        + lSelector.getRef()
4322:                                                        + " selector is not expected to be empty for query operation.\");");
4323:                                        lWriter.println("                if (l"
4324:                                                + lSelectorInputFieldStylesheet
4325:                                                        .getNormalisedName()
4326:                                                + ".isConcealed())");
4327:                                        lWriter
4328:                                                .println("                    throw new PSSelectorConstraintViolationException(\""
4329:                                                        + lInputField.getName()
4330:                                                        + " field in the "
4331:                                                        + lSelector.getRef()
4332:                                                        + " selector is not expected to be undefined for query operation.\");");
4333:                                    }
4334:                                }
4335:                            }
4336:                            // This selector does not update from clause with any extra tables
4337:                            lWriter.println("                return "
4338:                                    + lSqlWhereClause + ";");
4339:                            lWriter.println("            }");
4340:
4341:                            lWriter
4342:                                    .println("            public int populatePreparedStatement(STFilteringDetails pFilteringDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
4343:                            lWriter.println("            {");
4344:                            if (lInputFieldsInOrderOfUse.length > 0) {
4345:                                lWriter
4346:                                        .println("                int lInitialStartIndex = pStartIndex;");
4347:                                lWriter
4348:                                        .println("                // Get values from all input fields");
4349:                                int k = 0;
4350:                                for (Iterator lInputFieldsIterator = lInputFields
4351:                                        .iterator(); lInputFieldsIterator
4352:                                        .hasNext(); k++) {
4353:                                    SelectorInputField lInputField = (SelectorInputField) lInputFieldsIterator
4354:                                            .next();
4355:                                    STSelectorInputFieldStylesheet lSelectorInputFieldStylesheet = CodeGenerationStylesheetAccessor
4356:                                            .getSelectorInputFieldStylesheet(lInputField);
4357:                                    STDatatypeStylesheet lInputFieldDatatypeStylesheet = CodeGenerationStylesheetAccessor
4358:                                            .getDatatypeStylesheet(lInputField
4359:                                                    .getDataType());
4360:                                    if (lInputField.isArray()) {
4361:                                        lWriter
4362:                                                .println("                DataType[] l"
4363:                                                        + lSelectorInputFieldStylesheet
4364:                                                                .getNormalisedName()
4365:                                                        + " = pFilteringDetails.SelectorArguments["
4366:                                                        + k + "];");
4367:                                    } else {
4368:                                        lWriter
4369:                                                .println("                "
4370:                                                        + lInputFieldDatatypeStylesheet
4371:                                                                .getClassFullName()
4372:                                                        + " l"
4373:                                                        + lSelectorInputFieldStylesheet
4374:                                                                .getNormalisedName()
4375:                                                        + " = ("
4376:                                                        + lInputFieldDatatypeStylesheet
4377:                                                                .getClassFullName()
4378:                                                        + ")pFilteringDetails.SelectorArguments["
4379:                                                        + k + "][0];");
4380:                                    }
4381:                                }
4382:                                lWriter
4383:                                        .println("                // Populate prepared statement");
4384:                                lWriter.println("                try");
4385:                                lWriter.println("                {");
4386:                                for (int m = 0; m < lInputFieldsInOrderOfUse.length; m++) {
4387:                                    SelectorInputField lInputField = lInputFieldsInOrderOfUse[m];
4388:                                    STSelectorInputFieldStylesheet lSelectorInputFieldStylesheet = CodeGenerationStylesheetAccessor
4389:                                            .getSelectorInputFieldStylesheet(lInputField);
4390:                                    STDatatypeStylesheet lInputFieldDatatypeStylesheet = CodeGenerationStylesheetAccessor
4391:                                            .getDatatypeStylesheet(lInputField
4392:                                                    .getDataType());
4393:                                    if (lInputField.isArray()) {
4394:                                        lWriter
4395:                                                .println("                    for (int i = 0; i < l"
4396:                                                        + lSelectorInputFieldStylesheet
4397:                                                                .getNormalisedName()
4398:                                                        + ".length; i++)");
4399:                                        lWriter
4400:                                                .println("                    {");
4401:                                        lWriter
4402:                                                .println("                        "
4403:                                                        + lInputFieldDatatypeStylesheet
4404:                                                                .getClassFullName()
4405:                                                        + "  l"
4406:                                                        + lSelectorInputFieldStylesheet
4407:                                                                .getNormalisedName()
4408:                                                        + "Element = ("
4409:                                                        + lInputFieldDatatypeStylesheet
4410:                                                                .getClassFullName()
4411:                                                        + ")l"
4412:                                                        + lSelectorInputFieldStylesheet
4413:                                                                .getNormalisedName()
4414:                                                        + "[i];");
4415:                                        lWriter
4416:                                                .println("                        if (sLogger.isDebugEnabled())");
4417:                                        lWriter
4418:                                                .println("                            sLogger.debug(\"Parameter \" + pStartIndex + \" value: \" + l"
4419:                                                        + lSelectorInputFieldStylesheet
4420:                                                                .getNormalisedName()
4421:                                                        + "Element);");
4422:                                        lWriter
4423:                                                .println("                        pStatement."
4424:                                                        + getDataBaseMetaData()
4425:                                                                .suggestStatementSetMethod(
4426:                                                                        lInputField
4427:                                                                                .getDataType())
4428:                                                        + "(pStartIndex++, TypesConvertor.getSqlValueFrom"
4429:                                                        + getUniqueDatatypeName(lInputField
4430:                                                                .getDataType())
4431:                                                        + "( l"
4432:                                                        + lSelectorInputFieldStylesheet
4433:                                                                .getNormalisedName()
4434:                                                        + "Element));");
4435:                                        lWriter
4436:                                                .println("                    }");
4437:                                    } else {
4438:                                        lWriter
4439:                                                .println("                    if (sLogger.isDebugEnabled())");
4440:                                        lWriter
4441:                                                .println("                        sLogger.debug(\"Parameter \" + pStartIndex + \" value: \" + l"
4442:                                                        + lSelectorInputFieldStylesheet
4443:                                                                .getNormalisedName()
4444:                                                        + ");");
4445:                                        lWriter
4446:                                                .println("                    pStatement."
4447:                                                        + getDataBaseMetaData()
4448:                                                                .suggestStatementSetMethod(
4449:                                                                        lInputField
4450:                                                                                .getDataType())
4451:                                                        + "(pStartIndex++, TypesConvertor.getSqlValueFrom"
4452:                                                        + getUniqueDatatypeName(lInputField
4453:                                                                .getDataType())
4454:                                                        + "( l"
4455:                                                        + lSelectorInputFieldStylesheet
4456:                                                                .getNormalisedName()
4457:                                                        + "));");
4458:                                    }
4459:                                }
4460:                                lWriter.println("                }");
4461:                                lWriter
4462:                                        .println("                catch(DataTypeInvalidOperationForEmptyInstanceException e)");
4463:                                lWriter.println("                {");
4464:                                lWriter
4465:                                        .println("                    throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for empty instance\",e);");
4466:                                lWriter.println("                }");
4467:                                lWriter
4468:                                        .println("                catch(DataTypeInvalidOperationForConcealedInstanceException e)");
4469:                                lWriter.println("                {");
4470:                                lWriter
4471:                                        .println("                    throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for concealed instance\",e);");
4472:                                lWriter.println("                }");
4473:                                lWriter
4474:                                        .println("                catch(java.sql.SQLException e)");
4475:                                lWriter.println("                {");
4476:                                lWriter
4477:                                        .println("                    throw new PSDataSourceOperationInvocationException(\"Error on populating selector's prepared statement.\", e);");
4478:                                lWriter.println("                }");
4479:                                lWriter
4480:                                        .println("                return pStartIndex - lInitialStartIndex;");
4481:                            } else {
4482:                                lWriter
4483:                                        .println("                return 0; // This selector has no parameters");
4484:                            }
4485:                            lWriter.println("            }");
4486:                            lWriter.println("        });");
4487:                        }
4488:                    }
4489:                    lWriter.println("    }");
4490:
4491:                    // Initialise association  interpreters            
4492:                    lWriter.println("    static");
4493:                    lWriter.println("    {");
4494:                    // Iterate through associations and populate selector metadata
4495:                    for (Iterator lAssociationsIterator = lAssociations
4496:                            .iterator(); lAssociationsIterator.hasNext();) {
4497:                        Association lAssociation = (Association) lAssociationsIterator
4498:                                .next();
4499:                        // Roles variables. Note that the role object contains navigation target entity
4500:                        // we however more interested here navigation source entity, hence a bit of cross over in getting entities
4501:                        // Load tables metadata
4502:                        List lAssociationRoles = lAssociation.getRoles();
4503:                        AssociationRole lRoleA = (AssociationRole) lAssociationRoles
4504:                                .get(0);
4505:                        AssociationRole lRoleB = (AssociationRole) lAssociationRoles
4506:                                .get(1);
4507:                        Entity lAEntity = lRoleB.getEntity(); // Entity pointed to by Role B
4508:                        Entity lBEntity = lRoleA.getEntity(); // Entity pointed to by Role A
4509:
4510:                        RelationalEntityTable lAEntityTable = pDomainStorage
4511:                                .getEntityTable(lAEntity);
4512:                        String lAEntityTableName = lAEntityTable
4513:                                .getNameOverride();
4514:                        if (lAEntityTableName == null
4515:                                || lAEntityTableName.length() == 0)
4516:                            lAEntityTableName = lAEntityTable
4517:                                    .getNameSuggestion();
4518:
4519:                        String lAEntityTableInstanceIdColumnName = lAEntityTable
4520:                                .getInstanceIdColumnNameOverride();
4521:                        if (lAEntityTableInstanceIdColumnName == null
4522:                                || lAEntityTableInstanceIdColumnName.length() == 0)
4523:                            lAEntityTableInstanceIdColumnName = lAEntityTable
4524:                                    .getInstanceIdColumnNameSuggestion();
4525:
4526:                        RelationalEntityTable lBEntityTable = pDomainStorage
4527:                                .getEntityTable(lBEntity);
4528:                        String lBEntityTableName = lBEntityTable
4529:                                .getNameOverride();
4530:                        if (lBEntityTableName == null
4531:                                || lBEntityTableName.length() == 0)
4532:                            lBEntityTableName = lBEntityTable
4533:                                    .getNameSuggestion();
4534:
4535:                        String lBEntityTableInstanceIdColumnName = lBEntityTable
4536:                                .getInstanceIdColumnNameOverride();
4537:                        if (lBEntityTableInstanceIdColumnName == null
4538:                                || lBEntityTableInstanceIdColumnName.length() == 0)
4539:                            lBEntityTableInstanceIdColumnName = lBEntityTable
4540:                                    .getInstanceIdColumnNameSuggestion();
4541:
4542:                        // Find out if this is plural association involving the table in the middle
4543:                        String lMiddleTableName = null; // Only poupulatedd below if there is a middle table
4544:                        String lMiddleTableRoleAInstanceIdColumnName = null; // Only poupulatedd below if there is a middle table
4545:                        String lMiddleTableRoleBInstanceIdColumnName = null; // Only poupulatedd below if there is a middle table
4546:
4547:                        String lRoleAEntityAssociationRoleColumnName = null; // Only poupulatedd below if role a entity has a reference
4548:                        String lRoleBEntityAssociationRoleColumnName = null; // Only poupulatedd below if role b entity has a reference
4549:
4550:                        boolean lRoleAHasReference = CommonUtil
4551:                                .doesEntityStoreReference(lRoleA);
4552:                        boolean lRoleBHasReference = CommonUtil
4553:                                .doesEntityStoreReference(lRoleB);
4554:                        boolean lHasTableInTheMiddle = (lRoleAHasReference == false)
4555:                                && (lRoleBHasReference == false);
4556:                        if (lHasTableInTheMiddle) {
4557:                            // Load optional middle table metadata
4558:                            RelationalAssociationTable lAssociationTable = pDomainStorage
4559:                                    .getAssociationTable(lAssociation);
4560:                            lMiddleTableName = lAssociationTable
4561:                                    .getNameOverride();
4562:                            if (lMiddleTableName == null
4563:                                    || lMiddleTableName.length() == 0)
4564:                                lMiddleTableName = lAssociationTable
4565:                                        .getNameSuggestion();
4566:                            lMiddleTableRoleAInstanceIdColumnName = lAssociationTable
4567:                                    .getFirstRoleColumnNameOverride();
4568:                            if (lMiddleTableRoleAInstanceIdColumnName == null
4569:                                    || lMiddleTableRoleAInstanceIdColumnName
4570:                                            .length() == 0)
4571:                                lMiddleTableRoleAInstanceIdColumnName = lAssociationTable
4572:                                        .getFirstRoleColumnNameSuggestion();
4573:                            lMiddleTableRoleBInstanceIdColumnName = lAssociationTable
4574:                                    .getSecondRoleColumnNameOverride();
4575:                            if (lMiddleTableRoleBInstanceIdColumnName == null
4576:                                    || lMiddleTableRoleBInstanceIdColumnName
4577:                                            .length() == 0)
4578:                                lMiddleTableRoleBInstanceIdColumnName = lAssociationTable
4579:                                        .getSecondRoleColumnNameSuggestion();
4580:                        } else if (lRoleAHasReference) {
4581:                            RelationalEntityTableReferenceColumn lEntityTableAssociationRole = lAEntityTable
4582:                                    .getReferenceColumn(lRoleA);
4583:                            lRoleAEntityAssociationRoleColumnName = lEntityTableAssociationRole
4584:                                    .getColumnNameOverride();
4585:                            if (lRoleAEntityAssociationRoleColumnName == null
4586:                                    || lRoleAEntityAssociationRoleColumnName
4587:                                            .length() == 0)
4588:                                lRoleAEntityAssociationRoleColumnName = lEntityTableAssociationRole
4589:                                        .getColumnNameSuggestion();
4590:                        } else if (lRoleBHasReference) {
4591:                            RelationalEntityTableReferenceColumn lEntityTableAssociationRole = lBEntityTable
4592:                                    .getReferenceColumn(lRoleB);
4593:                            lRoleBEntityAssociationRoleColumnName = lEntityTableAssociationRole
4594:                                    .getColumnNameOverride();
4595:                            if (lRoleBEntityAssociationRoleColumnName == null
4596:                                    || lRoleBEntityAssociationRoleColumnName
4597:                                            .length() == 0)
4598:                                lRoleBEntityAssociationRoleColumnName = lEntityTableAssociationRole
4599:                                        .getColumnNameSuggestion();
4600:                        }
4601:                        // We need to build three where clauses from A to B,  from B to A and association join
4602:                        String lAtoBWhereClause = null;
4603:                        String lAtoBWhereClauseWithId = null;
4604:                        String lBtoAWhereClause = null;
4605:                        String lBtoAWhereClauseWithId = null;
4606:                        if (lHasTableInTheMiddle) {
4607:                            // AtoB clause
4608:                            StringBuffer lAtoBClauseWithIdBuffer = new StringBuffer();
4609:                            lAtoBClauseWithIdBuffer
4610:                                    .append("lFromTableAlias + \".");
4611:                            lAtoBClauseWithIdBuffer
4612:                                    .append(lAEntityTableInstanceIdColumnName);
4613:                            lAtoBClauseWithIdBuffer.append(" = ? AND \" + ");
4614:
4615:                            StringBuffer lAtoBWhereClauseBuffer = new StringBuffer();
4616:                            lAtoBWhereClauseBuffer
4617:                                    .append("lFromTableAlias + \".");
4618:                            lAtoBWhereClauseBuffer
4619:                                    .append(lAEntityTableInstanceIdColumnName);
4620:                            lAtoBWhereClauseBuffer
4621:                                    .append(" = \" + lMiddleTableAlias + \".");
4622:                            lAtoBWhereClauseBuffer
4623:                                    .append(lMiddleTableRoleBInstanceIdColumnName);
4624:                            lAtoBWhereClauseBuffer
4625:                                    .append(" AND \" + lToTableAlias + \".");
4626:                            lAtoBWhereClauseBuffer
4627:                                    .append(lBEntityTableInstanceIdColumnName);
4628:                            lAtoBWhereClauseBuffer
4629:                                    .append(" = \" + lMiddleTableAlias + \".");
4630:                            lAtoBWhereClauseBuffer
4631:                                    .append(lMiddleTableRoleAInstanceIdColumnName);
4632:                            lAtoBWhereClauseBuffer.append("\"");
4633:
4634:                            lAtoBWhereClause = lAtoBWhereClauseBuffer
4635:                                    .toString();
4636:                            lAtoBWhereClauseWithId = lAtoBClauseWithIdBuffer
4637:                                    .toString()
4638:                                    + lAtoBWhereClause;
4639:
4640:                            // BtoA clause
4641:                            StringBuffer lBtoAClauseWithIdBuffer = new StringBuffer();
4642:                            lBtoAClauseWithIdBuffer
4643:                                    .append("lFromTableAlias + \".");
4644:                            lBtoAClauseWithIdBuffer
4645:                                    .append(lBEntityTableInstanceIdColumnName);
4646:                            lBtoAClauseWithIdBuffer.append(" = ? AND \" + ");
4647:
4648:                            StringBuffer lBtoAWhereClauseBuffer = new StringBuffer();
4649:                            lBtoAWhereClauseBuffer
4650:                                    .append("lFromTableAlias + \".");
4651:                            lBtoAWhereClauseBuffer
4652:                                    .append(lBEntityTableInstanceIdColumnName);
4653:                            lBtoAWhereClauseBuffer
4654:                                    .append(" = \" + lMiddleTableAlias + \".");
4655:                            lBtoAWhereClauseBuffer
4656:                                    .append(lMiddleTableRoleAInstanceIdColumnName);
4657:                            lBtoAWhereClauseBuffer
4658:                                    .append(" AND \" + lMiddleTableAlias + \".");
4659:                            lBtoAWhereClauseBuffer
4660:                                    .append(lMiddleTableRoleBInstanceIdColumnName);
4661:                            lBtoAWhereClauseBuffer
4662:                                    .append(" = \" + lToTableAlias + \".");
4663:                            lBtoAWhereClauseBuffer
4664:                                    .append(lAEntityTableInstanceIdColumnName);
4665:                            lBtoAWhereClauseBuffer.append("\"");
4666:
4667:                            lBtoAWhereClause = lBtoAWhereClauseBuffer
4668:                                    .toString();
4669:                            lBtoAWhereClauseWithId = lBtoAClauseWithIdBuffer
4670:                                    .toString()
4671:                                    + lBtoAWhereClause;
4672:                        } else if (lRoleAHasReference) {
4673:                            // AtoB clause
4674:                            StringBuffer lAtoBClauseWithIdBuffer = new StringBuffer();
4675:                            lAtoBClauseWithIdBuffer
4676:                                    .append("lFromTableAlias + \".");
4677:                            lAtoBClauseWithIdBuffer
4678:                                    .append(lAEntityTableInstanceIdColumnName);
4679:                            lAtoBClauseWithIdBuffer.append(" = ? AND \" + ");
4680:
4681:                            StringBuffer lAtoBWhereClauseBuffer = new StringBuffer();
4682:                            lAtoBWhereClauseBuffer
4683:                                    .append("lFromTableAlias + \".");
4684:                            lAtoBWhereClauseBuffer
4685:                                    .append(lRoleAEntityAssociationRoleColumnName);
4686:                            lAtoBWhereClauseBuffer
4687:                                    .append(" = \" + lToTableAlias + \".");
4688:                            lAtoBWhereClauseBuffer
4689:                                    .append(lBEntityTableInstanceIdColumnName);
4690:                            lAtoBWhereClauseBuffer.append("\"");
4691:
4692:                            lAtoBWhereClause = lAtoBWhereClauseBuffer
4693:                                    .toString();
4694:                            lAtoBWhereClauseWithId = lAtoBClauseWithIdBuffer
4695:                                    .toString()
4696:                                    + lAtoBWhereClause;
4697:
4698:                            // BtoA clause
4699:                            StringBuffer lBtoAClauseWithIdBuffer = new StringBuffer();
4700:                            lBtoAClauseWithIdBuffer
4701:                                    .append("lFromTableAlias + \".");
4702:                            lBtoAClauseWithIdBuffer
4703:                                    .append(lBEntityTableInstanceIdColumnName);
4704:                            lBtoAClauseWithIdBuffer.append(" = ? AND \" + ");
4705:
4706:                            StringBuffer lBtoAWhereClauseBuffer = new StringBuffer();
4707:                            lBtoAWhereClauseBuffer
4708:                                    .append("lFromTableAlias + \".");
4709:                            lBtoAWhereClauseBuffer
4710:                                    .append(lBEntityTableInstanceIdColumnName);
4711:                            lBtoAWhereClauseBuffer
4712:                                    .append(" = \" + lToTableAlias + \".");
4713:                            lBtoAWhereClauseBuffer
4714:                                    .append(lRoleAEntityAssociationRoleColumnName);
4715:                            lBtoAWhereClauseBuffer.append("\"");
4716:
4717:                            lBtoAWhereClause = lBtoAWhereClauseBuffer
4718:                                    .toString();
4719:                            lBtoAWhereClauseWithId = lBtoAClauseWithIdBuffer
4720:                                    .toString()
4721:                                    + lBtoAWhereClause;
4722:                        } else {
4723:                            // AtoB clause
4724:                            StringBuffer lAtoBClauseWithIdBuffer = new StringBuffer();
4725:                            lAtoBClauseWithIdBuffer
4726:                                    .append("lFromTableAlias + \".");
4727:                            lAtoBClauseWithIdBuffer
4728:                                    .append(lAEntityTableInstanceIdColumnName);
4729:                            lAtoBClauseWithIdBuffer.append(" = ? AND \" + ");
4730:
4731:                            StringBuffer lAtoBWhereClauseBuffer = new StringBuffer();
4732:                            lAtoBWhereClauseBuffer
4733:                                    .append("lFromTableAlias + \".");
4734:                            lAtoBWhereClauseBuffer
4735:                                    .append(lAEntityTableInstanceIdColumnName);
4736:                            lAtoBWhereClauseBuffer
4737:                                    .append(" = \" + lToTableAlias + \".");
4738:                            lAtoBWhereClauseBuffer
4739:                                    .append(lRoleBEntityAssociationRoleColumnName);
4740:                            lAtoBWhereClauseBuffer.append("\"");
4741:
4742:                            lAtoBWhereClause = lAtoBWhereClauseBuffer
4743:                                    .toString();
4744:                            lAtoBWhereClauseWithId = lAtoBClauseWithIdBuffer
4745:                                    .toString()
4746:                                    + lAtoBWhereClause;
4747:
4748:                            // BtoA clause
4749:                            StringBuffer lBtoAClauseWithIdBuffer = new StringBuffer();
4750:                            lBtoAClauseWithIdBuffer
4751:                                    .append("lFromTableAlias + \".");
4752:                            lBtoAClauseWithIdBuffer
4753:                                    .append(lBEntityTableInstanceIdColumnName);
4754:                            lBtoAClauseWithIdBuffer.append(" = ? AND \" + ");
4755:
4756:                            StringBuffer lBtoAWhereClauseBuffer = new StringBuffer();
4757:                            lBtoAWhereClauseBuffer
4758:                                    .append("lFromTableAlias + \".");
4759:                            lBtoAWhereClauseBuffer
4760:                                    .append(lRoleBEntityAssociationRoleColumnName);
4761:                            lBtoAWhereClauseBuffer
4762:                                    .append(" = \" + lToTableAlias + \".");
4763:                            lBtoAWhereClauseBuffer
4764:                                    .append(lAEntityTableInstanceIdColumnName);
4765:                            lBtoAWhereClauseBuffer.append("\"");
4766:
4767:                            lBtoAWhereClause = lBtoAWhereClauseBuffer
4768:                                    .toString();
4769:                            lBtoAWhereClauseWithId = lBtoAClauseWithIdBuffer
4770:                                    .toString()
4771:                                    + lBtoAWhereClause;
4772:                        }
4773:                        // Write out the creation and registration of the Role A selector
4774:                        lWriter
4775:                                .println("        // Generate and store metadata for the "
4776:                                        + lRoleA.getRef()
4777:                                        + " association role selector");
4778:                        lWriter
4779:                                .println("        sAssociationSelectorMetadataMap.put(\""
4780:                                        + lRoleA.getRef()
4781:                                        + "\", new CollectionDetailsInterpreter()");
4782:                        lWriter.println("        {");
4783:                        lWriter
4784:                                .println("            public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
4785:                        lWriter.println("            {");
4786:                        // Look after from table
4787:                        lWriter
4788:                                .println("                if (pQueryContext.getCurrentToTableName() == null || pQueryContext.getCurrentToTableName().equals(\""
4789:                                        + lBEntityTableName + "\") == false)");
4790:                        lWriter
4791:                                .println("                    throw new PSUnexpectedProgramConditionException(\"Selector is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
4792:                        lWriter
4793:                                .println("                String lToTableAlias = pQueryContext.getCurrentToTableAlias();");
4794:                        // Look after middle table 
4795:                        if (lHasTableInTheMiddle)
4796:                            lWriter
4797:                                    .println("                String lMiddleTableAlias = pQueryContext.takeTableForUse(\""
4798:                                            + lMiddleTableName + "\");");
4799:                        // Look after to table
4800:                        lWriter
4801:                                .println("                String lFromTableAlias = pQueryContext.takeTableForUse(\""
4802:                                        + lAEntityTableName + "\");");
4803:                        // Now that we have finished with tables - return actual statements
4804:                        lWriter
4805:                                .println("                if ( pCollectionDetails.AssociationRoleEntityInstanceId == null)");
4806:                        lWriter.println("                    return "
4807:                                + lAtoBWhereClause + ";");
4808:                        lWriter.println("                return "
4809:                                + lAtoBWhereClauseWithId + ";");
4810:                        lWriter.println("            }");
4811:
4812:                        lWriter
4813:                                .println("            public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
4814:                        lWriter.println("            {");
4815:                        // Presence of instance id is optional - it just adds the recordid = ? clause
4816:                        lWriter
4817:                                .println("                if ( pCollectionDetails.AssociationRoleEntityInstanceId == null)");
4818:                        lWriter.println("                    return 0;");
4819:                        DataType lAEntityInstanceIdDatatype = lAEntity
4820:                                .getInstanceIdDataType();
4821:                        STDatatypeStylesheet lAEntityInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
4822:                                .getDatatypeStylesheet(lAEntityInstanceIdDatatype);
4823:                        lWriter
4824:                                .println("                "
4825:                                        + lAEntityInstanceIdDatatypeStylesheet
4826:                                                .getClassFullName()
4827:                                        + " lInstanceId = ("
4828:                                        + lAEntityInstanceIdDatatypeStylesheet
4829:                                                .getClassFullName()
4830:                                        + ")pCollectionDetails.AssociationRoleEntityInstanceId;");
4831:                        lWriter
4832:                                .println("                if (lInstanceId.isEmpty())");
4833:                        lWriter
4834:                                .println("                    throw new PSSelectorConstraintViolationException(\"AssociationRoleEntityInstanceId field in the "
4835:                                        + lRoleA.getRef()
4836:                                        + " association role selector is not expected to be empty for query operation.\");");
4837:                        lWriter
4838:                                .println("                if (lInstanceId.isConcealed())");
4839:                        lWriter
4840:                                .println("                    throw new PSSelectorConstraintViolationException(\"AssociationRoleEntityInstanceId field in the "
4841:                                        + lRoleA.getRef()
4842:                                        + " association role selector is not expected to be undefined for query operation.\");");
4843:                        // Now that the checking is done - populate prepared statement
4844:                        lWriter.println("                try");
4845:                        lWriter.println("                {");
4846:                        lWriter
4847:                                .println("                    if (sLogger.isDebugEnabled())");
4848:                        lWriter
4849:                                .println("                        sLogger.debug(\"Parameter \" + pStartIndex + \" value: \" + lInstanceId);");
4850:                        lWriter
4851:                                .println("                    pStatement."
4852:                                        + getDataBaseMetaData()
4853:                                                .suggestStatementSetMethod(
4854:                                                        lAEntityInstanceIdDatatype)
4855:                                        + "(pStartIndex++, TypesConvertor.getSqlValueFrom"
4856:                                        + getUniqueDatatypeName(lAEntityInstanceIdDatatype)
4857:                                        + "(lInstanceId));");
4858:                        lWriter.println("                }");
4859:                        lWriter
4860:                                .println("                catch(DataTypeInvalidOperationForEmptyInstanceException e)");
4861:                        lWriter.println("                {");
4862:                        lWriter
4863:                                .println("                    throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for empty instance\",e);");
4864:                        lWriter.println("                }");
4865:                        lWriter
4866:                                .println("                catch(DataTypeInvalidOperationForConcealedInstanceException e)");
4867:                        lWriter.println("                {");
4868:                        lWriter
4869:                                .println("                    throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for concealed instance\",e);");
4870:                        lWriter.println("                }");
4871:                        lWriter
4872:                                .println("                catch(java.sql.SQLException e)");
4873:                        lWriter.println("                {");
4874:                        lWriter
4875:                                .println("                    throw new PSDataSourceOperationInvocationException(\"Error on populating selector's prepared statement.\", e);");
4876:                        lWriter.println("                }");
4877:                        lWriter.println("                return 1;");
4878:                        lWriter.println("            }");
4879:                        lWriter.println("        });");
4880:                        // Write out the creation and registration of the Role B selector
4881:                        lWriter
4882:                                .println("        // Generate and store metadata for the "
4883:                                        + lRoleB.getRef()
4884:                                        + " association role selector");
4885:                        lWriter
4886:                                .println("        sAssociationSelectorMetadataMap.put(\""
4887:                                        + lRoleB.getRef()
4888:                                        + "\", new CollectionDetailsInterpreter()");
4889:                        lWriter.println("        {");
4890:                        lWriter
4891:                                .println("            public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
4892:                        lWriter.println("            {");
4893:                        lWriter
4894:                                .println("                if (pQueryContext.getCurrentToTableName() == null || pQueryContext.getCurrentToTableName().equals(\""
4895:                                        + lAEntityTableName + "\") == false)");
4896:                        lWriter
4897:                                .println("                    throw new PSUnexpectedProgramConditionException(\"Selector is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
4898:                        lWriter
4899:                                .println("                String lToTableAlias = pQueryContext.getCurrentToTableAlias();");
4900:                        // Look after middle table 
4901:                        if (lHasTableInTheMiddle)
4902:                            lWriter
4903:                                    .println("                String lMiddleTableAlias = pQueryContext.takeTableForUse(\""
4904:                                            + lMiddleTableName + "\");");
4905:                        // Look after to table
4906:                        lWriter
4907:                                .println("                String lFromTableAlias = pQueryContext.takeTableForUse(\""
4908:                                        + lBEntityTableName + "\");");
4909:                        // Now that we have finished with tables - return actual statements
4910:                        lWriter
4911:                                .println("                if ( pCollectionDetails.AssociationRoleEntityInstanceId == null)");
4912:                        lWriter.println("                    return "
4913:                                + lBtoAWhereClause + ";");
4914:                        lWriter.println("                return "
4915:                                + lBtoAWhereClauseWithId + ";");
4916:                        lWriter.println("            }");
4917:
4918:                        lWriter
4919:                                .println("            public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
4920:                        lWriter.println("            {");
4921:                        // Presence of instance id is optional - it just adds the recordid = ? clause
4922:                        lWriter
4923:                                .println("                if ( pCollectionDetails.AssociationRoleEntityInstanceId == null)");
4924:                        lWriter.println("                    return 0;");
4925:                        DataType lBEntityInstanceIdDatatype = lBEntity
4926:                                .getInstanceIdDataType();
4927:                        STDatatypeStylesheet lBEntityInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
4928:                                .getDatatypeStylesheet(lBEntityInstanceIdDatatype);
4929:                        lWriter
4930:                                .println("                "
4931:                                        + lBEntityInstanceIdDatatypeStylesheet
4932:                                                .getClassFullName()
4933:                                        + " lInstanceId = ("
4934:                                        + lBEntityInstanceIdDatatypeStylesheet
4935:                                                .getClassFullName()
4936:                                        + ")pCollectionDetails.AssociationRoleEntityInstanceId;");
4937:                        lWriter
4938:                                .println("                if (lInstanceId.isEmpty())");
4939:                        lWriter
4940:                                .println("                    throw new PSSelectorConstraintViolationException(\"AssociationRoleEntityInstanceId field in the "
4941:                                        + lRoleB.getRef()
4942:                                        + " association role selector is not expected to be empty for query operation.\");");
4943:                        lWriter
4944:                                .println("                if (lInstanceId.isConcealed())");
4945:                        lWriter
4946:                                .println("                    throw new PSSelectorConstraintViolationException(\"AssociationRoleEntityInstanceId field in the "
4947:                                        + lRoleB.getRef()
4948:                                        + " association role selector is not expected to be undefined for query operation.\");");
4949:                        // Now that the checking is done - populate prepared statement
4950:                        lWriter.println("                try");
4951:                        lWriter.println("                {");
4952:                        lWriter
4953:                                .println("                    if (sLogger.isDebugEnabled())");
4954:                        lWriter
4955:                                .println("                        sLogger.debug(\"Parameter \" + pStartIndex + \" value: \" + lInstanceId);");
4956:                        lWriter
4957:                                .println("                    pStatement."
4958:                                        + getDataBaseMetaData()
4959:                                                .suggestStatementSetMethod(
4960:                                                        lBEntityInstanceIdDatatype)
4961:                                        + "(pStartIndex++, TypesConvertor.getSqlValueFrom"
4962:                                        + getUniqueDatatypeName(lBEntityInstanceIdDatatype)
4963:                                        + "(lInstanceId));");
4964:                        lWriter.println("                }");
4965:                        lWriter
4966:                                .println("                catch(DataTypeInvalidOperationForEmptyInstanceException e)");
4967:                        lWriter.println("                {");
4968:                        lWriter
4969:                                .println("                    throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for empty instance\",e);");
4970:                        lWriter.println("                }");
4971:                        lWriter
4972:                                .println("                catch(DataTypeInvalidOperationForConcealedInstanceException e)");
4973:                        lWriter.println("                {");
4974:                        lWriter
4975:                                .println("                    throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code checks for concealed instance\",e);");
4976:                        lWriter.println("                }");
4977:                        lWriter
4978:                                .println("                catch(java.sql.SQLException e)");
4979:                        lWriter.println("                {");
4980:                        lWriter
4981:                                .println("                    throw new PSDataSourceOperationInvocationException(\"Error on populating selector's prepared statement.\", e);");
4982:                        lWriter.println("                }");
4983:                        lWriter.println("                return 1;");
4984:                        lWriter.println("            }");
4985:                        lWriter.println("        });");
4986:                    }
4987:                    lWriter.println("    }");
4988:
4989:                    // Initialise ordering interpreters            
4990:                    lWriter.println("    static");
4991:                    lWriter.println("    {");
4992:                    // Iterate through entities and populate selector metadata
4993:                    for (Iterator lEntitiesIterator = lEntities.iterator(); lEntitiesIterator
4994:                            .hasNext();) {
4995:                        Entity lEntity = (Entity) lEntitiesIterator.next();
4996:                        RelationalEntityTable lEntityTable = pDomainStorage
4997:                                .getEntityTable(lEntity);
4998:                        String lEntityTableName = lEntityTable
4999:                                .getNameOverride();
5000:                        if (lEntityTableName == null
5001:                                || lEntityTableName.length() == 0)
5002:                            lEntityTableName = lEntityTable.getNameSuggestion();
5003:                        String lEntityTableInstanceIdColumnName = lEntityTable
5004:                                .getInstanceIdColumnNameOverride();
5005:                        if (lEntityTableInstanceIdColumnName == null
5006:                                || lEntityTableInstanceIdColumnName.length() == 0)
5007:                            lEntityTableInstanceIdColumnName = lEntityTable
5008:                                    .getInstanceIdColumnNameSuggestion();
5009:
5010:                        Collection lSubtypeEntities = lEntity
5011:                                .getCombinedSubtypes();
5012:                        String[] lSubtypeTableNames = new String[lSubtypeEntities
5013:                                .size()];
5014:                        String[] lSubtypeInstanceIdColumnNames = new String[lSubtypeEntities
5015:                                .size()];
5016:                        {
5017:                            int i = 0;
5018:                            for (Iterator lSubtypeEntitiesIterator = lSubtypeEntities
5019:                                    .iterator(); lSubtypeEntitiesIterator
5020:                                    .hasNext(); i++) {
5021:                                Entity lSubtypeEntity = (Entity) lSubtypeEntitiesIterator
5022:                                        .next();
5023:                                RelationalEntityTable lSubtypeEntityTable = pDomainStorage
5024:                                        .getEntityTable(lSubtypeEntity);
5025:                                String lSubtypeEntityTableName = lSubtypeEntityTable
5026:                                        .getNameOverride();
5027:                                if (lSubtypeEntityTableName == null
5028:                                        || lSubtypeEntityTableName.length() == 0)
5029:                                    lSubtypeEntityTableName = lSubtypeEntityTable
5030:                                            .getNameSuggestion();
5031:                                String lSubtypeEntityTableInstanceIdColumnName = lSubtypeEntityTable
5032:                                        .getInstanceIdColumnNameOverride();
5033:                                if (lSubtypeEntityTableInstanceIdColumnName == null
5034:                                        || lSubtypeEntityTableInstanceIdColumnName
5035:                                                .length() == 0)
5036:                                    lSubtypeEntityTableInstanceIdColumnName = lSubtypeEntityTable
5037:                                            .getInstanceIdColumnNameSuggestion();
5038:                                lSubtypeTableNames[i] = lSubtypeEntityTableName;
5039:                                lSubtypeInstanceIdColumnNames[i] = lSubtypeEntityTableInstanceIdColumnName;
5040:                            }
5041:                        }
5042:
5043:                        Collection lAttributes = lEntity.getSelectors();
5044:                        for (Iterator lAttributesIterator = lEntity
5045:                                .getAttributes().iterator(); lAttributesIterator
5046:                                .hasNext();) {
5047:                            Attribute lAttribute = (Attribute) lAttributesIterator
5048:                                    .next();
5049:                            if (lAttribute.isUsedForOrdering()) {
5050:                                RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
5051:                                        .getAttributeColumn(lAttribute);
5052:                                String lAttributeColumnName = lRelationalEntityTableAttribute
5053:                                        .getColumnNameOverride();
5054:                                if (lAttributeColumnName == null
5055:                                        || lAttributeColumnName.length() == 0)
5056:                                    lAttributeColumnName = lRelationalEntityTableAttribute
5057:                                            .getColumnNameSuggestion();
5058:
5059:                                // If this is enumerable and comparable data type - the ordering will need to
5060:                                // use the reference table						
5061:                                boolean lNeedsToUseReferenceTable = false;
5062:                                DataType lAttributeDatatype = lAttribute
5063:                                        .getDataType();
5064:                                Properties lDataTypeProperties = DataTypeUtils
5065:                                        .getTypetemplatePropertiesAsProperties(lAttributeDatatype);
5066:                                TypeTemplate lTypetemplate = lAttributeDatatype
5067:                                        .getTypetemplate();
5068:                                if (lTypetemplate != null
5069:                                        && lTypetemplate
5070:                                                .equals(lEnumerableValueTypeTemplate)) {
5071:                                    if (Boolean.valueOf(
5072:                                            lDataTypeProperties.getProperty(
5073:                                                    "Comparable", "false"))
5074:                                            .booleanValue())
5075:                                        lNeedsToUseReferenceTable = true;
5076:                                }
5077:
5078:                                // Write out the creation and registration of this selector
5079:                                lWriter
5080:                                        .println("        // Generate and store metadata for the ordering by "
5081:                                                + lAttribute.getRef()
5082:                                                + " attribute selector");
5083:                                lWriter
5084:                                        .println("        sEntityOrderingMetadataMap.put(\""
5085:                                                + lAttribute.getRef()
5086:                                                + "\", new OrderingDetailsInterpreter()");
5087:                                lWriter.println("        {");
5088:                                lWriter
5089:                                        .println("            public OrderingDetailsInterpreter.SqlClauses getSqlClauses(STOrderingDetails pOrderingDetails, QueryContext pQueryContext) throws PSException");
5090:                                lWriter.println("            {");
5091:                                lWriter
5092:                                        .println("                OrderingDetailsInterpreter.SqlClauses lClauses = new OrderingDetailsInterpreter.SqlClauses();");
5093:                                lWriter
5094:                                        .println("                if (pQueryContext.getCurrentToTableName() == null)");
5095:                                lWriter
5096:                                        .println("                    throw new PSUnexpectedProgramConditionException(\"Ordering instruction is called out of context (current table is null).\");");
5097:                                // Deal with possible necessity to do a joint between super and subtable
5098:                                if (lSubtypeEntities.isEmpty()) {
5099:                                    // Simple case - this entity does not have any subtypes
5100:                                    lWriter
5101:                                            .println("                if (!pQueryContext.getCurrentToTableName().equals(\""
5102:                                                    + lEntityTableName + "\"))");
5103:                                    lWriter
5104:                                            .println("                    throw new PSUnexpectedProgramConditionException(\"Ordering instruction is called out of context (disconnected chain of tables). This situation means that the current table does not have this attribute and can not be sorted by it.\");");
5105:                                    lWriter
5106:                                            .println("                String lToTableAlias = pQueryContext.getCurrentToTableAlias();");
5107:                                    // If we are not using the reference table  it means that we will be doing an order by
5108:                                    // the column in this table. In order for this to work this column must be placed in the what clause
5109:                                    if (!lNeedsToUseReferenceTable) {
5110:                                        lWriter
5111:                                                .println("                StringBuffer lWhatClauseBuffer = new StringBuffer();");
5112:                                        lWriter
5113:                                                .println("                lWhatClauseBuffer.append(lToTableAlias);");
5114:                                        lWriter
5115:                                                .println("                lWhatClauseBuffer.append(\"."
5116:                                                        + lAttributeColumnName
5117:                                                        + "\");");
5118:                                        lWriter
5119:                                                .println("                lClauses.WhatClause = lWhatClauseBuffer.toString();");
5120:                                    }
5121:                                } else {
5122:                                    // TODO: Ensure that the joint only appears once in the select also move to the query context object concept - much neater
5123:                                    // Complex case - we need to cater for the subtypes
5124:                                    lWriter
5125:                                            .println("                String lToTableAlias = pQueryContext.getCurrentToTableAlias();");
5126:                                    for (int i = 0; i < lSubtypeTableNames.length; i++) {
5127:                                        if (i > 0)
5128:                                            lWriter
5129:                                                    .println("                else");
5130:                                        lWriter
5131:                                                .println("                if (pQueryContext.getCurrentToTableName().equals(\""
5132:                                                        + lSubtypeTableNames[i]
5133:                                                        + "\"))");
5134:                                        lWriter.println("                {");
5135:                                        // Note that we are taking the super table for use but not making it current table
5136:                                        lWriter
5137:                                                .println("                    String lSuperTableAlias = pQueryContext.takeTable(\""
5138:                                                        + lEntityTableName
5139:                                                        + "\");");
5140:                                        // If we are not using the reference table  it means that we will be doing an order by
5141:                                        // the column in this table. In order for this to work this column must be placed in the what clause
5142:                                        if (!lNeedsToUseReferenceTable) {
5143:                                            lWriter
5144:                                                    .println("                StringBuffer lWhatClauseBuffer = new StringBuffer();");
5145:                                            lWriter
5146:                                                    .println("                lWhatClauseBuffer.append(lSuperTableAlias);");
5147:                                            lWriter
5148:                                                    .println("                lWhatClauseBuffer.append(\"."
5149:                                                            + lAttributeColumnName
5150:                                                            + "\");");
5151:                                            lWriter
5152:                                                    .println("                lClauses.WhatClause = lWhatClauseBuffer.toString();");
5153:                                        }
5154:                                        // Add join to the where clause
5155:                                        lWriter
5156:                                                .println("                    StringBuffer lWhereClauseBuffer = new StringBuffer();");
5157:                                        lWriter
5158:                                                .println("                    lWhereClauseBuffer.append(lToTableAlias);");
5159:                                        lWriter
5160:                                                .println("                    lWhereClauseBuffer.append(\"."
5161:                                                        + lSubtypeInstanceIdColumnNames[i]
5162:                                                        + " = \");");
5163:                                        lWriter
5164:                                                .println("                    lWhereClauseBuffer.append(lSuperTableAlias);");
5165:                                        lWriter
5166:                                                .println("                    lWhereClauseBuffer.append(\"."
5167:                                                        + lEntityTableInstanceIdColumnName
5168:                                                        + "\");");
5169:                                        lWriter
5170:                                                .println("                    lClauses.WhereClause = lWhereClauseBuffer.toString();");
5171:                                        lWriter
5172:                                                .println("                    lToTableAlias = lSuperTableAlias;");
5173:                                        lWriter.println("                }");
5174:                                    }
5175:                                    lWriter.println("                else");
5176:                                    if (!lNeedsToUseReferenceTable) {
5177:                                        lWriter
5178:                                                .println("                if (pQueryContext.getCurrentToTableName().equals(\""
5179:                                                        + lEntityTableName
5180:                                                        + "\"))");
5181:                                        lWriter.println("                {");
5182:                                        lWriter
5183:                                                .println("                    StringBuffer lWhatClauseBuffer = new StringBuffer();");
5184:                                        lWriter
5185:                                                .println("                    lWhatClauseBuffer.append(lToTableAlias);");
5186:                                        lWriter
5187:                                                .println("                    lWhatClauseBuffer.append(\"."
5188:                                                        + lAttributeColumnName
5189:                                                        + "\");");
5190:                                        lWriter
5191:                                                .println("                    lClauses.WhatClause = lWhatClauseBuffer.toString();");
5192:                                        lWriter.println("                }");
5193:                                        lWriter.println("                else");
5194:                                        lWriter
5195:                                                .println("                    throw new PSUnexpectedProgramConditionException(\"Ordering instruction is called out of context (disconnected chain of tables). This situation means that the current table does not have this attribute and can not be sorted by it.\");");
5196:                                    } else {
5197:                                        lWriter
5198:                                                .println("                if (!pQueryContext.getCurrentToTableName().equals(\""
5199:                                                        + lEntityTableName
5200:                                                        + "\"))");
5201:                                        lWriter
5202:                                                .println("                    throw new PSUnexpectedProgramConditionException(\"Ordering instruction is called out of context (disconnected chain of tables). This situation means that the current table does not have this attribute and can not be sorted by it.\");");
5203:                                    }
5204:                                }
5205:
5206:                                if (lNeedsToUseReferenceTable) {
5207:                                    // This is the special case where the reference table must be used
5208:                                    // Obtain some values from storage definition            
5209:                                    RelationalReferenceTable lReferenceTable = pDomainStorage
5210:                                            .getReferenceTable(lAttributeDatatype);
5211:                                    String lReferenceTableName = lReferenceTable
5212:                                            .getNameOverride();
5213:                                    if (lReferenceTableName == null
5214:                                            || lReferenceTableName.length() == 0)
5215:                                        lReferenceTableName = lReferenceTable
5216:                                                .getNameSuggestion();
5217:                                    String lReferenceTableValueColumnName = lReferenceTable
5218:                                            .getValueColumnNameOverride();
5219:                                    if (lReferenceTableValueColumnName == null
5220:                                            || lReferenceTableValueColumnName
5221:                                                    .length() == 0)
5222:                                        lReferenceTableValueColumnName = lReferenceTable
5223:                                                .getValueColumnNameSuggestion();
5224:                                    String lReferenceTableWeightColumnName = lReferenceTable
5225:                                            .getWeightColumnNameOverride();
5226:                                    if (lReferenceTableWeightColumnName == null
5227:                                            || lReferenceTableWeightColumnName
5228:                                                    .length() == 0)
5229:                                        lReferenceTableWeightColumnName = lReferenceTable
5230:                                                .getWeightColumnNameSuggestion();
5231:
5232:                                    // Note that we are taking the reference table for use but not making it current table
5233:                                    lWriter
5234:                                            .println("                String lReferenceTableAlias = pQueryContext.takeTable(\""
5235:                                                    + lReferenceTableName
5236:                                                    + "\");");
5237:                                    // Add reference table to What clause
5238:                                    lWriter
5239:                                            .println("                StringBuffer lWhatClauseBuffer = new StringBuffer();");
5240:                                    lWriter
5241:                                            .println("                lWhatClauseBuffer.append(lReferenceTableAlias);");
5242:                                    lWriter
5243:                                            .println("                lWhatClauseBuffer.append(\"."
5244:                                                    + lReferenceTableWeightColumnName
5245:                                                    + "\");");
5246:                                    lWriter
5247:                                            .println("                lClauses.WhatClause = lWhatClauseBuffer.toString();");
5248:                                    // Add join to the where clause
5249:                                    lWriter
5250:                                            .println("                StringBuffer lWhereClauseBuffer = new StringBuffer();");
5251:                                    // Where clause may already have a join
5252:                                    if (!lSubtypeEntities.isEmpty()) {
5253:                                        // The subtypes join might already be populated - we need to preserve it
5254:                                        lWriter
5255:                                                .println("                if (lClauses.WhereClause != null)");
5256:                                        lWriter.println("                {");
5257:                                        lWriter
5258:                                                .println("                    lWhereClauseBuffer.append(lClauses.WhereClause);");
5259:                                        lWriter
5260:                                                .println("                    lWhereClauseBuffer.append(\" AND \");");
5261:                                        lWriter.println("                }");
5262:                                    }
5263:                                    lWriter
5264:                                            .println("                lWhereClauseBuffer.append(lToTableAlias);");
5265:                                    lWriter
5266:                                            .println("                lWhereClauseBuffer.append(\"."
5267:                                                    + lAttributeColumnName
5268:                                                    + " = \");");
5269:                                    lWriter
5270:                                            .println("                lWhereClauseBuffer.append(lReferenceTableAlias);");
5271:                                    lWriter
5272:                                            .println("                lWhereClauseBuffer.append(\"."
5273:                                                    + lReferenceTableValueColumnName
5274:                                                    + "\");");
5275:                                    lWriter
5276:                                            .println("                lClauses.WhereClause = lWhereClauseBuffer.toString();");
5277:
5278:                                    // Work on Order By clause		
5279:                                    lWriter
5280:                                            .println("                StringBuffer lOrderByClauseBuffer = new StringBuffer();");
5281:                                    lWriter
5282:                                            .println("                lOrderByClauseBuffer.append(lReferenceTableAlias);");
5283:                                    lWriter
5284:                                            .println("                lOrderByClauseBuffer.append(\"."
5285:                                                    + lReferenceTableWeightColumnName
5286:                                                    + "\");");
5287:                                    lWriter
5288:                                            .println("                lOrderByClauseBuffer.append(pOrderingDetails.Direction.equals(STOrderingDetails.DIRECTION_ASCENDING) ? \" ASC\" : \" DESC\");");
5289:                                    lWriter
5290:                                            .println("                lClauses.OrderByClause = lOrderByClauseBuffer.toString();");
5291:                                } else {
5292:                                    // We only need simple Order By clause		
5293:                                    lWriter
5294:                                            .println("                StringBuffer lOrderByClauseBuffer = new StringBuffer();");
5295:                                    lWriter
5296:                                            .println("                lOrderByClauseBuffer.append(lToTableAlias);");
5297:                                    lWriter
5298:                                            .println("                lOrderByClauseBuffer.append(\"."
5299:                                                    + lAttributeColumnName
5300:                                                    + "\");");
5301:                                    lWriter
5302:                                            .println("                lOrderByClauseBuffer.append(pOrderingDetails.Direction.equals(STOrderingDetails.DIRECTION_ASCENDING) ? \" ASC\" : \" DESC\");");
5303:                                    lWriter
5304:                                            .println("                lClauses.OrderByClause = lOrderByClauseBuffer.toString();");
5305:                                }
5306:                                lWriter
5307:                                        .println("                return lClauses;");
5308:                                lWriter.println("            }");
5309:                                lWriter.println("        });");
5310:                            }
5311:                        }
5312:                    }
5313:                    lWriter.println("    }");
5314:
5315:                    lWriter.println();
5316:                    // This is one of the most important methods used to build all parts of the sql statement
5317:                    // it is reentrant and is sometimes called recursively
5318:                    lWriter
5319:                            .println("    /** This method returns a structure containing parts of the sql statement to be executed */");
5320:                    lWriter
5321:                            .println("    public static SqlStatementParts getSqlStatementParts(STCollectionDetails[] pCollectionDetails, QueryContext pQueryContext) throws PSException");
5322:                    lWriter.println("    {");
5323:                    lWriter
5324:                            .println("        SqlStatementParts lParts = new SqlStatementParts();");
5325:                    // Check if we can return immediately with all inclusive collection
5326:                    lWriter
5327:                            .println("        if (pCollectionDetails == null || pCollectionDetails.length == 0)");
5328:                    lWriter.println("        {");
5329:                    lWriter
5330:                            .println("            lParts.setNumberOfTablesInFromClause(pQueryContext.getNumberOfTablesInFromClause());");
5331:                    lWriter
5332:                            .println("            lParts.mFromClause = pQueryContext.getFromClause();");
5333:                    lWriter.println("            return lParts;");
5334:                    lWriter.println("        }");
5335:                    // Ordering is only necessary for the QUERYTYPE_GETALLRECORDS and QUERYTYPE_GETALLRECORDIDS at the top level
5336:                    // or at subquery level, but only if subset is involved. The rationale is that if no subset is involved than 
5337:                    // no one really cares about the order of keys simply because all of them are to be returned 
5338:                    lWriter
5339:                            .println("        String lTableName = pQueryContext.getCurrentToTableName();");
5340:                    lWriter
5341:                            .println("        String lTableAlias = pQueryContext.getCurrentToTableAlias();");
5342:                    lWriter
5343:                            .println("        String lTableInstanceIdColumnName = pQueryContext.getCurrentToTableInstanceIdColumnName();");
5344:                    lWriter.println("        String[] lColumnNames = null;");
5345:                    lWriter
5346:                            .println("        QueryContext.QueryType lQueryType = pQueryContext.getType();");
5347:                    // Build "what" clause depending on what type of query we dealing with
5348:                    lWriter
5349:                            .println("        if (lQueryType.equals(QueryContext.QueryType.QUERYTYPE_GETALLRECORDS))");
5350:                    lWriter.println("        {");
5351:                    // Only "light" table columns are included in the individual get
5352:                    lWriter
5353:                            .println("            lColumnNames = QueryContext.getEntityTableLightColumnNamesByTableName(pQueryContext.getCurrentToTableName());");
5354:                    lWriter
5355:                            .println("            for (int i = 0; i < lColumnNames.length; i++)");
5356:                    lWriter.println("            {");
5357:                    lWriter
5358:                            .println("                StringBuffer lBuffer = new StringBuffer(lTableAlias);");
5359:                    lWriter.println("                lBuffer.append(\".\");");
5360:                    lWriter
5361:                            .println("                lBuffer.append(lColumnNames[i]);");
5362:                    lWriter
5363:                            .println("                lParts.appendWhatClauseElement(lBuffer.toString());");
5364:                    lWriter.println("            }");
5365:                    lWriter.println("        }");
5366:                    lWriter.println("        else");
5367:                    lWriter
5368:                            .println("        if (lQueryType.equals(QueryContext.QueryType.QUERYTYPE_GETSINGLERECORD))");
5369:                    lWriter.println("        {");
5370:                    // All table columns are included in the individual get
5371:                    lWriter
5372:                            .println("            lColumnNames = QueryContext.getEntityTableAllColumnNamesByTableName(pQueryContext.getCurrentToTableName());");
5373:                    lWriter
5374:                            .println("            for (int i = 0; i < lColumnNames.length; i++)");
5375:                    lWriter.println("            {");
5376:                    lWriter
5377:                            .println("                StringBuffer lBuffer = new StringBuffer(lTableAlias);");
5378:                    lWriter.println("                lBuffer.append(\".\");");
5379:                    lWriter
5380:                            .println("                lBuffer.append(lColumnNames[i]);");
5381:                    lWriter
5382:                            .println("                lParts.appendWhatClauseElement(lBuffer.toString());");
5383:                    lWriter.println("            }");
5384:                    lWriter.println("        }");
5385:                    lWriter.println("        else");
5386:                    lWriter
5387:                            .println("        if (lQueryType.equals(QueryContext.QueryType.QUERYTYPE_GETALLRECORDIDS) || lQueryType.equals(QueryContext.QueryType.QUERYTYPE_COUNTRECORDS))");
5388:                    lWriter.println("        {");
5389:                    // Only instance id table column is included in the get instance ids or get count
5390:                    lWriter
5391:                            .println("            lColumnNames = new String[] { lTableInstanceIdColumnName };");
5392:                    lWriter
5393:                            .println("            StringBuffer lBuffer = new StringBuffer(lTableAlias);");
5394:                    lWriter.println("            lBuffer.append(\".\");");
5395:                    lWriter
5396:                            .println("            lBuffer.append(lColumnNames[0]);");
5397:                    lWriter
5398:                            .println("            lParts.appendWhatClauseElement(lBuffer.toString());");
5399:                    lWriter.println("        }");
5400:                    lWriter.println("        else");
5401:                    lWriter
5402:                            .println("            throw new PSUnexpectedProgramConditionException(\"Unsupported QueryType : '\" + lQueryType + \"'\");");
5403:                    lWriter
5404:                            .println("        STCollectionDetails lTopCollectionDetails = pCollectionDetails[pCollectionDetails.length-1];");
5405:                    lWriter
5406:                            .println("        boolean lNeedToIncludeOrdering = lTopCollectionDetails != null && lTopCollectionDetails.Sorters != null;");
5407:                    lWriter
5408:                            .println("        StringBuffer lSqlWhereClause = null;");
5409:                    lWriter
5410:                            .println("        StringBuffer lSqlOrderByClause = null;");
5411:                    // Now work on subset if we have established that it is necessary
5412:                    lWriter
5413:                            .println("        if (lTopCollectionDetails.SetOperationName != null && lTopCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_SUBSET) &&");
5414:                    lWriter
5415:                            .println("            lTopCollectionDetails.FirstSetDetails != null && lTopCollectionDetails.FirstSetDetails.length > 0)");
5416:                    lWriter.println("        {");
5417:                    // Check the approach we need to take
5418:                    if (getDataBaseMetaData()
5419:                            .suggestSubsetSyntaxType()
5420:                            .equals(
5421:                                    DataBaseMetaData.SubsetSyntaxType.ROWNUM_PSEUDOCOLUMN)) {
5422:                        // This is  the Oracle style approach where subquery needs to be created with ROWNUM pseudocolumn  
5423:                        // Allocate distinct alias for the select statement , which will appear in the from clause as a dynamic table
5424:                        lWriter
5425:                                .println("            String lDynamicTableAlias = pQueryContext.takeTable(lTableName);");
5426:                        lWriter
5427:                                .println("            StringBuffer lSqlFromClause = new StringBuffer();");
5428:                        lWriter
5429:                                .println("            lSqlFromClause.append(\"( \");");
5430:                        lWriter.println("            {");
5431:                        lWriter
5432:                                .println("                QueryContext lSubqueryQueryContext = pQueryContext.openSubquery(pQueryContext.getType(),lTableName);");
5433:                        lWriter
5434:                                .println("                String lSubqueryQueryTableAlias = lSubqueryQueryContext.getCurrentToTableAlias();");
5435:                        lWriter
5436:                                .println("                lSqlFromClause.append(\"SELECT ROWNUM RN, \");");
5437:                        lWriter
5438:                                .println("                lSqlFromClause.append(lSubqueryQueryTableAlias);");
5439:                        lWriter
5440:                                .println("                lSqlFromClause.append(\".\");");
5441:                        lWriter
5442:                                .println("                lSqlFromClause.append(lTableInstanceIdColumnName);");
5443:                        lWriter
5444:                                .println("                lSqlFromClause.append(\" FROM (\");");
5445:                        lWriter.println("                {");
5446:                        lWriter
5447:                                .println("                    QueryContext lSubSubqueryQueryContext = lSubqueryQueryContext.openSubquery(QueryContext.QueryType.QUERYTYPE_GETALLRECORDIDS,lTableName);");
5448:                        lWriter
5449:                                .println("                    String lSubSubqueryQueryTableAlias = lSubSubqueryQueryContext.getCurrentToTableAlias();");
5450:                        // Make a recursive call to this method and populate inner query this time ignore subsets, but not the ordering
5451:                        lWriter
5452:                                .println("                    SqlStatementParts lInnerStatementParts = getSqlStatementParts(lTopCollectionDetails.FirstSetDetails, lSubSubqueryQueryContext);");
5453:                        lWriter
5454:                                .println("                    lSqlFromClause.append(\"SELECT \");");
5455:                        lWriter
5456:                                .println("                    lSqlFromClause.append(lInnerStatementParts.getWhatClause());");
5457:                        lWriter
5458:                                .println("                    if (lInnerStatementParts.mFromClause != null && lInnerStatementParts.mFromClause.length() > 0)");
5459:                        lWriter.println("                    {");
5460:                        lWriter
5461:                                .println("                        lSqlFromClause.append(\" FROM \");");
5462:                        lWriter
5463:                                .println("                        lSqlFromClause.append(lInnerStatementParts.mFromClause);");
5464:                        lWriter.println("                    }");
5465:                        lWriter
5466:                                .println("                    if (lInnerStatementParts.mWhereClause != null && lInnerStatementParts.mWhereClause.length() > 0)");
5467:                        lWriter.println("                    {");
5468:                        lWriter
5469:                                .println("                        lSqlFromClause.append(\" WHERE \");");
5470:                        lWriter
5471:                                .println("                        lSqlFromClause.append(lInnerStatementParts.mWhereClause);");
5472:                        lWriter.println("                    }");
5473:                        // When paging - there is a need to always order by somethig unique, in order for a sequence
5474:                        // to be reproduceable when the next page is taken a page. If we will not use the ordering
5475:                        // than the order of the records is not guaranteed and therefore the paging may not work correctly
5476:                        // For now only put the artificial ordering in if there is no custom order specified
5477:                        // TODO: Analysing whether application is already ordering by unique fields (eg. all elements of the primary key are present) and put this additional ordering at the end if necessary (ie. still not unique).
5478:                        lWriter
5479:                                .println("                    lSqlFromClause.append(\" ORDER BY \");");
5480:                        lWriter
5481:                                .println("                    if (lInnerStatementParts.mOrderByClause != null && lInnerStatementParts.mOrderByClause.length() > 0)");
5482:                        lWriter.println("                    {");
5483:                        lWriter
5484:                                .println("                        lSqlFromClause.append(lInnerStatementParts.mOrderByClause);");
5485:                        lWriter
5486:                                .println("                        lSqlFromClause.append(\",\");");
5487:                        lWriter.println("                    }");
5488:                        lWriter
5489:                                .println("                    lSqlFromClause.append(lSubSubqueryQueryTableAlias);");
5490:                        lWriter
5491:                                .println("                    lSqlFromClause.append(\".\");");
5492:                        lWriter
5493:                                .println("                    lSqlFromClause.append(lTableInstanceIdColumnName);");
5494:                        lWriter
5495:                                .println("                    lSqlFromClause.append(\" ASC\");");
5496:                        // Close subquery and go up the chain
5497:                        lWriter
5498:                                .println("                    lSubqueryQueryContext.closeSubquery(lSubSubqueryQueryContext);");
5499:                        lWriter.println("                }");
5500:                        lWriter
5501:                                .println("                lSqlFromClause.append(\") \");");
5502:                        lWriter
5503:                                .println("                lSqlFromClause.append(lSubqueryQueryTableAlias);");
5504:                        lWriter
5505:                                .println("                pQueryContext.closeSubquery(lSubqueryQueryContext);");
5506:                        lWriter.println("            }");
5507:                        lWriter
5508:                                .println("            lSqlFromClause.append(\") \");");
5509:                        // Save this subquery as part of from clause
5510:                        lWriter
5511:                                .println("            pQueryContext.setTableNameOverride(lDynamicTableAlias,lSqlFromClause.toString());");
5512:                        // Work on where and orderby clauses
5513:                        lWriter
5514:                                .println("            if (lSqlWhereClause == null)");
5515:                        lWriter
5516:                                .println("                lSqlWhereClause = new StringBuffer(\"(\");");
5517:                        lWriter.println("            else");
5518:                        lWriter
5519:                                .println("                lSqlWhereClause.append(\" AND (\");");
5520:                        lWriter
5521:                                .println("            lSqlWhereClause.append(lDynamicTableAlias);");
5522:                        lWriter
5523:                                .println("            lSqlWhereClause.append(\".RN > ? AND \");");
5524:                        lWriter
5525:                                .println("            lSqlWhereClause.append(lDynamicTableAlias);");
5526:                        lWriter
5527:                                .println("            lSqlWhereClause.append(\".RN <= (? + ?) AND \");");
5528:                        lWriter
5529:                                .println("            lSqlWhereClause.append(lDynamicTableAlias);");
5530:                        lWriter
5531:                                .println("            lSqlWhereClause.append(\".\");");
5532:                        lWriter
5533:                                .println("            lSqlWhereClause.append(lTableInstanceIdColumnName);");
5534:                        lWriter
5535:                                .println("            lSqlWhereClause.append(\" = \");");
5536:                        lWriter
5537:                                .println("            lSqlWhereClause.append(lTableAlias);");
5538:                        lWriter
5539:                                .println("            lSqlWhereClause.append(\".\");");
5540:                        lWriter
5541:                                .println("            lSqlWhereClause.append(lTableInstanceIdColumnName);");
5542:                        lWriter
5543:                                .println("            lSqlWhereClause.append(\")\");");
5544:                        // When paging - there is a need to always order by somethig unique, in order for a sequence
5545:                        // to be reproduceable when the next page is taken a page. If we will not use the ordering
5546:                        // than the order of the records is not guaranteed and therefore the paging may not work correctly
5547:                        // TODO: Some advantage may be gained by analysing whether application is already ordering by unique fields (eg. all elements of the primary key are present) and drop this additional ordering.
5548:                        lWriter
5549:                                .println("            if (lSqlOrderByClause == null)");
5550:                        lWriter
5551:                                .println("                lSqlOrderByClause = new StringBuffer();");
5552:                        lWriter.println("            else");
5553:                        lWriter
5554:                                .println("                lSqlOrderByClause.append(\",\");");
5555:                        // Insert possible application ordering instructions
5556:                        lWriter
5557:                                .println("            STCollectionDetails lTopSubsetCollectionDetails = lTopCollectionDetails.FirstSetDetails[lTopCollectionDetails.FirstSetDetails.length - 1];");
5558:                        lWriter
5559:                                .println("            if (lTopSubsetCollectionDetails.Sorters != null)");
5560:                        lWriter.println("            {");
5561:                        lWriter
5562:                                .println("                OrderingDetailsInterpreter.SqlClauses lOrderingSqlClauses =  getOrderingClauses(lTopSubsetCollectionDetails, pQueryContext);");
5563:                        lWriter
5564:                                .println("                lParts.appendWhatClauseElement(lOrderingSqlClauses.WhatClause);");
5565:                        lWriter
5566:                                .println("                if (lOrderingSqlClauses.WhereClause != null && lOrderingSqlClauses.WhereClause.length() > 0)");
5567:                        lWriter.println("                {");
5568:                        lWriter
5569:                                .println("                    lSqlWhereClause.append(\" AND (\");");
5570:                        lWriter
5571:                                .println("                    lSqlWhereClause.append(lOrderingSqlClauses.WhereClause);");
5572:                        lWriter
5573:                                .println("                    lSqlWhereClause.append(\")\");");
5574:                        lWriter.println("                }");
5575:                        lWriter
5576:                                .println("                if (lOrderingSqlClauses.OrderByClause != null && lOrderingSqlClauses.OrderByClause.length() > 0)");
5577:                        lWriter.println("                {");
5578:                        lWriter
5579:                                .println("                    lSqlOrderByClause.append(lOrderingSqlClauses.OrderByClause);");
5580:                        lWriter
5581:                                .println("                    lSqlOrderByClause.append(\",\");");
5582:                        lWriter.println("                }");
5583:                        lWriter.println("            }");
5584:                        lWriter
5585:                                .println("            lSqlOrderByClause.append(lTableAlias);");
5586:                        lWriter
5587:                                .println("            lSqlOrderByClause.append(\".\");");
5588:                        lWriter
5589:                                .println("            lSqlOrderByClause.append(lTableInstanceIdColumnName);");
5590:                        lWriter
5591:                                .println("            lSqlOrderByClause.append(\" ASC\");");
5592:
5593:                        // Old proven approach
5594:                        //				lWriter.println("            StringBuffer lSqlFromClause = new StringBuffer();");
5595:                        //				lWriter.println("            lSqlFromClause.append(\"( \");");
5596:                        //				lWriter.println("            {");
5597:                        //				lWriter.println("                QueryContext lSubqueryQueryContext = pQueryContext.openSubquery(pQueryContext.getType(),lTableName);");
5598:                        //				lWriter.println("                String lSubqueryQueryTableAlias = lSubqueryQueryContext.getCurrentToTableAlias();");
5599:                        //			    lWriter.println("                lSqlFromClause.append(\"SELECT ROWNUM RN \");");
5600:                        //	            lWriter.println("                for (int i = 0; i < lColumnNames.length; i++)");
5601:                        //	 		    lWriter.println("                {");
5602:                        //			    lWriter.println("                    lSqlFromClause.append(\",\");");
5603:                        //			    lWriter.println("                    lSqlFromClause.append(lSubqueryQueryTableAlias);");
5604:                        //			    lWriter.println("                    lSqlFromClause.append(\".\");");
5605:                        //			    lWriter.println("                    lSqlFromClause.append(lColumnNames[i]);");
5606:                        //			    lWriter.println("                }");
5607:                        //			    lWriter.println("                lSqlFromClause.append(\" FROM (\");");
5608:                        //				lWriter.println("                {");
5609:                        //				lWriter.println("                    QueryContext lSubSubqueryQueryContext = lSubqueryQueryContext.openSubquery(pQueryContext.getType(),lTableName);");
5610:                        //				lWriter.println("                    String lSubSubqueryQueryTableAlias = lSubSubqueryQueryContext.getCurrentToTableAlias();");
5611:                        //	            // Make a recursive call to this method and populate inner query this time ignore subsets, but not the ordering
5612:                        //				lWriter.println("                    SqlStatementParts lInnerStatementParts = getSqlStatementParts(lTopCollectionDetails.FirstSetDetails, lSubSubqueryQueryContext);");
5613:                        //				lWriter.println("                    lSqlFromClause.append(\"SELECT DISTINCT \");");
5614:                        //	 			lWriter.println("                    lSqlFromClause.append(lInnerStatementParts.getWhatClause());");
5615:                        //				lWriter.println("                    if (lInnerStatementParts.mFromClause != null && lInnerStatementParts.mFromClause.length() > 0)");
5616:                        //				lWriter.println("                    {");
5617:                        //				lWriter.println("                        lSqlFromClause.append(\" FROM \");");
5618:                        //				lWriter.println("                        lSqlFromClause.append(lInnerStatementParts.mFromClause);");
5619:                        //				lWriter.println("                    }");
5620:                        //				lWriter.println("                    if (lInnerStatementParts.mWhereClause != null && lInnerStatementParts.mWhereClause.length() > 0)");
5621:                        //				lWriter.println("                    {");
5622:                        //				lWriter.println("                        lSqlFromClause.append(\" WHERE \");");
5623:                        //				lWriter.println("                        lSqlFromClause.append(lInnerStatementParts.mWhereClause);");
5624:                        //				lWriter.println("                    }");
5625:                        //				// When paging - there is a need to always order by somethig unique, in order for a sequence
5626:                        //				// to be reproduceable when the next page is taken a page. If we will not use the ordering
5627:                        //				// than the order of the records is not guaranteed and therefore the paging may not work correctly
5628:                        //				// For now only put the artificial ordering in if there is no custom order specified
5629:                        //				// TODO: Analysing whether application is already ordering by unique fields (eg. all elements of the primary key are present) and put this additional ordering at the end if necessary (ie. still not unique).
5630:                        //				lWriter.println("                    lSqlFromClause.append(\" ORDER BY \");");
5631:                        //				lWriter.println("                    if (lInnerStatementParts.mOrderByClause != null && lInnerStatementParts.mOrderByClause.length() > 0)");
5632:                        //				lWriter.println("                    {");
5633:                        //				lWriter.println("                        lSqlFromClause.append(lInnerStatementParts.mOrderByClause);");
5634:                        //				lWriter.println("                    }");
5635:                        //				lWriter.println("                    else");
5636:                        //				lWriter.println("                    {");
5637:                        //				lWriter.println("                        lSqlFromClause.append(lSubSubqueryQueryTableAlias);");
5638:                        //				lWriter.println("                        lSqlFromClause.append(\".\");");
5639:                        //				lWriter.println("                        lSqlFromClause.append(lTableInstanceIdColumnName);");
5640:                        //				lWriter.println("                        lSqlFromClause.append(\" ASC\");");
5641:                        //				lWriter.println("                    }");
5642:                        //				// Close subquery and go up the chain
5643:                        //				lWriter.println("                    lSubqueryQueryContext.closeSubquery(lSubSubqueryQueryContext);");
5644:                        //				lWriter.println("                }");
5645:                        //			    lWriter.println("                lSqlFromClause.append(\") \");");
5646:                        //				lWriter.println("                lSqlFromClause.append(lSubqueryQueryTableAlias);");
5647:                        //				lWriter.println("                pQueryContext.closeSubquery(lSubqueryQueryContext);");
5648:                        //				lWriter.println("            }");
5649:                        //				lWriter.println("            lSqlFromClause.append(\") \");");
5650:                        //				// Save this subquery as part of from clause
5651:                        //				lWriter.println("            pQueryContext.setTableNameOverride(lTableAlias,lSqlFromClause.toString());");
5652:                        //				lWriter.println("            if (lSqlWhereClause == null)");
5653:                        //				lWriter.println("                lSqlWhereClause = new StringBuffer(\"(\");");
5654:                        //				lWriter.println("            else");
5655:                        //				lWriter.println("                lSqlWhereClause.append(\" AND (\");");
5656:                        //				lWriter.println("            lSqlWhereClause.append(lTableAlias);");
5657:                        //				lWriter.println("            lSqlWhereClause.append(\".RN > ? AND \");");
5658:                        //				lWriter.println("            lSqlWhereClause.append(lTableAlias);");
5659:                        //				lWriter.println("            lSqlWhereClause.append(\".RN <= (? + ?)\");");
5660:                        //				lWriter.println("            lSqlWhereClause.append(\")\");");
5661:
5662:                    } else if (getDataBaseMetaData()
5663:                            .suggestSubsetSyntaxType()
5664:                            .equals(
5665:                                    DataBaseMetaData.SubsetSyntaxType.LIMIT_KEYWORD)) {
5666:                        // This is the MySQL style approach where subquery conditions will just be built in the where clause and LIMIT x,y keyword must be appended to the query
5667:                        // If this element contains any filters or sorters - than the subset must be realised with the 'IN' subquery
5668:                        // otherwise we can use 'flat query'
5669:                        lWriter
5670:                                .println("            if (lTopCollectionDetails.Sorters != null || lTopCollectionDetails.Filters != null)");
5671:                        lWriter.println("            {");
5672:                        // Subquery style
5673:                        // Because this level has sorters or filters - we have to push the building of the subset collection
5674:                        // in the subquery. This is because this level's filters and sorters should be applied to the subset
5675:                        lWriter
5676:                                .println("                if (lSqlWhereClause == null)");
5677:                        lWriter
5678:                                .println("                    lSqlWhereClause = new StringBuffer(\"(\");");
5679:                        lWriter.println("                else");
5680:                        lWriter
5681:                                .println("                    lSqlWhereClause.append(\" AND (\");");
5682:                        lWriter
5683:                                .println("                lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
5684:                        lWriter
5685:                                .println("                lSqlWhereClause.append(\".\");");
5686:                        lWriter
5687:                                .println("                lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
5688:                        lWriter
5689:                                .println("                lSqlWhereClause.append(\" IN (\");");
5690:                        lWriter
5691:                                .println("                lSqlWhereClause.append(buildSubquery(lTopCollectionDetails.FirstSetDetails, pQueryContext));");
5692:                        lWriter
5693:                                .println("                lSqlWhereClause.append(\"))\");");
5694:                        lWriter.println("            }");
5695:                        lWriter.println("            else");
5696:                        lWriter.println("            {");
5697:                        // Query style
5698:                        // Because this level does not have sorters or filters - we can bring the building of the subset collection
5699:                        // in to this level. This is because this level will not appply any additional transformation to the subset
5700:                        lWriter
5701:                                .println("                lParts.mLimitClause = \"?,?\";");
5702:                        lWriter
5703:                                .println("                SqlStatementParts lInnerStatementParts = getSqlStatementParts(lTopCollectionDetails.FirstSetDetails, pQueryContext);");
5704:                        lWriter
5705:                                .println("                if (lInnerStatementParts.mWhereClause != null && lInnerStatementParts.mWhereClause.length() > 0)");
5706:                        lWriter.println("                {");
5707:                        lWriter
5708:                                .println("                    if (lSqlWhereClause == null)");
5709:                        lWriter
5710:                                .println("                        lSqlWhereClause = new StringBuffer(\"(\");");
5711:                        lWriter.println("                    else");
5712:                        lWriter
5713:                                .println("                        lSqlWhereClause.append(\" AND (\");");
5714:                        lWriter
5715:                                .println("                    lSqlWhereClause.append(lInnerStatementParts.mWhereClause);");
5716:                        lWriter
5717:                                .println("                    lSqlWhereClause.append(\")\");");
5718:                        lWriter.println("                }");
5719:                        // When paging - there is a need to always order by somethig unique, in order for a sequence
5720:                        // to be reproduceable when the next page is taken a page. If we will not use the ordering
5721:                        // than the order of the records is not guaranteed and therefore the paging may not work correctly
5722:                        // TODO: Some advantage may be gained by analysing whether application is already ordering by unique fields (eg. all elements of the primary key are present) and drop this additional ordering.
5723:                        lWriter
5724:                                .println("                if (lSqlOrderByClause == null)");
5725:                        lWriter
5726:                                .println("                    lSqlOrderByClause = new StringBuffer();");
5727:                        lWriter.println("                else");
5728:                        lWriter
5729:                                .println("                    lSqlOrderByClause.append(\",\");");
5730:                        lWriter
5731:                                .println("                if (lInnerStatementParts.mOrderByClause != null && lInnerStatementParts.mOrderByClause.length() > 0)");
5732:                        lWriter.println("                {");
5733:                        lWriter
5734:                                .println("                    lSqlOrderByClause.append(lInnerStatementParts.mOrderByClause);");
5735:                        lWriter
5736:                                .println("                    lSqlOrderByClause.append(\",\");");
5737:                        lWriter.println("                }");
5738:                        lWriter
5739:                                .println("                lSqlOrderByClause.append(lTableAlias);");
5740:                        lWriter
5741:                                .println("                lSqlOrderByClause.append(\".\");");
5742:                        lWriter
5743:                                .println("                lSqlOrderByClause.append(lTableInstanceIdColumnName);");
5744:                        lWriter
5745:                                .println("                lSqlOrderByClause.append(\" ASC\");");
5746:                        lWriter.println("            }");
5747:                    } else
5748:                        throw new BSUnexpectedProgramConditionException(
5749:                                "DataBaseMetaData does not have returned unsupported SubsetSyntaxType:"
5750:                                        + getDataBaseMetaData()
5751:                                                .suggestSubsetSyntaxType());
5752:                    lWriter.println("        }");
5753:                    // All cases where no subsets are required will fall here and will be processed here
5754:                    // Process ordering if required
5755:                    lWriter
5756:                            .println("        if (lTopCollectionDetails.Sorters != null)");
5757:                    lWriter.println("        {");
5758:                    lWriter
5759:                            .println("            OrderingDetailsInterpreter.SqlClauses lOrderingSqlClauses =  getOrderingClauses(lTopCollectionDetails, pQueryContext);");
5760:                    lWriter
5761:                            .println("            lParts.appendWhatClauseElement(lOrderingSqlClauses.WhatClause);");
5762:                    lWriter
5763:                            .println("            if (lOrderingSqlClauses.WhereClause != null && lOrderingSqlClauses.WhereClause.length() > 0)");
5764:                    lWriter.println("            {");
5765:                    lWriter
5766:                            .println("                if (lSqlWhereClause == null)");
5767:                    lWriter
5768:                            .println("                    lSqlWhereClause = new StringBuffer(\"(\");");
5769:                    lWriter.println("                else");
5770:                    lWriter
5771:                            .println("                    lSqlWhereClause.append(\" AND (\");");
5772:                    lWriter
5773:                            .println("                lSqlWhereClause.append(lOrderingSqlClauses.WhereClause);");
5774:                    lWriter
5775:                            .println("                lSqlWhereClause.append(\")\");");
5776:                    lWriter.println("            }");
5777:                    lWriter
5778:                            .println("            if (lOrderingSqlClauses.OrderByClause != null && lOrderingSqlClauses.OrderByClause.length() > 0)");
5779:                    lWriter.println("            {");
5780:                    lWriter
5781:                            .println("                if (lSqlOrderByClause == null)");
5782:                    lWriter
5783:                            .println("                    lSqlOrderByClause = new StringBuffer();");
5784:                    lWriter.println("                else");
5785:                    lWriter
5786:                            .println("                    lSqlOrderByClause.append(\",\");");
5787:                    lWriter
5788:                            .println("                lSqlOrderByClause.append(lOrderingSqlClauses.OrderByClause);");
5789:                    lWriter.println("            }");
5790:                    lWriter.println("        }");
5791:                    // Process filtering
5792:                    lWriter
5793:                            .println("        String lFilteringWhereClause = getSqlWhereClause(pCollectionDetails, pQueryContext);");
5794:                    lWriter
5795:                            .println("        if (lFilteringWhereClause != null && lFilteringWhereClause.length() > 0)");
5796:                    lWriter.println("        {");
5797:                    lWriter.println("            if (lSqlWhereClause == null)");
5798:                    lWriter
5799:                            .println("                lSqlWhereClause = new StringBuffer(\"(\");");
5800:                    lWriter.println("            else");
5801:                    lWriter
5802:                            .println("                lSqlWhereClause.append(\" AND (\");");
5803:                    lWriter
5804:                            .println("            lSqlWhereClause.append(lFilteringWhereClause);");
5805:                    lWriter
5806:                            .println("            lSqlWhereClause.append(\")\");");
5807:                    lWriter.println("        }");
5808:                    // Now prepare result
5809:                    lWriter
5810:                            .println("        lParts.setNumberOfTablesInFromClause(pQueryContext.getNumberOfTablesInFromClause());");
5811:                    lWriter
5812:                            .println("        lParts.mFromClause = pQueryContext.getFromClause();");
5813:                    lWriter.println("        if (lSqlWhereClause != null)");
5814:                    lWriter
5815:                            .println("            lParts.mWhereClause = lSqlWhereClause.toString();");
5816:                    lWriter.println("        if (lSqlOrderByClause != null)");
5817:                    lWriter
5818:                            .println("            lParts.mOrderByClause = lSqlOrderByClause.toString();");
5819:                    lWriter.println("        return lParts;");
5820:                    lWriter.println("    }");
5821:
5822:                    // Helper method, used to set ordering clauses
5823:                    lWriter.println();
5824:                    lWriter
5825:                            .println("    private static OrderingDetailsInterpreter.SqlClauses getOrderingClauses(STCollectionDetails pCollectionDetail, QueryContext pQueryContext) throws PSException");
5826:                    lWriter.println("    {");
5827:                    lWriter
5828:                            .println("        StringBuffer lSqlWhatClause = null;");
5829:                    lWriter
5830:                            .println("        StringBuffer lSqlWhereClause = null;");
5831:                    lWriter
5832:                            .println("        StringBuffer lSqlOrderByClause = null;");
5833:                    lWriter
5834:                            .println("        if (pCollectionDetail.Sorters != null)");
5835:                    lWriter.println("        {");
5836:                    // Sorters are iterated normally - from first to last
5837:                    lWriter
5838:                            .println("            for (int i = 0; i < pCollectionDetail.Sorters.length; i++)");
5839:                    lWriter.println("            {");
5840:                    lWriter
5841:                            .println("                STOrderingDetails lOrderingDetails = pCollectionDetail.Sorters[i];");
5842:                    lWriter
5843:                            .println("                OrderingDetailsInterpreter lInterpreter = getMandatoryInterpreter(lOrderingDetails);");
5844:                    lWriter
5845:                            .println("                OrderingDetailsInterpreter.SqlClauses lOrderingSqlClauses = lInterpreter.getSqlClauses(lOrderingDetails,pQueryContext);");
5846:                    lWriter
5847:                            .println("                if (lOrderingSqlClauses.WhatClause != null)");
5848:                    lWriter.println("                {");
5849:                    lWriter
5850:                            .println("                    if (lSqlWhatClause == null)");
5851:                    lWriter
5852:                            .println("                        lSqlWhatClause = new StringBuffer();");
5853:                    lWriter.println("                    else");
5854:                    lWriter
5855:                            .println("                        lSqlWhatClause.append(\",\");");
5856:                    lWriter
5857:                            .println("                    lSqlWhatClause.append(lOrderingSqlClauses.WhatClause);");
5858:                    lWriter.println("                }");
5859:                    lWriter
5860:                            .println("                if (lOrderingSqlClauses.WhereClause != null)");
5861:                    lWriter.println("                {");
5862:                    lWriter
5863:                            .println("                    if (lSqlWhereClause == null)");
5864:                    lWriter
5865:                            .println("                        lSqlWhereClause = new StringBuffer(\"(\");");
5866:                    lWriter.println("                    else");
5867:                    lWriter
5868:                            .println("                        lSqlWhereClause.append(\" AND (\");");
5869:                    lWriter
5870:                            .println("                    lSqlWhereClause.append(lOrderingSqlClauses.WhereClause);");
5871:                    lWriter
5872:                            .println("                    lSqlWhereClause.append(\")\");");
5873:                    lWriter.println("                }");
5874:                    lWriter
5875:                            .println("                if (lOrderingSqlClauses.OrderByClause  != null)");
5876:                    lWriter.println("                {");
5877:                    lWriter
5878:                            .println("                    if (lSqlOrderByClause == null)");
5879:                    lWriter
5880:                            .println("                        lSqlOrderByClause = new StringBuffer();");
5881:                    lWriter.println("                    else");
5882:                    lWriter
5883:                            .println("                        lSqlOrderByClause.append(\",\");");
5884:                    lWriter
5885:                            .println("                    lSqlOrderByClause.append(lOrderingSqlClauses.OrderByClause);");
5886:                    lWriter.println("                }");
5887:                    lWriter.println("            }");
5888:                    lWriter.println("        }");
5889:                    // Prepare the return
5890:                    lWriter
5891:                            .println("        OrderingDetailsInterpreter.SqlClauses lReturnSqlClauses = new OrderingDetailsInterpreter.SqlClauses();");
5892:                    lWriter.println("        if (lSqlWhatClause != null)");
5893:                    lWriter
5894:                            .println("          lReturnSqlClauses.WhatClause = lSqlWhatClause.toString();");
5895:                    lWriter.println("        if (lSqlWhereClause != null)");
5896:                    lWriter
5897:                            .println("          lReturnSqlClauses.WhereClause = lSqlWhereClause.toString();");
5898:                    lWriter.println("        if (lSqlOrderByClause != null)");
5899:                    lWriter
5900:                            .println("          lReturnSqlClauses.OrderByClause = lSqlOrderByClause.toString();");
5901:                    lWriter.println("        return lReturnSqlClauses;");
5902:                    lWriter.println("    }");
5903:
5904:                    // Helper method, can be called recursively on set of subselectors
5905:                    lWriter.println();
5906:                    lWriter
5907:                            .println("    private static String getSqlWhereClause(STCollectionDetails[] pCollectionDetails, QueryContext pQueryContext) throws PSException");
5908:                    lWriter.println("    {");
5909:                    // We will iterate through selectors and collect where and from clauses together
5910:                    lWriter
5911:                            .println("        StringBuffer lSqlWhereClause = new StringBuffer();");
5912:                    lWriter.println("        boolean lNeedAnd = false;");
5913:                    lWriter.println("        if (pCollectionDetails != null)");
5914:                    lWriter.println("        {");
5915:                    // We buld statement from the last selector to the first - kind of "working our way back" from the desired entity
5916:                    lWriter
5917:                            .println("            for (int i = (pCollectionDetails.length - 1); i >= 0; i--)");
5918:                    lWriter.println("            {");
5919:                    lWriter
5920:                            .println("                STCollectionDetails lCollectionDetails = pCollectionDetails[i];");
5921:                    // First work on filters
5922:                    lWriter
5923:                            .println("                if (lCollectionDetails.Filters != null)");
5924:                    lWriter.println("                {");
5925:                    lWriter
5926:                            .println("                    for (int j = (lCollectionDetails.Filters.length - 1); j >= 0; j--)");
5927:                    lWriter.println("                    {");
5928:                    lWriter
5929:                            .println("                        STFilteringDetails lFilteringDetails = lCollectionDetails.Filters[j];");
5930:                    lWriter
5931:                            .println("                        FilteringDetailsInterpreter lInterpreter = getMandatoryInterpreter(lFilteringDetails);");
5932:                    lWriter
5933:                            .println("                        String lSqlWhereClauseUnit = lInterpreter.getSqlWhereClause(lFilteringDetails, pQueryContext);");
5934:                    lWriter
5935:                            .println("                        if (lSqlWhereClauseUnit != null && lSqlWhereClauseUnit.length() > 0)");
5936:                    lWriter.println("                        {");
5937:                    lWriter
5938:                            .println("                            if (lNeedAnd)");
5939:                    lWriter
5940:                            .println("                                lSqlWhereClause.append(\" AND \");");
5941:                    lWriter.println("                            else");
5942:                    lWriter
5943:                            .println("                                lNeedAnd = true;");
5944:                    lWriter
5945:                            .println("                            lSqlWhereClause.append(\"( \");");
5946:                    lWriter
5947:                            .println("                            lSqlWhereClause.append(lSqlWhereClauseUnit);");
5948:                    lWriter
5949:                            .println("                            lSqlWhereClause.append(\" )\");");
5950:                    lWriter.println("                        }");
5951:                    lWriter.println("                    }");
5952:                    lWriter.println("                }");
5953:                    // Now work on this collection itself.
5954:                    // If the first element is a subset we need to ignore it because it does not go inside where
5955:                    lWriter
5956:                            .println("                if ((i == (pCollectionDetails.length - 1)) && lCollectionDetails != null && lCollectionDetails.SetOperationName != null && lCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_SUBSET))");
5957:                    lWriter.println("                    continue;");
5958:                    lWriter
5959:                            .println("                CollectionDetailsInterpreter lInterpreter = getMandatoryInterpreter(lCollectionDetails);");
5960:                    lWriter
5961:                            .println("                String lSqlWhereClauseUnit = lInterpreter.getSqlWhereClause(lCollectionDetails, pQueryContext);");
5962:                    lWriter
5963:                            .println("                if (lSqlWhereClauseUnit != null && lSqlWhereClauseUnit.length() > 0)");
5964:                    lWriter.println("                {");
5965:                    lWriter.println("                    if (lNeedAnd)");
5966:                    lWriter
5967:                            .println("                        lSqlWhereClause.append(\" AND \");");
5968:                    lWriter.println("                    else");
5969:                    lWriter.println("                        lNeedAnd = true;");
5970:                    lWriter
5971:                            .println("                    lSqlWhereClause.append(\"( \");");
5972:                    lWriter
5973:                            .println("                    lSqlWhereClause.append(lSqlWhereClauseUnit);");
5974:                    lWriter
5975:                            .println("                    lSqlWhereClause.append(\" )\");");
5976:                    lWriter.println("                }");
5977:                    lWriter.println("            }");
5978:                    lWriter.println("        }");
5979:                    lWriter
5980:                            .println("        return lSqlWhereClause.toString();");
5981:                    lWriter.println("    }");
5982:
5983:                    lWriter
5984:                            .println("    /** This method populates passed PreparedStatement with arguments from selectors */");
5985:                    lWriter
5986:                            .println("    public static int populatePreparedStatement(STCollectionDetails[] pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
5987:                    lWriter.println("    {");
5988:                    lWriter
5989:                            .println("        int lNextStartIndex = pStartIndex;");
5990:                    lWriter.println("        if (pCollectionDetails != null)");
5991:                    lWriter.println("        {");
5992:                    // We buld statement from the last selector to the first - kind of "working our way back" from the desired entity
5993:                    lWriter
5994:                            .println("            for (int i = (pCollectionDetails.length - 1); i >= 0; i--)");
5995:                    lWriter.println("            {");
5996:                    lWriter
5997:                            .println("                STCollectionDetails lCollectionDetails = pCollectionDetails[i];");
5998:                    // Various patterns depending on subset syntax type
5999:                    if (getDataBaseMetaData()
6000:                            .suggestSubsetSyntaxType()
6001:                            .equals(
6002:                                    DataBaseMetaData.SubsetSyntaxType.ROWNUM_PSEUDOCOLUMN)) {
6003:                        // This is  the Oracle style approach where subquery needs to be created with ROWNUM pseudocolumn  
6004:                        lWriter
6005:                                .println("                if (lCollectionDetails.SetOperationName != null && lCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_SUBSET))");
6006:                        lWriter.println("                {");
6007:                        // Work on subquery parameters first
6008:                        lWriter
6009:                                .println("                    CollectionDetailsInterpreter lStepInterpreter = getMandatoryInterpreter(lCollectionDetails);");
6010:                        lWriter
6011:                                .println("                    lNextStartIndex += lStepInterpreter.populatePreparedStatement(lCollectionDetails, pStatement, lNextStartIndex);");
6012:
6013:                        // Populate paging parameters		
6014:                        lWriter.println("                    try");
6015:                        lWriter.println("                    {");
6016:                        lWriter
6017:                                .println("                        if (sLogger.isDebugEnabled())");
6018:                        lWriter
6019:                                .println("                            sLogger.debug(\"Parameter \" + lNextStartIndex + \" value: \" + lCollectionDetails.ResultStartOffset);");
6020:                        lWriter
6021:                                .println("                        pStatement.setLong( lNextStartIndex++, TypesConvertor.getSqlValueFromCollectionOffset(("
6022:                                        + lCollectionOffsetDatatypeStylesheet
6023:                                                .getClassFullName()
6024:                                        + ")lCollectionDetails.ResultStartOffset));");
6025:
6026:                        lWriter
6027:                                .println("                        if (sLogger.isDebugEnabled())");
6028:                        lWriter
6029:                                .println("                            sLogger.debug(\"Parameter \" + lNextStartIndex + \" value: \" + lCollectionDetails.ResultMaximumSize);");
6030:                        lWriter
6031:                                .println("                        pStatement.setLong( lNextStartIndex++, TypesConvertor.getSqlValueFromSubsetSize(("
6032:                                        + lSubsetSizeDatatypeStylesheet
6033:                                                .getClassFullName()
6034:                                        + ")lCollectionDetails.ResultMaximumSize));");
6035:
6036:                        lWriter
6037:                                .println("                        if (sLogger.isDebugEnabled())");
6038:                        lWriter
6039:                                .println("                            sLogger.debug(\"Parameter \" + lNextStartIndex + \" value: \" + lCollectionDetails.ResultStartOffset);");
6040:                        lWriter
6041:                                .println("                        pStatement.setLong( lNextStartIndex++, TypesConvertor.getSqlValueFromCollectionOffset(("
6042:                                        + lCollectionOffsetDatatypeStylesheet
6043:                                                .getClassFullName()
6044:                                        + ")lCollectionDetails.ResultStartOffset));");
6045:                        lWriter.println("                    }");
6046:                        lWriter
6047:                                .println("                    catch(DataTypeInvalidOperationForEmptyInstanceException e)");
6048:                        lWriter.println("                    {");
6049:                        lWriter
6050:                                .println("                        throw new PSDatatypeOperationException(\"Unexpected empty instance\",e);");
6051:                        lWriter.println("                    }");
6052:                        lWriter
6053:                                .println("                    catch(DataTypeInvalidOperationForConcealedInstanceException e)");
6054:                        lWriter.println("                    {");
6055:                        lWriter
6056:                                .println("                        throw new PSDatatypeOperationException(\"Unexpected concealed instance\",e);");
6057:                        lWriter.println("                    }");
6058:                        lWriter
6059:                                .println("                    catch(java.sql.SQLException e)");
6060:                        lWriter.println("                    {");
6061:                        lWriter
6062:                                .println("                        throw new PSDataSourceOperationInvocationException(\"Error on populating subset prepared statement.\", e);");
6063:                        lWriter.println("                    }");
6064:                        // Work on filters
6065:                        lWriter
6066:                                .println("                    if (lCollectionDetails.Filters != null)");
6067:                        lWriter.println("                    {");
6068:                        lWriter
6069:                                .println("                        for (int j = (lCollectionDetails.Filters.length - 1); j >= 0; j--)");
6070:                        lWriter.println("                        {");
6071:                        lWriter
6072:                                .println("                            STFilteringDetails lFilteringDetails = lCollectionDetails.Filters[j];");
6073:                        lWriter
6074:                                .println("                            FilteringDetailsInterpreter lFilterInterpreter = getMandatoryInterpreter(lFilteringDetails);");
6075:                        lWriter
6076:                                .println("                            lNextStartIndex += lFilterInterpreter.populatePreparedStatement(lFilteringDetails, pStatement, lNextStartIndex);");
6077:                        lWriter.println("                        }");
6078:                        lWriter.println("                    }");
6079:                        lWriter.println("                }");
6080:                        lWriter.println("                else");
6081:                        lWriter.println("                {");
6082:                        // Work on filters
6083:                        lWriter
6084:                                .println("                    if (lCollectionDetails.Filters != null)");
6085:                        lWriter.println("                    {");
6086:                        lWriter
6087:                                .println("                        for (int j = (lCollectionDetails.Filters.length - 1); j >= 0; j--)");
6088:                        lWriter.println("                        {");
6089:                        lWriter
6090:                                .println("                            STFilteringDetails lFilteringDetails = lCollectionDetails.Filters[j];");
6091:                        lWriter
6092:                                .println("                            FilteringDetailsInterpreter lFilterInterpreter = getMandatoryInterpreter(lFilteringDetails);");
6093:                        lWriter
6094:                                .println("                            lNextStartIndex += lFilterInterpreter.populatePreparedStatement(lFilteringDetails, pStatement, lNextStartIndex);");
6095:                        lWriter.println("                        }");
6096:                        lWriter.println("                    }");
6097:                        // Work on interpreter
6098:                        lWriter
6099:                                .println("                    CollectionDetailsInterpreter lStepInterpreter = getMandatoryInterpreter(lCollectionDetails);");
6100:                        lWriter
6101:                                .println("                    lNextStartIndex += lStepInterpreter.populatePreparedStatement(lCollectionDetails, pStatement, lNextStartIndex);");
6102:                        lWriter.println("                }");
6103:                    } else if (getDataBaseMetaData()
6104:                            .suggestSubsetSyntaxType()
6105:                            .equals(
6106:                                    DataBaseMetaData.SubsetSyntaxType.LIMIT_KEYWORD)) {
6107:                        // This is the MySQL style approach where LIMIT x,y keyword must be appended to the query at the back
6108:
6109:                        // Work on filters
6110:                        lWriter
6111:                                .println("                if (lCollectionDetails.Filters != null)");
6112:                        lWriter.println("                {");
6113:                        lWriter
6114:                                .println("                    for (int j = (lCollectionDetails.Filters.length - 1); j >= 0; j--)");
6115:                        lWriter.println("                    {");
6116:                        lWriter
6117:                                .println("                        STFilteringDetails lFilteringDetails = lCollectionDetails.Filters[j];");
6118:                        lWriter
6119:                                .println("                        FilteringDetailsInterpreter lFilterInterpreter = getMandatoryInterpreter(lFilteringDetails);");
6120:                        lWriter
6121:                                .println("                        lNextStartIndex += lFilterInterpreter.populatePreparedStatement(lFilteringDetails, pStatement, lNextStartIndex);");
6122:                        lWriter.println("                    }");
6123:                        lWriter.println("                }");
6124:                        // Work on interpreter
6125:                        lWriter
6126:                                .println("                CollectionDetailsInterpreter lStepInterpreter = getMandatoryInterpreter(lCollectionDetails);");
6127:                        lWriter
6128:                                .println("                lNextStartIndex += lStepInterpreter.populatePreparedStatement(lCollectionDetails, pStatement, lNextStartIndex);");
6129:
6130:                        lWriter
6131:                                .println("                if (lCollectionDetails.SetOperationName != null && lCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_SUBSET))");
6132:                        lWriter.println("                {");
6133:                        // Populate paging parameters		
6134:                        lWriter.println("                    try");
6135:                        lWriter.println("                    {");
6136:                        lWriter
6137:                                .println("                        if (sLogger.isDebugEnabled())");
6138:                        lWriter
6139:                                .println("                            sLogger.debug(\"Parameter \" + lNextStartIndex + \" value: \" + lCollectionDetails.ResultStartOffset);");
6140:                        lWriter
6141:                                .println("                        pStatement.setLong( lNextStartIndex++, TypesConvertor.getSqlValueFromCollectionOffset(("
6142:                                        + lCollectionOffsetDatatypeStylesheet
6143:                                                .getClassFullName()
6144:                                        + ")lCollectionDetails.ResultStartOffset));");
6145:
6146:                        lWriter
6147:                                .println("                        if (sLogger.isDebugEnabled())");
6148:                        lWriter
6149:                                .println("                            sLogger.debug(\"Parameter \" + lNextStartIndex + \" value: \" + lCollectionDetails.ResultMaximumSize);");
6150:                        lWriter
6151:                                .println("                        pStatement.setLong( lNextStartIndex++, TypesConvertor.getSqlValueFromSubsetSize(("
6152:                                        + lSubsetSizeDatatypeStylesheet
6153:                                                .getClassFullName()
6154:                                        + ")lCollectionDetails.ResultMaximumSize));");
6155:                        lWriter.println("                    }");
6156:                        lWriter
6157:                                .println("                    catch(DataTypeInvalidOperationForEmptyInstanceException e)");
6158:                        lWriter.println("                    {");
6159:                        lWriter
6160:                                .println("                        throw new PSDatatypeOperationException(\"Unexpected empty instance\",e);");
6161:                        lWriter.println("                    }");
6162:                        lWriter
6163:                                .println("                    catch(DataTypeInvalidOperationForConcealedInstanceException e)");
6164:                        lWriter.println("                    {");
6165:                        lWriter
6166:                                .println("                        throw new PSDatatypeOperationException(\"Unexpected concealed instance\",e);");
6167:                        lWriter.println("                    }");
6168:                        lWriter
6169:                                .println("                    catch(java.sql.SQLException e)");
6170:                        lWriter.println("                    {");
6171:                        lWriter
6172:                                .println("                        throw new PSDataSourceOperationInvocationException(\"Error on populating subset prepared statement.\", e);");
6173:                        lWriter.println("                    }");
6174:                        lWriter.println("                }");
6175:                    } else
6176:                        throw new BSUnexpectedProgramConditionException(
6177:                                "DataBaseMetaData does not have returned unsupported SubsetSyntaxType:"
6178:                                        + getDataBaseMetaData()
6179:                                                .suggestSubsetSyntaxType());
6180:                    lWriter.println("            }");
6181:                    lWriter.println("        }");
6182:                    lWriter
6183:                            .println("        return (lNextStartIndex - pStartIndex); // Difference between before and after");
6184:                    lWriter.println("    }");
6185:
6186:                    lWriter
6187:                            .println("    // This interpreter deals with whole, unfiltered entity collection");
6188:                    lWriter
6189:                            .println("    private static CollectionDetailsInterpreter sAllEntitiesInterpreter = new CollectionDetailsInterpreter()");
6190:                    lWriter.println("    {");
6191:                    lWriter
6192:                            .println("        // No filtering conditions whatsoever");
6193:                    lWriter
6194:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
6195:                    lWriter.println("        {");
6196:                    lWriter.println("            return \"\";");
6197:                    lWriter.println("        }");
6198:                    lWriter.println();
6199:                    lWriter.println("        // No parameters whatsoever");
6200:                    lWriter
6201:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
6202:                    lWriter.println("        {");
6203:                    lWriter.println("            return 0;");
6204:                    lWriter.println("        }");
6205:                    lWriter.println("    };");
6206:
6207:                    lWriter
6208:                            .println("    // This interpreter deals with entity casting along inheritance lines");
6209:                    lWriter
6210:                            .println("    private static CollectionDetailsInterpreter sCastInterpreter = new CollectionDetailsInterpreter()");
6211:                    lWriter.println("    {");
6212:                    lWriter
6213:                            .println("        // Cast means a simple join of from and to tables 'from_entity.instance_id = to_entity.instance_id'");
6214:                    lWriter
6215:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
6216:                    lWriter.println("        {");
6217:                    // It is allowed to have a "null cast" - it is used to separate filters and sorters and subset modifiers on the collection
6218:                    lWriter
6219:                            .println("            if (pCollectionDetails.EntityRef.equals(pCollectionDetails.CastingSourceEntityRef))");
6220:                    lWriter.println("                return \"\";");
6221:                    lWriter
6222:                            .println("            String lFromTableName = QueryContext.getTableNameByModelRef(pCollectionDetails.CastingSourceEntityRef);");
6223:                    lWriter.println("            if (lFromTableName == null)");
6224:                    lWriter
6225:                            .println("                throw new PSUnexpectedProgramConditionException(\"Collection details structure contains reference to unrecognised entity in the 'CastingSourceEntityRef' field: \" + pCollectionDetails.CastingSourceEntityRef);");
6226:                    lWriter
6227:                            .println("            String lToTableName = QueryContext.getTableNameByModelRef(pCollectionDetails.EntityRef);");
6228:                    lWriter.println("            if (lToTableName == null)");
6229:                    lWriter
6230:                            .println("                throw new PSUnexpectedProgramConditionException(\"Collection details structure contains reference to unrecognised entity in the 'EntityRef' field: \" + pCollectionDetails.EntityRef);");
6231:                    lWriter
6232:                            .println("            if (pQueryContext.getCurrentToTableName() == null || pQueryContext.getCurrentToTableName().equals(lToTableName) == false)");
6233:                    lWriter
6234:                            .println("                throw new PSUnexpectedProgramConditionException(\"Casting selector is called out of context (Disconnected chain of tables. Expecting '\" + lToTableName + \"', got '\" + pQueryContext.getCurrentToTableName() + \"'). This situation means that two neigbouring selectors were not referring to same table.\");");
6235:                    lWriter
6236:                            .println("            String lToTableAlias = pQueryContext.getCurrentToTableAlias();");
6237:                    lWriter
6238:                            .println("            String lToTableInstanceIdColumnName = pQueryContext.getCurrentToTableInstanceIdColumnName();");
6239:                    lWriter
6240:                            .println("            String lFromTableAlias = pQueryContext.takeTableForUse(lFromTableName);");
6241:                    lWriter
6242:                            .println("            String lFromTableInstanceIdColumnName = pQueryContext.getCurrentToTableInstanceIdColumnName();");
6243:                    lWriter
6244:                            .println("            StringBuffer lSqlWhereClause = new StringBuffer();");
6245:                    lWriter
6246:                            .println("            lSqlWhereClause.append(lFromTableAlias);");
6247:                    lWriter
6248:                            .println("            lSqlWhereClause.append(\".\");");
6249:                    lWriter
6250:                            .println("            lSqlWhereClause.append(lFromTableInstanceIdColumnName);");
6251:                    lWriter
6252:                            .println("            lSqlWhereClause.append(\" = \");");
6253:                    lWriter
6254:                            .println("            lSqlWhereClause.append(lToTableAlias);");
6255:                    lWriter
6256:                            .println("            lSqlWhereClause.append(\".\");");
6257:                    lWriter
6258:                            .println("            lSqlWhereClause.append(lToTableInstanceIdColumnName);");
6259:                    lWriter
6260:                            .println("            return lSqlWhereClause.toString();");
6261:                    lWriter.println("        }");
6262:                    lWriter.println();
6263:                    lWriter.println("        // Cast never uses any arguments");
6264:                    lWriter
6265:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
6266:                    lWriter.println("        {");
6267:                    lWriter.println("            return 0;");
6268:                    lWriter.println("        }");
6269:                    lWriter.println("    };");
6270:
6271:                    // This interpreter deals with collection subset
6272:                    lWriter
6273:                            .println("    private static CollectionDetailsInterpreter sSubsetInterpreter = new CollectionDetailsInterpreter()");
6274:                    lWriter.println("    {");
6275:                    lWriter
6276:                            .println("        // Subset means IN (first sql clause)");
6277:                    lWriter
6278:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
6279:                    lWriter.println("        {");
6280:                    // Check if selector was called in context
6281:                    lWriter
6282:                            .println("            String lEntityTableName = QueryContext.getTableNameByModelRef(pCollectionDetails.EntityRef);");
6283:                    lWriter
6284:                            .println("            if (pQueryContext.getCurrentToTableName() == null || lEntityTableName == null || pQueryContext.getCurrentToTableName().equals(lEntityTableName) == false)");
6285:                    lWriter
6286:                            .println("               throw new PSUnexpectedProgramConditionException(\"Collection is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
6287:                    lWriter
6288:                            .println("            StringBuffer lSqlWhereClause = new StringBuffer();");
6289:                    lWriter
6290:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0)");
6291:                    lWriter.println("            {");
6292:                    lWriter
6293:                            .println("                 lSqlWhereClause.append(\"(\");");
6294:                    lWriter
6295:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6296:                    lWriter
6297:                            .println("                 lSqlWhereClause.append(\".\");");
6298:                    lWriter
6299:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6300:                    lWriter
6301:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6302:                    lWriter
6303:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingInstruction(new STCollectionDetails[] { pCollectionDetails }), pQueryContext));");
6304:                    lWriter
6305:                            .println("                 lSqlWhereClause.append(\"))\");");
6306:                    lWriter.println("            }");
6307:                    lWriter
6308:                            .println("            return lSqlWhereClause.toString();");
6309:                    lWriter.println("        }");
6310:                    lWriter
6311:                            .println("        // Subset means IN (first sql clause)");
6312:                    lWriter
6313:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
6314:                    lWriter.println("        {");
6315:                    lWriter
6316:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0)");
6317:                    lWriter.println("            {");
6318:                    lWriter
6319:                            .println("                int lNextStartIndex = pStartIndex;");
6320:                    lWriter
6321:                            .println("                lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.FirstSetDetails, pStatement, lNextStartIndex);");
6322:                    lWriter
6323:                            .println("                return (lNextStartIndex - pStartIndex);");
6324:                    lWriter.println("            }");
6325:                    // If one of the clauses is empty (means includes all entities) - no statements and parameters required.
6326:                    lWriter.println("            return 0;");
6327:                    lWriter.println("        }");
6328:                    lWriter.println("    };");
6329:
6330:                    // This interpreter deals with collection union
6331:                    lWriter
6332:                            .println("    private static CollectionDetailsInterpreter sUnionInterpreter = new CollectionDetailsInterpreter()");
6333:                    lWriter.println("    {");
6334:                    lWriter
6335:                            .println("        // Union means (first sql clause) or (second sql clause)");
6336:                    lWriter
6337:                            .println("        // If one of the branches is empty (meaing all inclusive) the result is empty where clause - includes all");
6338:                    lWriter
6339:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
6340:                    lWriter.println("        {");
6341:                    // Check if selector was called in context
6342:                    lWriter
6343:                            .println("            String lEntityTableName = QueryContext.getTableNameByModelRef(pCollectionDetails.EntityRef);");
6344:                    lWriter
6345:                            .println("            if (pQueryContext.getCurrentToTableName() == null || lEntityTableName == null || pQueryContext.getCurrentToTableName().equals(lEntityTableName) == false)");
6346:                    lWriter
6347:                            .println("               throw new PSUnexpectedProgramConditionException(\"Collection is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
6348:                    lWriter
6349:                            .println("            StringBuffer lSqlWhereClause = new StringBuffer();");
6350:                    lWriter
6351:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0 && pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6352:                    lWriter.println("            {");
6353:                    lWriter
6354:                            .println("                 lSqlWhereClause.append(\"(\");");
6355:                    lWriter
6356:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6357:                    lWriter
6358:                            .println("                 lSqlWhereClause.append(\".\");");
6359:                    lWriter
6360:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6361:                    lWriter
6362:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6363:                    lWriter
6364:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.FirstSetDetails), pQueryContext));");
6365:                    lWriter
6366:                            .println("                 lSqlWhereClause.append(\") OR \");");
6367:                    lWriter
6368:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6369:                    lWriter
6370:                            .println("                 lSqlWhereClause.append(\".\");");
6371:                    lWriter
6372:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6373:                    lWriter
6374:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6375:                    lWriter
6376:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.SecondSetDetails), pQueryContext));");
6377:                    lWriter
6378:                            .println("                 lSqlWhereClause.append(\"))\");");
6379:                    lWriter.println("            }");
6380:                    lWriter.println("            else");
6381:                    lWriter.println("            {");
6382:                    // Everything matches if one of the branches is empty and we have to select everything
6383:                    // This also means that the limit and orderby do not apply 
6384:                    lWriter
6385:                            .println("                 QueryContext lSubqueryQueryContext = pQueryContext.openSubquery(QueryContext.QueryType.QUERYTYPE_GETALLRECORDIDS,lEntityTableName);");
6386:                    lWriter
6387:                            .println("                 String lSubqueryTableAlias = lSubqueryQueryContext.getCurrentToTableAlias();");
6388:                    lWriter
6389:                            .println("                 String lSubqueryTableInstanceIdColumName = lSubqueryQueryContext.getCurrentToTableInstanceIdColumnName();");
6390:                    lWriter
6391:                            .println("                 pQueryContext.closeSubquery(lSubqueryQueryContext);");
6392:                    lWriter
6393:                            .println("                 lSqlWhereClause.append(\"(\");");
6394:                    lWriter
6395:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6396:                    lWriter
6397:                            .println("                 lSqlWhereClause.append(\".\");");
6398:                    lWriter
6399:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6400:                    lWriter
6401:                            .println("                 lSqlWhereClause.append(\" IN ( SELECT DISTINCT(\");");
6402:                    lWriter
6403:                            .println("                 lSqlWhereClause.append(lSubqueryTableAlias);");
6404:                    lWriter
6405:                            .println("                 lSqlWhereClause.append(\".\");");
6406:                    lWriter
6407:                            .println("                 lSqlWhereClause.append(lSubqueryTableInstanceIdColumName);");
6408:                    lWriter
6409:                            .println("                 lSqlWhereClause.append(\") FROM \");");
6410:                    lWriter
6411:                            .println("                 lSqlWhereClause.append(lEntityTableName);");
6412:                    lWriter
6413:                            .println("                 lSqlWhereClause.append(\" \");");
6414:                    lWriter
6415:                            .println("                 lSqlWhereClause.append(lSubqueryTableAlias);");
6416:                    lWriter
6417:                            .println("                 lSqlWhereClause.append(\"))\");");
6418:                    lWriter.println("            }");
6419:                    lWriter
6420:                            .println("            return lSqlWhereClause.toString();");
6421:                    lWriter.println("        }");
6422:                    lWriter
6423:                            .println("        // Union means (first sql clause) or (second sql clause)");
6424:                    lWriter
6425:                            .println("        // If one of the branches is empty (meaing all inclusive) the result is empty");
6426:                    lWriter
6427:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
6428:                    lWriter.println("        {");
6429:                    lWriter
6430:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0 && pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6431:                    lWriter.println("            {");
6432:                    lWriter
6433:                            .println("                int lNextStartIndex = pStartIndex;");
6434:                    lWriter
6435:                            .println("                lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.FirstSetDetails, pStatement, lNextStartIndex);");
6436:                    lWriter
6437:                            .println("                lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.SecondSetDetails, pStatement, lNextStartIndex);");
6438:                    lWriter
6439:                            .println("                return (lNextStartIndex - pStartIndex);");
6440:                    lWriter.println("            }");
6441:                    // If one of the clauses is empty (means includes all entities) - no statements and parameters required.
6442:                    lWriter.println("            return 0;");
6443:                    lWriter.println("        }");
6444:                    lWriter.println("    };");
6445:
6446:                    // This interpreter deals with collection intersection operation
6447:                    lWriter
6448:                            .println("    private static CollectionDetailsInterpreter sIntersectionInterpreter = new CollectionDetailsInterpreter()");
6449:                    lWriter.println("    {");
6450:                    lWriter
6451:                            .println("        // Intersection means (first sql clause) and (second sql clause)");
6452:                    lWriter
6453:                            .println("        // If one of the branches is empty (meaing all inclusive) the result has only other branch's clause");
6454:                    lWriter
6455:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
6456:                    lWriter.println("        {");
6457:                    // Check if selector was called in context
6458:                    lWriter
6459:                            .println("            String lEntityTableName = QueryContext.getTableNameByModelRef(pCollectionDetails.EntityRef);");
6460:                    lWriter
6461:                            .println("            if (pQueryContext.getCurrentToTableName() == null || lEntityTableName == null || pQueryContext.getCurrentToTableName().equals(lEntityTableName) == false)");
6462:                    lWriter
6463:                            .println("               throw new PSUnexpectedProgramConditionException(\"Collection is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
6464:                    lWriter
6465:                            .println("            StringBuffer lSqlWhereClause = new StringBuffer();");
6466:                    lWriter
6467:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0 && pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6468:                    lWriter.println("            {");
6469:                    lWriter
6470:                            .println("                 lSqlWhereClause.append(\"(\");");
6471:                    lWriter
6472:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6473:                    lWriter
6474:                            .println("                 lSqlWhereClause.append(\".\");");
6475:                    lWriter
6476:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6477:                    lWriter
6478:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6479:                    lWriter
6480:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.FirstSetDetails), pQueryContext));");
6481:                    lWriter
6482:                            .println("                 lSqlWhereClause.append(\") AND \");");
6483:                    lWriter
6484:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6485:                    lWriter
6486:                            .println("                 lSqlWhereClause.append(\".\");");
6487:                    lWriter
6488:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6489:                    lWriter
6490:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6491:                    lWriter
6492:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.SecondSetDetails), pQueryContext));");
6493:                    lWriter
6494:                            .println("                 lSqlWhereClause.append(\"))\");");
6495:                    lWriter.println("            }");
6496:                    lWriter.println("            else");
6497:                    lWriter
6498:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0)");
6499:                    lWriter.println("            {");
6500:                    lWriter
6501:                            .println("                 lSqlWhereClause.append(\"(\");");
6502:                    lWriter
6503:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6504:                    lWriter
6505:                            .println("                 lSqlWhereClause.append(\".\");");
6506:                    lWriter
6507:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6508:                    lWriter
6509:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6510:                    lWriter
6511:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.FirstSetDetails), pQueryContext));");
6512:                    lWriter
6513:                            .println("                 lSqlWhereClause.append(\"))\");");
6514:                    lWriter.println("            }");
6515:                    lWriter.println("            else");
6516:                    lWriter
6517:                            .println("            if (pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6518:                    lWriter.println("            {");
6519:                    lWriter
6520:                            .println("                 lSqlWhereClause.append(\"(\");");
6521:                    lWriter
6522:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6523:                    lWriter
6524:                            .println("                 lSqlWhereClause.append(\".\");");
6525:                    lWriter
6526:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6527:                    lWriter
6528:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6529:                    lWriter
6530:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.SecondSetDetails), pQueryContext));");
6531:                    lWriter
6532:                            .println("                 lSqlWhereClause.append(\"))\");");
6533:                    lWriter.println("            }");
6534:                    lWriter
6535:                            .println("            return lSqlWhereClause.toString();");
6536:                    lWriter.println("        }");
6537:                    lWriter
6538:                            .println("        // Intersection means (first sql clause) and (second sql clause)");
6539:                    lWriter
6540:                            .println("        // If one of the branches is empty (meaing all inclusive) the result has only other branch's clause");
6541:                    lWriter
6542:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
6543:                    lWriter.println("        {");
6544:                    lWriter
6545:                            .println("             int lNextStartIndex = pStartIndex;");
6546:                    lWriter
6547:                            .println("             lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.FirstSetDetails, pStatement, lNextStartIndex);");
6548:                    lWriter
6549:                            .println("             lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.SecondSetDetails, pStatement, lNextStartIndex);");
6550:                    lWriter
6551:                            .println("             return (lNextStartIndex - pStartIndex);");
6552:                    lWriter.println("        }");
6553:                    lWriter.println("    };");
6554:
6555:                    lWriter
6556:                            .println("    // This interpreter deals with collection difference operation");
6557:                    lWriter
6558:                            .println("    private static CollectionDetailsInterpreter sDifferenceInterpreter = new CollectionDetailsInterpreter()");
6559:                    lWriter.println("    {");
6560:                    lWriter
6561:                            .println("        // Difference means (first sql clause) and not (second sql clause)");
6562:                    lWriter
6563:                            .println("        // If first branch is empty (meaing all inclusive) the result has all elements not in the second clause");
6564:                    lWriter
6565:                            .println("        // If second branch is empty (meaing all inclusive) the result is empty");
6566:                    lWriter
6567:                            .println("        public String getSqlWhereClause(STCollectionDetails pCollectionDetails, QueryContext pQueryContext) throws PSException");
6568:                    lWriter.println("        {");
6569:                    // Check if selector was called in context
6570:                    lWriter
6571:                            .println("            String lEntityTableName = QueryContext.getTableNameByModelRef(pCollectionDetails.EntityRef);");
6572:                    lWriter
6573:                            .println("            if (pQueryContext.getCurrentToTableName() == null || lEntityTableName == null || pQueryContext.getCurrentToTableName().equals(lEntityTableName) == false)");
6574:                    lWriter
6575:                            .println("               throw new PSUnexpectedProgramConditionException(\"Collection is called out of context (disconnected chain of tables). This situation means that two neigbouring selectors were not referring to same table.\");");
6576:                    lWriter
6577:                            .println("            StringBuffer lSqlWhereClause = new StringBuffer();");
6578:                    lWriter
6579:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0 && pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6580:                    lWriter.println("            {");
6581:                    lWriter
6582:                            .println("                 lSqlWhereClause.append(\"(\");");
6583:                    lWriter
6584:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6585:                    lWriter
6586:                            .println("                 lSqlWhereClause.append(\".\");");
6587:                    lWriter
6588:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6589:                    lWriter
6590:                            .println("                 lSqlWhereClause.append(\" IN (\");");
6591:                    lWriter
6592:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.FirstSetDetails), pQueryContext));");
6593:                    lWriter
6594:                            .println("                 lSqlWhereClause.append(\") AND \");");
6595:                    lWriter
6596:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6597:                    lWriter
6598:                            .println("                 lSqlWhereClause.append(\".\");");
6599:                    lWriter
6600:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6601:                    lWriter
6602:                            .println("                 lSqlWhereClause.append(\" NOT IN (\");");
6603:                    lWriter
6604:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.SecondSetDetails), pQueryContext));");
6605:                    lWriter
6606:                            .println("                 lSqlWhereClause.append(\"))\");");
6607:                    lWriter.println("            }");
6608:                    lWriter.println("            else");
6609:                    lWriter
6610:                            .println("            if (pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6611:                    lWriter.println("            {");
6612:                    lWriter
6613:                            .println("                 lSqlWhereClause.append(\"(\");");
6614:                    lWriter
6615:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6616:                    lWriter
6617:                            .println("                 lSqlWhereClause.append(\".\");");
6618:                    lWriter
6619:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6620:                    lWriter
6621:                            .println("                 lSqlWhereClause.append(\" NOT IN (\");");
6622:                    lWriter
6623:                            .println("                 lSqlWhereClause.append(buildSubquery(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails.SecondSetDetails), pQueryContext));");
6624:                    lWriter
6625:                            .println("                 lSqlWhereClause.append(\"))\");");
6626:                    lWriter.println("            }");
6627:                    lWriter.println("            else");
6628:                    lWriter.println("            {");
6629:                    // If second branch is empty - we are sure to select nothing - "not in the world" 
6630:                    lWriter
6631:                            .println("                 QueryContext lSubqueryQueryContext = pQueryContext.openSubquery(QueryContext.QueryType.QUERYTYPE_GETALLRECORDIDS,lEntityTableName);");
6632:                    lWriter
6633:                            .println("                 String lSubqueryTableAlias = lSubqueryQueryContext.getCurrentToTableAlias();");
6634:                    lWriter
6635:                            .println("                 String lSubqueryTableInstanceIdColumName = lSubqueryQueryContext.getCurrentToTableInstanceIdColumnName();");
6636:                    lWriter
6637:                            .println("                 pQueryContext.closeSubquery(lSubqueryQueryContext);");
6638:
6639:                    lWriter
6640:                            .println("                 lSqlWhereClause.append(\"(\");");
6641:                    lWriter
6642:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableAlias());");
6643:                    lWriter
6644:                            .println("                 lSqlWhereClause.append(\".\");");
6645:                    lWriter
6646:                            .println("                 lSqlWhereClause.append(pQueryContext.getCurrentToTableInstanceIdColumnName());");
6647:                    lWriter
6648:                            .println("                 lSqlWhereClause.append(\" NOT IN ( SELECT DISTINCT(\");");
6649:                    lWriter
6650:                            .println("                 lSqlWhereClause.append(lSubqueryTableAlias);");
6651:                    lWriter
6652:                            .println("                 lSqlWhereClause.append(\".\");");
6653:                    lWriter
6654:                            .println("                 lSqlWhereClause.append(lSubqueryTableInstanceIdColumName);");
6655:                    lWriter
6656:                            .println("                 lSqlWhereClause.append(\") FROM \");");
6657:                    lWriter
6658:                            .println("                 lSqlWhereClause.append(lEntityTableName);");
6659:                    lWriter
6660:                            .println("                 lSqlWhereClause.append(\" \");");
6661:                    lWriter
6662:                            .println("                 lSqlWhereClause.append(lSubqueryTableAlias);");
6663:                    lWriter
6664:                            .println("                 lSqlWhereClause.append(\"))\");");
6665:                    lWriter.println("            }");
6666:                    lWriter
6667:                            .println("            return lSqlWhereClause.toString();");
6668:                    lWriter.println("        }");
6669:                    lWriter
6670:                            .println("        // Difference means (first sql clause) and not (second sql clause)");
6671:                    lWriter
6672:                            .println("        // If first branch is empty (meaing all inclusive) the result has all elements not in the second clause");
6673:                    lWriter
6674:                            .println("        // If second branch is empty (meaing all inclusive) the result is empty");
6675:                    lWriter
6676:                            .println("        public int populatePreparedStatement(STCollectionDetails pCollectionDetails, PreparedStatement pStatement, int pStartIndex) throws PSException");
6677:                    lWriter.println("        {");
6678:                    lWriter
6679:                            .println("            if (pCollectionDetails.FirstSetDetails != null && pCollectionDetails.FirstSetDetails.length > 0 && pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6680:                    lWriter.println("            {");
6681:                    lWriter
6682:                            .println("                int lNextStartIndex = pStartIndex;");
6683:                    lWriter
6684:                            .println("                lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.FirstSetDetails, pStatement, lNextStartIndex);");
6685:                    lWriter
6686:                            .println("                lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.SecondSetDetails, pStatement, lNextStartIndex);");
6687:                    lWriter
6688:                            .println("                return (lNextStartIndex - pStartIndex);");
6689:                    lWriter.println("            }");
6690:                    lWriter.println("            else");
6691:                    lWriter
6692:                            .println("            if (pCollectionDetails.SecondSetDetails != null && pCollectionDetails.SecondSetDetails.length > 0)");
6693:                    lWriter.println("            {");
6694:                    lWriter
6695:                            .println("                int lNextStartIndex = pStartIndex;");
6696:                    lWriter
6697:                            .println("                lNextStartIndex += Selectors.populatePreparedStatement(pCollectionDetails.SecondSetDetails, pStatement, lNextStartIndex);");
6698:                    lWriter
6699:                            .println("                return (lNextStartIndex - pStartIndex);");
6700:                    lWriter.println("            }");
6701:                    lWriter.println("            return 0;");
6702:                    lWriter.println("        }");
6703:                    lWriter.println("    };");
6704:
6705:                    // Helper. Returns interpreter corresponding to the collection navigation or throws exception
6706:                    lWriter.println();
6707:                    lWriter
6708:                            .println("    private static CollectionDetailsInterpreter getMandatoryInterpreter(STCollectionDetails pCollectionDetails) throws PSException");
6709:                    lWriter.println("    {");
6710:                    lWriter
6711:                            .println("        if (pCollectionDetails.EntityRef == null)");
6712:                    lWriter
6713:                            .println("           throw new PSUnexpectedProgramConditionException(\"Field 'EntityRef' in the selector details structure is mandatory and can not be null.\");");
6714:                    lWriter
6715:                            .println("        if (pCollectionDetails.SetOperationName != null)");
6716:                    lWriter.println("        {");
6717:                    // This is the set operation - return interpreter in accordance with operation type
6718:                    lWriter
6719:                            .println("            if (pCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_SUBSET))");
6720:                    lWriter
6721:                            .println("                return sSubsetInterpreter;");
6722:                    lWriter.println("            else");
6723:                    lWriter
6724:                            .println("            if (pCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_UNION))");
6725:                    lWriter
6726:                            .println("                return sUnionInterpreter;");
6727:                    lWriter.println("            else");
6728:                    lWriter
6729:                            .println("            if (pCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_INTERSECTION))");
6730:                    lWriter
6731:                            .println("                return sIntersectionInterpreter;");
6732:                    lWriter.println("            else");
6733:                    lWriter
6734:                            .println("            if (pCollectionDetails.SetOperationName.equals(STCollectionDetails.SETOPERATION_DIFFERENCE))");
6735:                    lWriter
6736:                            .println("                return sDifferenceInterpreter;");
6737:                    lWriter.println("            else");
6738:                    // No other types are supported right now
6739:                    lWriter
6740:                            .println("               throw new PSUnexpectedProgramConditionException(\"Unsupported collection operation \" + pCollectionDetails.SetOperationName);");
6741:                    lWriter.println("        }");
6742:                    lWriter.println("        else");
6743:                    lWriter
6744:                            .println("        if (pCollectionDetails.CastingSourceEntityRef != null)");
6745:                    lWriter.println("        {");
6746:                    // This is the cast operation - return cast interpreter
6747:                    lWriter.println("            return sCastInterpreter;");
6748:                    lWriter.println("        }");
6749:                    lWriter.println("        else");
6750:                    lWriter
6751:                            .println("        if (pCollectionDetails.AssociationRoleRef != null)");
6752:                    lWriter.println("        {");
6753:                    // This is association role selector. Get the interpreter"
6754:                    lWriter
6755:                            .println("            CollectionDetailsInterpreter lInterpreter = (CollectionDetailsInterpreter)sAssociationSelectorMetadataMap.get(pCollectionDetails.AssociationRoleRef);");
6756:                    lWriter.println("            if (lInterpreter == null)");
6757:                    lWriter
6758:                            .println("               throw new PSUnexpectedProgramConditionException(\"Unregistered association role selector. AssociationRoleRef: \" + pCollectionDetails.AssociationRoleRef);");
6759:                    lWriter.println("            return lInterpreter;");
6760:                    lWriter.println("        }");
6761:                    // No other types are supported right now
6762:                    lWriter.println("        else");
6763:                    lWriter
6764:                            .println("        if (pCollectionDetails.AllEntitiesInDomain == true)");
6765:                    lWriter.println("        {");
6766:                    // This is the all entities operation - return all entities interpreter
6767:                    lWriter
6768:                            .println("            return sAllEntitiesInterpreter;");
6769:                    lWriter.println("        }");
6770:                    lWriter.println("        else");
6771:                    // No other types are supported right now
6772:                    lWriter
6773:                            .println("            throw new PSUnexpectedProgramConditionException(\"Unsupported selector type\");");
6774:                    lWriter.println("    }");
6775:
6776:                    // Helper. Returns interpreter corresponding to the selector or throws exception
6777:                    lWriter.println();
6778:                    lWriter
6779:                            .println("    private static FilteringDetailsInterpreter getMandatoryInterpreter(STFilteringDetails pFilteringDetails) throws PSException");
6780:                    lWriter.println("    {");
6781:                    lWriter
6782:                            .println("        if (pFilteringDetails.SelectorRef != null)");
6783:                    lWriter.println("        {");
6784:                    // This is entity selector. Get the interpreter from map
6785:                    lWriter
6786:                            .println("            FilteringDetailsInterpreter lInterpreter = (FilteringDetailsInterpreter)sEntitySelectorMetadataMap.get(pFilteringDetails.SelectorRef);");
6787:                    lWriter.println("            if (lInterpreter == null)");
6788:                    lWriter
6789:                            .println("               throw new PSUnexpectedProgramConditionException(\"Unregistered selector. SelectorRef: \" + pFilteringDetails.SelectorRef);");
6790:                    lWriter.println("            return lInterpreter;");
6791:                    lWriter.println("        }");
6792:                    lWriter.println("        else");
6793:                    lWriter
6794:                            .println("           throw new PSUnexpectedProgramConditionException(\"Field 'SelectorRef' in the filtering details structure is mandatory and can not be null.\");");
6795:                    lWriter.println("    }");
6796:                    // Helper. Returns interpreter corresponding to the sorter or throws exception
6797:                    lWriter.println();
6798:                    lWriter
6799:                            .println("    private static OrderingDetailsInterpreter getMandatoryInterpreter(STOrderingDetails pOrderingDetails) throws PSException");
6800:                    lWriter.println("    {");
6801:                    lWriter
6802:                            .println("        if (pOrderingDetails.ByAttributeRef != null)");
6803:                    lWriter.println("        {");
6804:                    // This is sorting selector. Get the interpreter from map
6805:                    lWriter
6806:                            .println("            OrderingDetailsInterpreter lInterpreter = (OrderingDetailsInterpreter)sEntityOrderingMetadataMap.get(pOrderingDetails.ByAttributeRef);");
6807:                    lWriter.println("            if (lInterpreter == null)");
6808:                    lWriter
6809:                            .println("               throw new PSUnexpectedProgramConditionException(\"Unregistered attribute ordering instruction. AttributeRef: \" + pOrderingDetails.ByAttributeRef);");
6810:                    lWriter.println("            return lInterpreter;");
6811:                    lWriter.println("        }");
6812:                    lWriter.println("        else");
6813:                    lWriter
6814:                            .println("           throw new PSUnexpectedProgramConditionException(\"Field 'ByAttributeRef' in the ordering details structure is mandatory and can not be null.\");");
6815:                    lWriter.println("    }");
6816:
6817:                    // This helper method returns select subquery for the given collection details chain 
6818:                    lWriter
6819:                            .println("    private static String buildSubquery(STCollectionDetails[] pCollectionDetails, QueryContext pQueryContext) throws PSException");
6820:                    lWriter.println("    {");
6821:                    lWriter
6822:                            .println("        StringBuffer lSubquery = new StringBuffer();");
6823:                    lWriter
6824:                            .println("        if (pCollectionDetails != null && pCollectionDetails.length > 0)");
6825:                    lWriter.println("        {");
6826:                    lWriter
6827:                            .println("            STCollectionDetails lCurrentCollectionDetails = pCollectionDetails[pCollectionDetails.length - 1];");
6828:                    lWriter
6829:                            .println("            String lEntityTableName = QueryContext.getTableNameByModelRef(lCurrentCollectionDetails.EntityRef);");
6830:                    // Check for the disconnection
6831:                    lWriter
6832:                            .println("            if (pQueryContext.getCurrentToTableName() == null || lEntityTableName == null || pQueryContext.getCurrentToTableName().equals(lEntityTableName) == false)");
6833:                    lWriter
6834:                            .println("               throw new PSUnexpectedProgramConditionException(\"Subquery builder is called out of context (disconnected chain of tables). This situation means that two neigbouring collection definitions were not referring to same table.\");");
6835:                    // Open subquery and get the sql statement parts
6836:                    lWriter
6837:                            .println("            QueryContext lSubqueryQueryContext = pQueryContext.openSubquery(QueryContext.QueryType.QUERYTYPE_GETALLRECORDIDS,lEntityTableName);");
6838:                    lWriter
6839:                            .println("            String lSubqueryTableAlias = lSubqueryQueryContext.getCurrentToTableAlias();");
6840:                    lWriter
6841:                            .println("            String lSubqueryTableInstanceIdColumName = lSubqueryQueryContext.getCurrentToTableInstanceIdColumnName();");
6842:                    lWriter
6843:                            .println("            Selectors.SqlStatementParts lSubquerySqlStatementParts = getSqlStatementParts(Util.suppressSortingIfNoSubsetInstruction(pCollectionDetails), lSubqueryQueryContext);");
6844:                    // Now we have everything to build the query
6845:                    lWriter
6846:                            .println("            lSubquery.append(\"SELECT DISTINCT \");");
6847:                    lWriter
6848:                            .println("            lSubquery.append(lSubquerySqlStatementParts.getWhatClause());");
6849:                    lWriter
6850:                            .println("            lSubquery.append(\" FROM \");");
6851:                    lWriter
6852:                            .println("            lSubquery.append(lSubquerySqlStatementParts.mFromClause);");
6853:                    // Work on "where" clause
6854:                    lWriter
6855:                            .println("            if (lSubquerySqlStatementParts.mWhereClause != null && lSubquerySqlStatementParts.mWhereClause.length() > 0)");
6856:                    lWriter.println("            {");
6857:                    lWriter
6858:                            .println("                lSubquery.append(\" WHERE \");");
6859:                    lWriter
6860:                            .println("                lSubquery.append(lSubquerySqlStatementParts.mWhereClause);");
6861:                    lWriter.println("            }");
6862:                    // Work on "limit" and "order by" clauses if record set is not limited - there is no need to do orderby
6863:                    lWriter
6864:                            .println("            if (lSubquerySqlStatementParts.mLimitClause != null && lSubquerySqlStatementParts.mLimitClause.length() > 0)");
6865:                    lWriter.println("            {");
6866:                    // When paging - there is a need to always order by somethig unique, in order for a sequence
6867:                    // to be reproduceable when the next page is taken a page. If we will not use the ordering
6868:                    // than the order of the records is not guaranteed and therefore the paging may not work correctly
6869:                    // For now only put the artificial ordering in if there is no custom order specified
6870:                    // TODO: Analysing whether application is already ordering by unique fields (eg. all elements of the primary key are present) and put this additional ordering at the end if necessary (ie. still not unique).
6871:                    lWriter
6872:                            .println("                 lSubquery.append(\" ORDER BY \");");
6873:                    lWriter
6874:                            .println("                 if (lSubquerySqlStatementParts.mOrderByClause != null && lSubquerySqlStatementParts.mOrderByClause.length() > 0)");
6875:                    lWriter.println("                 {");
6876:                    lWriter
6877:                            .println("                     lSubquery.append(lSubquerySqlStatementParts.mOrderByClause);");
6878:                    lWriter.println("                 }");
6879:                    lWriter.println("                 else");
6880:                    lWriter.println("                 {");
6881:                    lWriter
6882:                            .println("                     lSubquery.append(lSubqueryTableAlias);");
6883:                    lWriter
6884:                            .println("                     lSubquery.append(\".\");");
6885:                    lWriter
6886:                            .println("                     lSubquery.append(lSubqueryTableInstanceIdColumName);");
6887:                    lWriter
6888:                            .println("                     lSubquery.append(\" ASC\");");
6889:                    lWriter.println("                 }");
6890:                    // Now actual limit clause
6891:                    lWriter
6892:                            .println("                 lSubquery.append(\" LIMIT \");");
6893:                    lWriter
6894:                            .println("                 lSubquery.append(lSubquerySqlStatementParts.mLimitClause);");
6895:                    lWriter.println("            }");
6896:                    // Close subquery and move on
6897:                    lWriter
6898:                            .println("            pQueryContext.closeSubquery(lSubqueryQueryContext);");
6899:                    lWriter.println("        }");
6900:                    lWriter.println("        else");
6901:                    lWriter
6902:                            .println("            throw new PSUnexpectedProgramConditionException(\"Subquery builder is called out of context (null collection details). This situation is totally unexpected.\");");
6903:                    lWriter.println("        return lSubquery.toString();");
6904:                    lWriter.println("    }");
6905:                    lWriter.println("}");
6906:                } catch (IOException e) {
6907:                    throw new BSException(e);
6908:                } catch (BOException e) {
6909:                    throw new BSDomainObjectInvocationException(e);
6910:                } finally {
6911:                    if (lFileWriter != null) {
6912:                        try {
6913:                            lFileWriter.flush();
6914:                        } catch (IOException e) {
6915:                            // Ignore
6916:                        }
6917:                        try {
6918:                            lFileWriter.close();
6919:                        } catch (IOException e) {
6920:                            // Ignore
6921:                        }
6922:                    }
6923:                    if (lWriter != null) {
6924:                        lWriter.flush();
6925:                        lWriter.close();
6926:                    }
6927:                }
6928:            }
6929:
6930:            // Special expression resolver. Initialised with the context and resolves given SQLSeelctor macro expression
6931:            private static class SQLSelectorExpressionResolver implements 
6932:                    TemplateUtil.ExpressionResolver {
6933:                // In the constants below - Token suggests that we wil use startsWith and 
6934:                // disassemble expression further. Expression means that the whole expression 
6935:                // must be matched 
6936:                // The ${EntAttribute.aaaaaa} construct is substituted by the name of the column prefixed with the table alias
6937:                private static String sEntAttributeToken = "EntAttribute.";
6938:                private static int sEntAttributeTokenLength = sEntAttributeToken
6939:                        .length();
6940:                // The ${Inputs.iiiii} construct is substituted by the value from corresponding input field
6941:                private static String sInputToken = "Inputs.";
6942:                private static int sInputTokenLength = sInputToken.length();
6943:                // The ${Entity} construct is substituted by the name of the table representing this entity
6944:                private static String sOwnerEntityExpression = "Entity";
6945:                // The ${Ent} construct is substituted by the alias of the table representing this entity
6946:                private static String sOwnerEntityAliasExpression = "Ent";
6947:                // The ${Attribute.aaaaaa} construct is substituted by the name of the column representing specified attribute
6948:                private static String sAttributeToken = "Attribute.";
6949:                private static int sAttributeTokenLength = sAttributeToken
6950:                        .length();
6951:                // The ${Entities.eeeeee} construct is substituted by the name of the table representing specified entity
6952:                private static String sNamedEntityToken = "Entities.";
6953:                private static int sNamedEntityTokenLength = sNamedEntityToken
6954:                        .length();
6955:                // The ${Attributes.eeeeee} construct is substituted by the name of the column in table representing specified attribute in the specified entity
6956:                private static String sNamedAttributeToken = "Attributes.";
6957:                private static int sNamedAttributeTokenLength = sNamedAttributeToken
6958:                        .length();
6959:
6960:                private Domain mDomain;
6961:                private Entity mEntity;
6962:                private Selector mSelector;
6963:                private DomainRelationalStorageDefinition mDomainStorage;
6964:
6965:                // Create expression resolver with context		
6966:                public SQLSelectorExpressionResolver(Domain pDomain,
6967:                        Entity pEntity, Selector pSelector,
6968:                        DomainRelationalStorageDefinition pDomainStorage) {
6969:                    mDomain = pDomain;
6970:                    mEntity = pEntity;
6971:                    mSelector = pSelector;
6972:                    mDomainStorage = pDomainStorage;
6973:                }
6974:
6975:                /** Returns string to substitute given expression */
6976:                public String resolve(String pExpression)
6977:                        throws TemplateUtil.UnexpectedSyntaxException,
6978:                        TemplateUtil.ResolutionException {
6979:                    try {
6980:                        // Attempt to match supplied token against known ones
6981:                        if (pExpression.startsWith(sEntAttributeToken)) {
6982:                            // Alias.AttributeColumnName
6983:                            return "\" + pQueryContext.getCurrentToTableAlias() + \"."
6984:                                    + getAttributeColumnName(
6985:                                            mEntity,
6986:                                            pExpression
6987:                                                    .substring(sEntAttributeTokenLength));
6988:                        } else if (pExpression.startsWith(sInputToken)) {
6989:                            String lInputFieldName = pExpression
6990:                                    .substring(sInputTokenLength);
6991:                            SelectorInputField lInputField = mSelector
6992:                                    .findInputField(lInputFieldName);
6993:                            if (lInputField == null)
6994:                                throw new TemplateUtil.UnexpectedSyntaxException(
6995:                                        "Input field not found in the selector. Desired field name: '"
6996:                                                + lInputFieldName
6997:                                                + "' Macro: '" + pExpression
6998:                                                + "' SelectorRef: "
6999:                                                + mSelector.getRef());
7000:                            if (lInputField.isArray()) {
7001:                                STSelectorInputFieldStylesheet lSelectorInputFieldStylesheet = CodeGenerationStylesheetAccessor
7002:                                        .getSelectorInputFieldStylesheet(lInputField);
7003:                                // Place a number of '?' corresponding to the length of the array
7004:                                return "\" + com.metaboss.util.StringUtils.fill(\"?\",\"\",\"\",\",\",l"
7005:                                        + lSelectorInputFieldStylesheet
7006:                                                .getNormalisedName()
7007:                                        + ".length) + \"";
7008:                            } else {
7009:                                // Just place a single '?' for a single parameter placeholder in the prepared statement
7010:                                return "?";
7011:                            }
7012:                        } else if (pExpression.equals(sOwnerEntityExpression)) {
7013:                            // OwnerEntityTableName
7014:                            return getEntityTableName(mEntity);
7015:                        } else if (pExpression.startsWith(sNamedEntityToken)) {
7016:                            // Any EntityTableName
7017:                            String lEntityName = pExpression
7018:                                    .substring(sNamedEntityTokenLength);
7019:                            Entity lEntity = mDomain.findEntity(lEntityName);
7020:                            if (lEntity == null)
7021:                                throw new TemplateUtil.UnexpectedSyntaxException(
7022:                                        "Entity not found in the selector. Desired entity name: '"
7023:                                                + lEntityName + "' Macro: '"
7024:                                                + pExpression
7025:                                                + "' SelectorRef: "
7026:                                                + mSelector.getRef());
7027:                            // Entity Table name from the 
7028:                            return getEntityTableName(lEntity);
7029:                        } else if (pExpression
7030:                                .equals(sOwnerEntityAliasExpression)) {
7031:                            // Alias
7032:                            return "\" + pQueryContext.getCurrentToTableAlias() + \"";
7033:                        } else if (pExpression.startsWith(sAttributeToken)) {
7034:                            // AttributeColumnName
7035:                            return getAttributeColumnName(mEntity, pExpression
7036:                                    .substring(sAttributeTokenLength));
7037:                        } else if (pExpression.startsWith(sNamedAttributeToken)) {
7038:                            // Any AttributeColumnName
7039:                            StringTokenizer lTokenizer = new StringTokenizer(
7040:                                    pExpression
7041:                                            .substring(sNamedAttributeTokenLength),
7042:                                    ".", false);
7043:                            if (lTokenizer.countTokens() != 2)
7044:                                throw new TemplateUtil.UnexpectedSyntaxException(
7045:                                        "Invalid syntax for the "
7046:                                                + sNamedAttributeToken
7047:                                                + " macro. Expecting EntityName.AttributeName. Got '"
7048:                                                + pExpression
7049:                                                + "' SelectorRef: "
7050:                                                + mSelector.getRef());
7051:                            String lEntityName = lTokenizer.nextToken();
7052:                            Entity lEntity = mDomain.findEntity(lEntityName);
7053:                            if (lEntity == null)
7054:                                throw new TemplateUtil.UnexpectedSyntaxException(
7055:                                        "Entity not found in the selector. Desired entity name: '"
7056:                                                + lEntityName + "' Macro: '"
7057:                                                + pExpression
7058:                                                + "' SelectorRef: "
7059:                                                + mSelector.getRef());
7060:                            return getAttributeColumnName(mEntity, lTokenizer
7061:                                    .nextToken());
7062:                        }
7063:                        throw new TemplateUtil.UnexpectedSyntaxException(
7064:                                "Unrecognised macro in the SQLSelector text. Macro: '"
7065:                                        + pExpression + "' SelectorRef: "
7066:                                        + mSelector.getRef());
7067:                    } catch (JmiException e) {
7068:                        throw new TemplateUtil.ResolutionException(e);
7069:                    } catch (BSException e) {
7070:                        throw new TemplateUtil.ResolutionException(e);
7071:                    }
7072:                }
7073:
7074:                // Helper. Returns the name of the table reresenting an entity
7075:                private String getEntityTableName(Entity pEntity)
7076:                        throws TemplateUtil.UnexpectedSyntaxException,
7077:                        TemplateUtil.ResolutionException {
7078:                    try {
7079:                        RelationalEntityTable lEntityTable = mDomainStorage
7080:                                .getEntityTable(pEntity);
7081:                        String lEntityTableName = lEntityTable
7082:                                .getNameOverride();
7083:                        if (lEntityTableName == null
7084:                                || lEntityTableName.length() == 0)
7085:                            lEntityTableName = lEntityTable.getNameSuggestion();
7086:                        return lEntityTableName;
7087:                    } catch (JmiException e) {
7088:                        throw new TemplateUtil.ResolutionException(e);
7089:                    }
7090:                }
7091:
7092:                // Helper. Returns the name of the column reresenting an attribute
7093:                private String getAttributeColumnName(Entity pEntity,
7094:                        String pAttributeName)
7095:                        throws TemplateUtil.UnexpectedSyntaxException,
7096:                        TemplateUtil.ResolutionException {
7097:                    try {
7098:                        STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
7099:                                .getEntityStylesheet(pEntity);
7100:                        RelationalEntityTable lEntityTable = mDomainStorage
7101:                                .getEntityTable(pEntity);
7102:                        // Try standard columns
7103:                        if (pAttributeName.equals(lEntityStylesheet
7104:                                .getInstanceIdStorageStructureAttributeName())) {
7105:                            String lInstanceIdColumnName = lEntityTable
7106:                                    .getInstanceIdColumnNameOverride();
7107:                            if (lInstanceIdColumnName == null
7108:                                    || lInstanceIdColumnName.length() == 0)
7109:                                lInstanceIdColumnName = lEntityTable
7110:                                        .getInstanceIdColumnNameSuggestion();
7111:                            return lInstanceIdColumnName;
7112:                        } else if (pAttributeName.equals(lEntityStylesheet
7113:                                .getVersionIdStorageStructureAttributeName())) {
7114:                            if (!pEntity.isModifiable())
7115:                                throw new TemplateUtil.UnexpectedSyntaxException(
7116:                                        "Entity is not modifiable and selector can not refer to the version id system attribute. EntityRef:"
7117:                                                + pEntity.getRef()
7118:                                                + " SelectorRef: "
7119:                                                + mSelector.getRef());
7120:                            String lVersionIdColumnName = lEntityTable
7121:                                    .getVersionIdColumnNameOverride();
7122:                            if (lVersionIdColumnName == null
7123:                                    || lVersionIdColumnName.length() == 0)
7124:                                lVersionIdColumnName = lEntityTable
7125:                                        .getVersionIdColumnNameSuggestion();
7126:                            return lVersionIdColumnName;
7127:                        } else if (pAttributeName.equals(lEntityStylesheet
7128:                                .getStateStorageStructureAttributeName())) {
7129:                            if (pEntity.getStateMachine() == null)
7130:                                throw new TemplateUtil.UnexpectedSyntaxException(
7131:                                        "Entity does not have a state machine and selector can not refer to the state system attribute. EntityRef:"
7132:                                                + pEntity.getRef()
7133:                                                + " SelectorRef: "
7134:                                                + mSelector.getRef());
7135:                            String lStateColumnName = lEntityTable
7136:                                    .getStateColumnNameOverride();
7137:                            if (lStateColumnName == null
7138:                                    || lStateColumnName.length() == 0)
7139:                                lStateColumnName = lEntityTable
7140:                                        .getStateColumnNameSuggestion();
7141:                            return lStateColumnName;
7142:                        }
7143:                        // Now lets look at other attributes
7144:                        Attribute lAttribute = pEntity
7145:                                .findAttribute(pAttributeName);
7146:                        if (lAttribute == null)
7147:                            throw new TemplateUtil.UnexpectedSyntaxException(
7148:                                    "Attribute named '"
7149:                                            + pAttributeName
7150:                                            + "' not found in the entity. SelectorRef: "
7151:                                            + mSelector.getRef());
7152:                        RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
7153:                                .getAttributeColumn(lAttribute);
7154:                        String lAttributeColumnName = lRelationalEntityTableAttribute
7155:                                .getColumnNameOverride();
7156:                        if (lAttributeColumnName == null
7157:                                || lAttributeColumnName.length() == 0)
7158:                            lAttributeColumnName = lRelationalEntityTableAttribute
7159:                                    .getColumnNameSuggestion();
7160:                        return lAttributeColumnName;
7161:                    } catch (BSException e) {
7162:                        throw new TemplateUtil.ResolutionException(e);
7163:                    }
7164:                }
7165:            }
7166:
7167:            // Helper. Substitutes ${Attributes.<attribute name>} with column names
7168:            // For example '${Attributes.Price}' becomes 'Price'
7169:            // For example '${EntAttributes.Price}' becomes 'T.Price'
7170:            private static String convertSQLSelectorTextToStringConstant(
7171:                    String pSQLSelectorTemplate, Domain pDomain,
7172:                    Entity pEntity, Selector pSelector,
7173:                    DomainRelationalStorageDefinition pDomainStorage)
7174:                    throws BSException, BOException {
7175:                try {
7176:                    StringBuffer lOutputBuffer = new StringBuffer("\""); // Start string constant
7177:                    lOutputBuffer.append(TemplateUtil.processTemplate(
7178:                            pSQLSelectorTemplate,
7179:                            new SQLSelectorExpressionResolver(pDomain, pEntity,
7180:                                    pSelector, pDomainStorage)));
7181:                    // Ensure that possible "" + at the beginning is stripped off - this may occur if
7182:                    // the very beginning of the expression is a column expression
7183:                    String lReturn = lOutputBuffer.toString() + "\""; // Need to close the string constant
7184:                    if (lReturn.startsWith("\"\" + "))
7185:                        return lReturn.substring(5);
7186:                    return lReturn;
7187:                } catch (TemplateUtil.UnexpectedSyntaxException e) {
7188:                    throw new BSUnexpectedProgramConditionException(
7189:                            "Syntax error in the SQLSelector text", e);
7190:                } catch (TemplateUtil.ResolutionException e) {
7191:                    if (e.getCause() instanceof  BOException)
7192:                        throw (BOException) e.getCause();
7193:                    else if (e.getCause() instanceof  BSException)
7194:                        throw (BSException) e.getCause();
7195:                    throw new BSUnexpectedProgramConditionException(
7196:                            "Unexpected exception type was thrown from the template processor",
7197:                            e);
7198:                }
7199:            }
7200:
7201:            // The ${Inputs.iiiii} construct is substituted by the value from corresponding input field
7202:            private static String sInputToken = "${Inputs.";
7203:            private static int sInputTokenLength = sInputToken.length();
7204:            // Every macro ends in this 
7205:            private static String sEndToken = "}";
7206:            private static int sEndTokenLength = sEndToken.length();
7207:
7208:            // Helper. Returns an array of BOField objects in exact order as they have to be supplied to the
7209:            // prepared statement. It scans supplied string for ${Inputs.<input field name>}
7210:            // and gets field object corresponding to the name from the selector's definition
7211:            private static SelectorInputField[] getInputFieldsInOrderOfUse(
7212:                    String pSQLSelectorTemplate, Entity pEntity,
7213:                    Selector pSelector) throws BSException, BOException {
7214:                String lRemainderOfTemplate = pSQLSelectorTemplate;
7215:                ArrayList lInputFieldsInOrderOfUse = new ArrayList();
7216:                while (true) {
7217:                    int lPos = lRemainderOfTemplate.indexOf(sInputToken);
7218:                    if (lPos < 0) {
7219:                        // Finished
7220:                        break;
7221:                    }
7222:                    // Found another one
7223:                    lRemainderOfTemplate = lRemainderOfTemplate.substring(lPos
7224:                            + sInputTokenLength);
7225:                    // The remainder begins with input name}
7226:                    lPos = lRemainderOfTemplate.indexOf(sEndToken);
7227:                    if (lPos < 0)
7228:                        throw new BSUnexpectedProgramConditionException(
7229:                                "Unclosed "
7230:                                        + sInputToken
7231:                                        + " tag in the SQL template. SelectorRef:"
7232:                                        + pSelector.getRef());
7233:                    String lInputFieldName = lRemainderOfTemplate.substring(0,
7234:                            lPos);
7235:                    SelectorInputField lInputField = pSelector
7236:                            .getInputField(lInputFieldName);
7237:                    lInputFieldsInOrderOfUse.add(lInputField);
7238:                    lRemainderOfTemplate = lRemainderOfTemplate.substring(lPos
7239:                            + sEndTokenLength);
7240:                }
7241:                return (SelectorInputField[]) lInputFieldsInOrderOfUse
7242:                        .toArray(new SelectorInputField[lInputFieldsInOrderOfUse
7243:                                .size()]);
7244:            }
7245:
7246:            // Helper. This method will return unique name for the given datatype
7247:            // It is guaranteed to be unique within one jvm session
7248:            private static HashMap sUsedDatatypeNames = new HashMap(); // Datatype Ref - - Given name  
7249:            private static HashSet sTakenNames = new HashSet(); // List of taken names
7250:
7251:            public static String getUniqueDatatypeName(DataType pDatatype)
7252:                    throws BOException {
7253:                // First see if name has been given already
7254:                String lName = (String) sUsedDatatypeNames.get(pDatatype
7255:                        .getRef());
7256:                if (lName == null) {
7257:                    // We must come up with the name
7258:                    lName = pDatatype.getName();
7259:                    // Ensure that the name is unique by appending a number to the unlucky second ones
7260:                    for (int i = 1; sTakenNames.contains(lName); i++)
7261:                        lName = pDatatype.getName()
7262:                                + Integer.toString(i, Character.MAX_RADIX);
7263:                    // Now we have a unique new name
7264:                    sTakenNames.add(lName);
7265:                    sUsedDatatypeNames.put(pDatatype.getRef(), lName);
7266:                }
7267:                return lName;
7268:            }
7269:
7270:            // Helper. Writes out part of the where clause in getByPrimaryKey	
7271:            private static void writePartOfPrimaryKeyWhereClause(
7272:                    PrintWriter pWriter, Entity pPreviousEntity,
7273:                    Entity pThisEntity, List pPrimaryKeyElements,
7274:                    DomainRelationalStorageDefinition pDomainStorage)
7275:                    throws BOException {
7276:                RelationalEntityTable lThisEntityTable = pDomainStorage
7277:                        .getEntityTable(pThisEntity);
7278:                String lThisEntityTableName = lThisEntityTable
7279:                        .getNameOverride();
7280:                if (lThisEntityTableName == null
7281:                        || lThisEntityTableName.length() == 0)
7282:                    lThisEntityTableName = lThisEntityTable.getNameSuggestion();
7283:                // Work on linking to previous table
7284:                String lThisEntityInstanceIdColumnName = lThisEntityTable
7285:                        .getInstanceIdColumnNameOverride();
7286:                if (lThisEntityInstanceIdColumnName == null
7287:                        || lThisEntityInstanceIdColumnName.length() == 0)
7288:                    lThisEntityInstanceIdColumnName = lThisEntityTable
7289:                            .getInstanceIdColumnNameSuggestion();
7290:                // See if we need to take table and write the joint out	
7291:                if (pPreviousEntity != null) {
7292:                    RelationalEntityTable lPreviousEntityTable = pDomainStorage
7293:                            .getEntityTable(pPreviousEntity);
7294:                    String lPreviousEntityInstanceIdColumnName = lPreviousEntityTable
7295:                            .getInstanceIdColumnNameOverride();
7296:                    if (lPreviousEntityInstanceIdColumnName == null
7297:                            || lPreviousEntityInstanceIdColumnName.length() == 0)
7298:                        lPreviousEntityInstanceIdColumnName = lPreviousEntityTable
7299:                                .getInstanceIdColumnNameSuggestion();
7300:                    pWriter
7301:                            .println("                lPrimaryKeyWhereText.append(\" AND \");");
7302:                    pWriter
7303:                            .println("                lPrimaryKeyWhereText.append(lQueryContext.getCurrentToTableAlias());");
7304:                    pWriter
7305:                            .println("                lPrimaryKeyWhereText.append(\"."
7306:                                    + lPreviousEntityInstanceIdColumnName
7307:                                    + " = \");");
7308:                    pWriter
7309:                            .println("                lPrimaryKeyWhereText.append(lQueryContext.takeTableForUse(\""
7310:                                    + lThisEntityTableName + "\"));");
7311:                    pWriter
7312:                            .println("                lPrimaryKeyWhereText.append(\"."
7313:                                    + lThisEntityInstanceIdColumnName + " \");");
7314:                }
7315:                // Now write the comparisions
7316:                if (pPrimaryKeyElements != null
7317:                        && pPrimaryKeyElements.size() > 0) {
7318:                    // There are primary key elements in this entity. Must iterate through them
7319:
7320:                    // Need join if there was something written already;
7321:                    boolean lNeedAnd = (pPreviousEntity != null);
7322:
7323:                    // Work on primary key element matching clauses
7324:                    for (Iterator lPrimaryKeyElementsIterator = pPrimaryKeyElements
7325:                            .iterator(); lPrimaryKeyElementsIterator.hasNext();) {
7326:                        PrimaryKeyElement lPrimaryKeyElement = (PrimaryKeyElement) lPrimaryKeyElementsIterator
7327:                                .next();
7328:                        // Join conditions together if necessary
7329:                        if (lNeedAnd)
7330:                            pWriter
7331:                                    .println("                lPrimaryKeyWhereText.append(\" AND \");");
7332:                        else
7333:                            lNeedAnd = true;
7334:                        pWriter
7335:                                .println("                lPrimaryKeyWhereText.append(lQueryContext.getCurrentToTableAlias());");
7336:                        if (lPrimaryKeyElement instanceof  Attribute) {
7337:                            Attribute lAttribute = (Attribute) lPrimaryKeyElement;
7338:                            RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lThisEntityTable
7339:                                    .getAttributeColumn(lAttribute);
7340:                            String lAttributeColumnName = lRelationalEntityTableAttribute
7341:                                    .getColumnNameOverride();
7342:                            if (lAttributeColumnName == null
7343:                                    || lAttributeColumnName.length() == 0)
7344:                                lAttributeColumnName = lRelationalEntityTableAttribute
7345:                                        .getColumnNameSuggestion();
7346:                            pWriter
7347:                                    .println("                lPrimaryKeyWhereText.append(\"."
7348:                                            + lAttributeColumnName
7349:                                            + " = ? \");");
7350:                        } else if (lPrimaryKeyElement instanceof  AssociationRole) {
7351:                            AssociationRole lAssociationRole = (AssociationRole) lPrimaryKeyElement;
7352:                            RelationalEntityTableReferenceColumn lRelationalEntityTableAssociationRole = lThisEntityTable
7353:                                    .getReferenceColumn(lAssociationRole);
7354:                            String lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
7355:                                    .getColumnNameOverride();
7356:                            if (lAssociationRoleInstanceIdColumnName == null
7357:                                    || lAssociationRoleInstanceIdColumnName
7358:                                            .length() == 0)
7359:                                lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
7360:                                        .getColumnNameSuggestion();
7361:                            pWriter
7362:                                    .println("                lPrimaryKeyWhereText.append(\"."
7363:                                            + lAssociationRoleInstanceIdColumnName
7364:                                            + " = ? \");");
7365:                        }
7366:                    }
7367:                }
7368:            }
7369:
7370:            // Helper. Writes out part of the parameter set in getByPrimaryKey	
7371:            protected int writePartOfPrimaryKeyParameterSet(
7372:                    PrintWriter pWriter, int pNextParameterIndex,
7373:                    List pPrimaryKeyElements) throws BSException, BOException {
7374:                for (Iterator lPrimaryKeyElementsIterator = pPrimaryKeyElements
7375:                        .iterator(); lPrimaryKeyElementsIterator.hasNext();) {
7376:                    PrimaryKeyElement lPrimaryKeyElement = (PrimaryKeyElement) lPrimaryKeyElementsIterator
7377:                            .next();
7378:                    String lParameterName = null;
7379:                    DataType lParameterDatatype = null;
7380:                    if (lPrimaryKeyElement instanceof  Attribute) {
7381:                        Attribute lAttribute = (Attribute) lPrimaryKeyElement;
7382:                        STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
7383:                                .getAttributeStylesheet(lAttribute);
7384:                        lParameterName = "p" + lAttribute.getEntity().getName()
7385:                                + lAttributeStylesheet.getNormalisedName();
7386:                        lParameterDatatype = lAttribute.getDataType();
7387:                    } else if (lPrimaryKeyElement instanceof  AssociationRole) {
7388:                        AssociationRole lRole = (AssociationRole) lPrimaryKeyElement;
7389:                        lParameterName = "p" + lRole.getName() + "InstanceId";
7390:                        lParameterDatatype = lRole.getEntity()
7391:                                .getInstanceIdDataType();
7392:                    }
7393:                    // Obtain parameter datatype stylesheet
7394:                    STDatatypeStylesheet lParameterDatatypeStylesheet = CodeGenerationStylesheetAccessor
7395:                            .getDatatypeStylesheet(lParameterDatatype);
7396:                    pWriter
7397:                            .print("                    lGetByPrimaryKeyStatement.");
7398:                    pWriter.print(getDataBaseMetaData()
7399:                            .suggestStatementSetMethod(lParameterDatatype));
7400:                    pWriter.print("( ");
7401:                    pWriter.print(Integer.toString(pNextParameterIndex++));
7402:                    pWriter.print(", TypesConvertor.getSqlValueFrom");
7403:                    pWriter.print(getUniqueDatatypeName(lParameterDatatype));
7404:                    pWriter.print("(");
7405:                    pWriter.print(lParameterName);
7406:                    pWriter.println("));");
7407:                }
7408:                return pNextParameterIndex;
7409:            }
7410:
7411:            // Helper. Generates the string with all columns forming entity's natural primary key
7412:            private static String getPrimaryKeyArgumentsForWhereClause(
7413:                    Entity pEntity,
7414:                    DomainRelationalStorageDefinition pDomainStorage)
7415:                    throws BSException {
7416:                try {
7417:                    StringBuffer lWhereClause = new StringBuffer("");
7418:                    Collection lPrimaryKeyElements = pEntity
7419:                            .getPrimaryKeyElements();
7420:                    if (lPrimaryKeyElements.isEmpty())
7421:                        throw new BSException("Undefined PrimaryKey. Entity : "
7422:                                + pEntity.getName());
7423:                    boolean lNeedAnd = false;
7424:
7425:                    RelationalEntityTable lEntityTable = pDomainStorage
7426:                            .getEntityTable(pEntity);
7427:                    String lTableAlias = lEntityTable.getTableAlias();
7428:
7429:                    for (Iterator lPrimaryKeyElementsIterator = lPrimaryKeyElements
7430:                            .iterator(); lPrimaryKeyElementsIterator.hasNext();) {
7431:                        PrimaryKeyElement lPrimaryKeyElement = (PrimaryKeyElement) lPrimaryKeyElementsIterator
7432:                                .next();
7433:                        // Join conditions together if necessary
7434:                        if (lNeedAnd)
7435:                            lWhereClause.append(" AND ");
7436:                        else
7437:                            lNeedAnd = true;
7438:                        if (lPrimaryKeyElement instanceof  Attribute) {
7439:                            Attribute lAttribute = (Attribute) lPrimaryKeyElement;
7440:                            RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
7441:                                    .getAttributeColumn(lAttribute);
7442:                            String lAttributeColumnName = lRelationalEntityTableAttribute
7443:                                    .getColumnNameOverride();
7444:                            if (lAttributeColumnName == null
7445:                                    || lAttributeColumnName.length() == 0)
7446:                                lAttributeColumnName = lRelationalEntityTableAttribute
7447:                                        .getColumnNameSuggestion();
7448:
7449:                            // This attribute can not be optional
7450:                            if (lAttribute.isOptional())
7451:                                throw new BSException(
7452:                                        "Optional attribute can not be part of entity primary key. Entity : "
7453:                                                + pEntity.getName()
7454:                                                + ". Attribute : "
7455:                                                + lAttribute.getName());
7456:                            lWhereClause.append(lTableAlias);
7457:                            lWhereClause.append(".");
7458:                            lWhereClause.append(lAttributeColumnName);
7459:                            lWhereClause.append(" = ?");
7460:                        } else if (lPrimaryKeyElement instanceof  AssociationRole) {
7461:                            AssociationRole lAssociationRole = (AssociationRole) lPrimaryKeyElement;
7462:                            if (lAssociationRole.isOptional())
7463:                                throw new BSException(
7464:                                        "For Association to be part of PrimaryKey, the other entity's role must have cardinality of \"exactly one\". Entity : "
7465:                                                + pEntity.getName()
7466:                                                + ", Element "
7467:                                                + lAssociationRole.getName());
7468:                            RelationalEntityTableReferenceColumn lRelationalEntityTableAssociationRole = lEntityTable
7469:                                    .getReferenceColumn(lAssociationRole);
7470:                            String lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
7471:                                    .getColumnNameOverride();
7472:                            if (lAssociationRoleInstanceIdColumnName == null
7473:                                    || lAssociationRoleInstanceIdColumnName
7474:                                            .length() == 0)
7475:                                lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
7476:                                        .getColumnNameSuggestion();
7477:                            lWhereClause.append(lTableAlias);
7478:                            lWhereClause.append(".");
7479:                            lWhereClause
7480:                                    .append(lAssociationRoleInstanceIdColumnName);
7481:                            lWhereClause.append(" = ?");
7482:                        }
7483:                    }
7484:                    return lWhereClause.toString();
7485:                } catch (JmiException e) {
7486:                    throw new BSServiceProviderException(e);
7487:                }
7488:            }
7489:
7490:            // Helper. Writes the method which unpacks a single record from the result set
7491:            protected void writeUnpackEntityHelperOperation(
7492:                    PrintWriter pWriter, Entity pEntity,
7493:                    DomainRelationalStorageDefinition pDomainStorage)
7494:                    throws BOException, BSException {
7495:                // Get some stylesheets
7496:                STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
7497:                        .getEntityStylesheet(pEntity);
7498:
7499:                DataType lInstanceIdDatatype = pEntity.getInstanceIdDataType();
7500:                STDatatypeStylesheet lInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
7501:                        .getDatatypeStylesheet(lInstanceIdDatatype);
7502:                STDatatypeTranslationStylesheet lInstanceIdDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
7503:                        .getDatatypeTranslationStylesheet(lInstanceIdDatatype);
7504:                DataTypeTranslationMetadata.SqlType lInstanceIdDatatypeSqlType = DataTypeTranslationMetadata.SqlType
7505:                        .createFromName(lInstanceIdDatatypeTranslationStylesheet
7506:                                .getSqlTypeName());
7507:
7508:                boolean lIsModifiable = pEntity.isModifiable();
7509:                DataType lVersionIdDatatype = (lIsModifiable) ? pEntity
7510:                        .getVersionIdDataType() : null;
7511:                STDatatypeStylesheet lVersionIdDatatypeStylesheet = (lIsModifiable) ? CodeGenerationStylesheetAccessor
7512:                        .getDatatypeStylesheet(lVersionIdDatatype)
7513:                        : null;
7514:                STDatatypeTranslationStylesheet lVersionIdDatatypeTranslationStylesheet = (lIsModifiable) ? CodeGenerationStylesheetAccessor
7515:                        .getDatatypeTranslationStylesheet(lVersionIdDatatype)
7516:                        : null;
7517:                DataTypeTranslationMetadata.SqlType lVersionIdDatatypeSqlType = (lIsModifiable) ? DataTypeTranslationMetadata.SqlType
7518:                        .createFromName(lVersionIdDatatypeTranslationStylesheet
7519:                                .getSqlTypeName())
7520:                        : null;
7521:
7522:                boolean lHasState = pEntity.getStateMachine() != null;
7523:                DataType lStateDatatype = (lHasState) ? pEntity
7524:                        .getStateDataType() : null;
7525:                STDatatypeStylesheet lStateDatatypeStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
7526:                        .getDatatypeStylesheet(lStateDatatype)
7527:                        : null;
7528:                STDatatypeTranslationStylesheet lStateDatatypeTranslationStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
7529:                        .getDatatypeTranslationStylesheet(lStateDatatype)
7530:                        : null;
7531:                DataTypeTranslationMetadata.SqlType lStateDatatypeSqlType = (lHasState) ? DataTypeTranslationMetadata.SqlType
7532:                        .createFromName(lStateDatatypeTranslationStylesheet
7533:                                .getSqlTypeName())
7534:                        : null;
7535:
7536:                // Find out if this entity has LOBs (can only be in attributes)
7537:                boolean lHasBlobs = false;
7538:                boolean lHasClobs = false;
7539:                for (Iterator lAttributesIterator = pEntity.getAttributes()
7540:                        .iterator(); ((lHasBlobs == false) || (lHasBlobs == false))
7541:                        && (lAttributesIterator.hasNext());) {
7542:                    Attribute lAttribute = (Attribute) lAttributesIterator
7543:                            .next();
7544:                    STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
7545:                            .getDatatypeTranslationStylesheet(lAttribute
7546:                                    .getDataType());
7547:                    DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
7548:                            .createFromName(lAttributeDatatypeTranslationStylesheet
7549:                                    .getSqlTypeName());
7550:                    if (lHasBlobs == false
7551:                            && lAttributeDatatypeSqlType
7552:                                    .equals(DataTypeTranslationMetadata.SQL_BLOB))
7553:                        lHasBlobs = true;
7554:                    else if (lHasClobs == false
7555:                            && lAttributeDatatypeSqlType
7556:                                    .equals(DataTypeTranslationMetadata.SQL_CLOB))
7557:                        lHasClobs = true;
7558:                }
7559:
7560:                pWriter.println();
7561:                pWriter.println("    // Helper. Retrieves single "
7562:                        + pEntity.getName()
7563:                        + " record from the supplied ResultSet");
7564:                if (lHasClobs || lHasBlobs)
7565:                    pWriter
7566:                            .println("    private "
7567:                                    + lEntityStylesheet
7568:                                            .getStorageRecordFullName()
7569:                                    + " unpackRecordFromResultSet( java.sql.ResultSet pResultSet, boolean pResultSetHasLobs) throws PSException");
7570:                else
7571:                    pWriter
7572:                            .println("    private "
7573:                                    + lEntityStylesheet
7574:                                            .getStorageRecordFullName()
7575:                                    + " unpackRecordFromResultSet( java.sql.ResultSet pResultSet) throws PSException");
7576:                pWriter.println("    {");
7577:                pWriter.println("        try");
7578:                pWriter.println("        {");
7579:                pWriter.print("            ");
7580:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
7581:                pWriter.print(" lRecord = new ");
7582:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
7583:                pWriter.println("();");
7584:                pWriter.println("            int lParameterIndex = 1;");
7585:                pWriter.print("            ");
7586:                pWriter.print(lInstanceIdDatatypeSqlType.getJavaType()
7587:                        .getName()
7588:                        + (lInstanceIdDatatypeSqlType.isArray() ? "[]" : ""));
7589:                pWriter.print(" lInstanceId = pResultSet.");
7590:                pWriter.print(getDataBaseMetaData().suggestResultSetGetMethod(
7591:                        lInstanceIdDatatype));
7592:                pWriter.println("(lParameterIndex++);");
7593:                pWriter.println("            if (!pResultSet.wasNull())");
7594:                pWriter
7595:                        .println("                lRecord.InstanceId = TypesConvertor.create"
7596:                                + getUniqueDatatypeName(lInstanceIdDatatype)
7597:                                + "FromSqlValue(lInstanceId);");
7598:                pWriter.println("            else");
7599:                pWriter
7600:                        .println("                throw new PSAttributeConstraintViolationException(\""
7601:                                + lEntityStylesheet.getStorageRecordFullName()
7602:                                + ".InstanceId is not expected to be null in database.\");");
7603:                if (pEntity.isModifiable()) {
7604:                    pWriter.print("            ");
7605:                    pWriter
7606:                            .print(lVersionIdDatatypeSqlType.getJavaType()
7607:                                    .getName()
7608:                                    + (lVersionIdDatatypeSqlType.isArray() ? "[]"
7609:                                            : ""));
7610:                    pWriter.print(" lVersionId = pResultSet.");
7611:                    pWriter.print(getDataBaseMetaData()
7612:                            .suggestResultSetGetMethod(lVersionIdDatatype));
7613:                    pWriter.println("(lParameterIndex++);");
7614:                    pWriter.println("            if (!pResultSet.wasNull())");
7615:                    pWriter
7616:                            .println("                lRecord.VersionId = TypesConvertor.create"
7617:                                    + getUniqueDatatypeName(lVersionIdDatatype)
7618:                                    + "FromSqlValue(lVersionId);");
7619:                    pWriter.println("            else");
7620:                    pWriter
7621:                            .println("                throw new PSAttributeConstraintViolationException(\""
7622:                                    + lEntityStylesheet
7623:                                            .getStorageRecordFullName()
7624:                                    + ".VersionId is not expected to be null in database.\");");
7625:                }
7626:                if (lHasState) {
7627:                    pWriter.print("            ");
7628:                    pWriter.print(lStateDatatypeSqlType.getJavaType().getName()
7629:                            + (lStateDatatypeSqlType.isArray() ? "[]" : ""));
7630:                    pWriter.print(" lState = pResultSet.");
7631:                    pWriter.print(getDataBaseMetaData()
7632:                            .suggestResultSetGetMethod(lStateDatatype));
7633:                    pWriter.println("(lParameterIndex++);");
7634:                    pWriter.println("            if (!pResultSet.wasNull())");
7635:                    pWriter.println("                lRecord."
7636:                            + lEntityStylesheet
7637:                                    .getStateStorageStructureAttributeName()
7638:                            + " = TypesConvertor.create"
7639:                            + getUniqueDatatypeName(lStateDatatype)
7640:                            + "FromSqlValue(lState);");
7641:                    pWriter.println("            else");
7642:                    pWriter
7643:                            .println("                throw new PSAttributeConstraintViolationException(\""
7644:                                    + lEntityStylesheet
7645:                                            .getStorageRecordFullName()
7646:                                    + "."
7647:                                    + lEntityStylesheet
7648:                                            .getStateStorageStructureAttributeName()
7649:                                    + " is not expected to be null in database.\");");
7650:                }
7651:                // Deal with attributes
7652:                for (Iterator lAttributesIterator = pEntity.getAttributes()
7653:                        .iterator(); lAttributesIterator.hasNext();) {
7654:                    Attribute lAttribute = (Attribute) lAttributesIterator
7655:                            .next();
7656:                    STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
7657:                            .getAttributeStylesheet(lAttribute);
7658:                    DataType lAttributeDatatype = lAttribute.getDataType();
7659:                    STDatatypeStylesheet lAttributeDatatypeStylesheet = CodeGenerationStylesheetAccessor
7660:                            .getDatatypeStylesheet(lAttributeDatatype);
7661:                    STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
7662:                            .getDatatypeTranslationStylesheet(lAttribute
7663:                                    .getDataType());
7664:                    DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
7665:                            .createFromName(lAttributeDatatypeTranslationStylesheet
7666:                                    .getSqlTypeName());
7667:
7668:                    if (lAttributeDatatypeSqlType
7669:                            .equals(DataTypeTranslationMetadata.SQL_BLOB)) {
7670:                        pWriter.println("            if (pResultSetHasLobs)");
7671:                        pWriter.println("            {");
7672:                        pWriter.print("                java.sql.Blob l");
7673:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7674:                        pWriter
7675:                                .println(" = pResultSet.getBlob(lParameterIndex++);");
7676:                        pWriter
7677:                                .println("                if (!pResultSet.wasNull())");
7678:                        pWriter.print("                   lRecord.");
7679:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7680:                        pWriter.print(" = TypesConvertor.create");
7681:                        pWriter
7682:                                .print(getUniqueDatatypeName(lAttributeDatatype));
7683:                        pWriter
7684:                                .print("FromSqlValue(com.metaboss.util.ByteUtils.readByteStreamFully(l");
7685:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7686:                        pWriter.print(".getBinaryStream()));");
7687:                        pWriter.println("                else");
7688:                        if (lAttribute.isOptional()) {
7689:                            pWriter.print("                    lRecord.");
7690:                            pWriter.print(lAttributeStylesheet
7691:                                    .getNormalisedName());
7692:                            pWriter.print(" = ");
7693:                            pWriter.print(lAttributeDatatypeStylesheet
7694:                                    .getClassFullName());
7695:                            pWriter.println(".createEmpty();");
7696:                        } else {
7697:                            pWriter
7698:                                    .write("                    throw new PSAttributeConstraintViolationException(\"");
7699:                            pWriter.print(lEntityStylesheet
7700:                                    .getStorageRecordFullName());
7701:                            pWriter.print(".");
7702:                            pWriter.print(lAttributeStylesheet
7703:                                    .getNormalisedName());
7704:                            pWriter
7705:                                    .println(" is not expected to be null in database.\");");
7706:                        }
7707:                        pWriter.println("            }");
7708:                    } else if (lAttributeDatatypeSqlType
7709:                            .equals(DataTypeTranslationMetadata.SQL_CLOB)) {
7710:                        pWriter.println("            if (pResultSetHasLobs)");
7711:                        pWriter.println("            {");
7712:                        pWriter.print("                java.sql.Clob l");
7713:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7714:                        pWriter
7715:                                .println(" = pResultSet.getClob(lParameterIndex++);");
7716:                        pWriter
7717:                                .println("                if (!pResultSet.wasNull())");
7718:                        pWriter.print("                    lRecord.");
7719:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7720:                        pWriter.print(" = TypesConvertor.create");
7721:                        pWriter
7722:                                .print(getUniqueDatatypeName(lAttributeDatatype));
7723:                        pWriter
7724:                                .print("FromSqlValue(com.metaboss.util.StringUtils.readTextStreamFully(l");
7725:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7726:                        pWriter.print(".getAsciiStream()));");
7727:                        pWriter.println("                else");
7728:                        if (lAttribute.isOptional()) {
7729:                            pWriter.print("                    lRecord.");
7730:                            pWriter.print(lAttributeStylesheet
7731:                                    .getNormalisedName());
7732:                            pWriter.print(" = ");
7733:                            pWriter.print(lAttributeDatatypeStylesheet
7734:                                    .getClassFullName());
7735:                            pWriter.println(".createEmpty();");
7736:                        } else {
7737:                            pWriter
7738:                                    .write("                    throw new PSAttributeConstraintViolationException(\"");
7739:                            pWriter.print(lEntityStylesheet
7740:                                    .getStorageRecordFullName());
7741:                            pWriter.print(".");
7742:                            pWriter.print(lAttributeStylesheet
7743:                                    .getNormalisedName());
7744:                            pWriter
7745:                                    .println(" is not expected to be null in database.\");");
7746:                        }
7747:                        pWriter.println("            }");
7748:                    } else {
7749:                        pWriter.print("            ");
7750:                        pWriter.print(lAttributeDatatypeSqlType.getJavaType()
7751:                                .getName()
7752:                                + (lAttributeDatatypeSqlType.isArray() ? "[]"
7753:                                        : ""));
7754:                        pWriter.print(" l");
7755:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7756:                        pWriter.print(" = pResultSet.");
7757:                        pWriter.print(getDataBaseMetaData()
7758:                                .suggestResultSetGetMethod(lAttributeDatatype));
7759:                        pWriter.println("(lParameterIndex++);");
7760:                        pWriter
7761:                                .println("            if (!pResultSet.wasNull())");
7762:                        pWriter.print("                lRecord.");
7763:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7764:                        pWriter.print(" = TypesConvertor.create");
7765:                        pWriter
7766:                                .print(getUniqueDatatypeName(lAttributeDatatype));
7767:                        pWriter.print("FromSqlValue( l");
7768:                        pWriter.print(lAttributeStylesheet.getNormalisedName());
7769:                        pWriter.println(");");
7770:                        pWriter.println("            else");
7771:                        if (lAttribute.isOptional()) {
7772:                            pWriter.print("                lRecord.");
7773:                            pWriter.print(lAttributeStylesheet
7774:                                    .getNormalisedName());
7775:                            pWriter.print(" = ");
7776:                            pWriter.print(lAttributeDatatypeStylesheet
7777:                                    .getClassFullName());
7778:                            pWriter.println(".createEmpty();");
7779:                        } else {
7780:                            pWriter
7781:                                    .write("                throw new PSAttributeConstraintViolationException(\"");
7782:                            pWriter.print(lEntityStylesheet
7783:                                    .getStorageRecordFullName());
7784:                            pWriter.print(".");
7785:                            pWriter.print(lAttributeStylesheet
7786:                                    .getNormalisedName());
7787:                            pWriter
7788:                                    .println(" is not expected to be null in database.\");");
7789:                        }
7790:                    }
7791:                }
7792:                // Deal with associations
7793:                for (Iterator lReferencesIterator = pEntity.getReferences()
7794:                        .iterator(); lReferencesIterator.hasNext();) {
7795:                    AssociationRole lRole = (AssociationRole) lReferencesIterator
7796:                            .next();
7797:                    // Association constraint is only necessary if this entity has a reference
7798:                    if (CommonUtil.doesEntityStoreReference(lRole)) {
7799:                        DataType lRoleEntityInstanceIdDatatype = lRole
7800:                                .getEntity().getInstanceIdDataType();
7801:                        STDatatypeStylesheet lRoleEntityInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
7802:                                .getDatatypeStylesheet(lRoleEntityInstanceIdDatatype);
7803:                        STDatatypeTranslationStylesheet lRoleEntityInstanceIdDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
7804:                                .getDatatypeTranslationStylesheet(lRoleEntityInstanceIdDatatype);
7805:                        DataTypeTranslationMetadata.SqlType lRoleEntityInstanceIdDatatypeSqlType = DataTypeTranslationMetadata.SqlType
7806:                                .createFromName(lRoleEntityInstanceIdDatatypeTranslationStylesheet
7807:                                        .getSqlTypeName());
7808:                        pWriter.print("            ");
7809:                        pWriter.print(lRoleEntityInstanceIdDatatypeSqlType
7810:                                .getJavaType().getName()
7811:                                + (lRoleEntityInstanceIdDatatypeSqlType
7812:                                        .isArray() ? "[]" : ""));
7813:                        pWriter.print(" l");
7814:                        pWriter.print(lRole.getName());
7815:                        pWriter.print("InstanceId = pResultSet.");
7816:                        pWriter.print(getDataBaseMetaData()
7817:                                .suggestResultSetGetMethod(
7818:                                        lRoleEntityInstanceIdDatatype));
7819:                        pWriter.println("(lParameterIndex++);");
7820:                        pWriter
7821:                                .println("            if (!pResultSet.wasNull())");
7822:                        pWriter.print("                lRecord.");
7823:                        pWriter.print(lRole.getName());
7824:                        pWriter.print("InstanceId = TypesConvertor.create");
7825:                        pWriter
7826:                                .print(getUniqueDatatypeName(lRoleEntityInstanceIdDatatype));
7827:                        pWriter.print("FromSqlValue( l");
7828:                        pWriter.print(lRole.getName());
7829:                        pWriter.println("InstanceId);");
7830:                        pWriter.println("            else");
7831:                        // See if empty association is allowed
7832:                        if (lRole.isOptional()) {
7833:                            pWriter.print("                lRecord.");
7834:                            pWriter.print(lRole.getName());
7835:                            pWriter.print("InstanceId = ");
7836:                            pWriter
7837:                                    .print(lRoleEntityInstanceIdDatatypeStylesheet
7838:                                            .getClassFullName());
7839:                            pWriter.println(".createEmpty();");
7840:                        } else {
7841:                            pWriter
7842:                                    .print("                throw new PSAssociationConstraintViolationException(\"");
7843:                            pWriter.print(lEntityStylesheet
7844:                                    .getStorageRecordFullName());
7845:                            pWriter.print(".");
7846:                            pWriter.print(lRole.getName());
7847:                            pWriter
7848:                                    .println("InstanceId is not expected to be null in database.\");");
7849:                        }
7850:                    }
7851:                }
7852:                pWriter.println("            return lRecord;");
7853:                pWriter.println("        }");
7854:                if (lHasBlobs || lHasClobs) {
7855:                    pWriter.println("        catch(java.io.IOException e)");
7856:                    pWriter.println("        {");
7857:                    pWriter
7858:                            .print("            throw new PSException(\"java.io.IOException caught while unpacking the ");
7859:                    pWriter.print(lEntityStylesheet.getStorageRecordFullName());
7860:                    pWriter.println(" from the java.sql.ResultSet\", e);");
7861:                    pWriter.println("        }");
7862:                }
7863:                pWriter.println("        catch(java.sql.SQLException e)");
7864:                pWriter.println("        {");
7865:                pWriter
7866:                        .print("            throw new PSDataSourceOperationInvocationException(\"Error unpacking the ");
7867:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
7868:                pWriter.println(" from the java.sql.ResultSet\", e);");
7869:                pWriter.println("        }");
7870:                pWriter.println("    }");
7871:            }
7872:
7873:            // This hepler writes out the helper method to insert the entity record
7874:            protected void writeInsertEntityHelperOperation(
7875:                    PrintWriter pWriter, Entity pEntity,
7876:                    DomainRelationalStorageDefinition pDomainStorage)
7877:                    throws BOException, BSException {
7878:                STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
7879:                        .getEntityStylesheet(pEntity);
7880:                Collection lAttributes = pEntity.getAttributes();
7881:                Collection lReferences = pEntity.getReferences();
7882:
7883:                DataType lInstanceIdDatatype = pEntity.getInstanceIdDataType();
7884:                STDatatypeStylesheet lInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
7885:                        .getDatatypeStylesheet(lInstanceIdDatatype);
7886:                STDatatypeTranslationStylesheet lInstanceIdDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
7887:                        .getDatatypeTranslationStylesheet(lInstanceIdDatatype);
7888:                DataTypeTranslationMetadata.SqlType lInstanceIdDatatypeSqlType = DataTypeTranslationMetadata.SqlType
7889:                        .createFromName(lInstanceIdDatatypeTranslationStylesheet
7890:                                .getSqlTypeName());
7891:
7892:                boolean lIsModifiable = pEntity.isModifiable();
7893:                DataType lVersionIdDatatype = (lIsModifiable) ? pEntity
7894:                        .getVersionIdDataType() : null;
7895:                STDatatypeStylesheet lVersionIdDatatypeStylesheet = (lIsModifiable) ? CodeGenerationStylesheetAccessor
7896:                        .getDatatypeStylesheet(lVersionIdDatatype)
7897:                        : null;
7898:                STDatatypeTranslationStylesheet lVersionIdDatatypeTranslationStylesheet = (lIsModifiable) ? CodeGenerationStylesheetAccessor
7899:                        .getDatatypeTranslationStylesheet(lVersionIdDatatype)
7900:                        : null;
7901:                DataTypeTranslationMetadata.SqlType lVersionIdDatatypeSqlType = (lIsModifiable) ? DataTypeTranslationMetadata.SqlType
7902:                        .createFromName(lVersionIdDatatypeTranslationStylesheet
7903:                                .getSqlTypeName())
7904:                        : null;
7905:
7906:                boolean lHasState = pEntity.getStateMachine() != null;
7907:                DataType lStateDatatype = (lHasState) ? pEntity
7908:                        .getStateDataType() : null;
7909:                STDatatypeStylesheet lStateDatatypeStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
7910:                        .getDatatypeStylesheet(lStateDatatype)
7911:                        : null;
7912:                STDatatypeTranslationStylesheet lStateDatatypeTranslationStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
7913:                        .getDatatypeTranslationStylesheet(lStateDatatype)
7914:                        : null;
7915:                DataTypeTranslationMetadata.SqlType lStateDatatypeSqlType = (lHasState) ? DataTypeTranslationMetadata.SqlType
7916:                        .createFromName(lStateDatatypeTranslationStylesheet
7917:                                .getSqlTypeName())
7918:                        : null;
7919:
7920:                RelationalEntityTable lEntityTable = pDomainStorage
7921:                        .getEntityTable(pEntity);
7922:                String lEntityTableName = lEntityTable.getNameOverride();
7923:                if (lEntityTableName == null || lEntityTableName.length() == 0)
7924:                    lEntityTableName = lEntityTable.getNameSuggestion();
7925:                String lInstanceIdColumnName = lEntityTable
7926:                        .getInstanceIdColumnNameOverride();
7927:                if (lInstanceIdColumnName == null
7928:                        || lInstanceIdColumnName.length() == 0)
7929:                    lInstanceIdColumnName = lEntityTable
7930:                            .getInstanceIdColumnNameSuggestion();
7931:
7932:                String lVersionIdColumnName = null;
7933:                if (lIsModifiable) {
7934:                    lVersionIdColumnName = lEntityTable
7935:                            .getVersionIdColumnNameOverride();
7936:                    if (lVersionIdColumnName == null
7937:                            || lVersionIdColumnName.length() == 0)
7938:                        lVersionIdColumnName = lEntityTable
7939:                                .getVersionIdColumnNameSuggestion();
7940:                }
7941:
7942:                String lStateColumnName = null;
7943:                if (lHasState) {
7944:                    lStateColumnName = lEntityTable
7945:                            .getStateColumnNameOverride();
7946:                    if (lStateColumnName == null
7947:                            || lStateColumnName.length() == 0)
7948:                        lStateColumnName = lEntityTable
7949:                                .getStateColumnNameSuggestion();
7950:                }
7951:                pWriter.println();
7952:                pWriter.println("    // Inserts one or more new "
7953:                        + pEntity.getName() + " records into the database");
7954:                pWriter.println("    private void insert" + pEntity.getName()
7955:                        + "Records( java.sql.Connection pConnection, "
7956:                        + lEntityStylesheet.getStorageRecordFullName()
7957:                        + "[] pNewRecords) throws PSException");
7958:                pWriter.println("    {");
7959:                pWriter.println("        try");
7960:                pWriter.println("        {");
7961:
7962:                pWriter
7963:                        .println("            java.sql.PreparedStatement lCurrentStatement = null;");
7964:                pWriter
7965:                        .println("            String lCurrentTextOfInsertStatement = null;");
7966:                pWriter.println("            try");
7967:                pWriter.println("            {");
7968:                pWriter
7969:                        .println("                StringBuffer lProposedTextOfInsert = new StringBuffer();");
7970:                pWriter
7971:                        .println("                StringBuffer lProposedTextOfValues = new StringBuffer();");
7972:                pWriter
7973:                        .println("                for (int i = 0; i < pNewRecords.length; i++)");
7974:                pWriter.println("                {");
7975:                pWriter
7976:                        .println("                    lProposedTextOfInsert.setLength(0);");
7977:                pWriter
7978:                        .println("                    lProposedTextOfInsert.append(\"INSERT INTO "
7979:                                + lEntityTableName + " (\");");
7980:                pWriter
7981:                        .println("                    lProposedTextOfValues.setLength(0);");
7982:                pWriter
7983:                        .println("                    lProposedTextOfValues.append(\") VALUES (\");");
7984:                pWriter.println("                    "
7985:                        + lEntityStylesheet.getStorageRecordFullName()
7986:                        + " lNewRecord = pNewRecords[i];");
7987:                // InstanceId is mandatory
7988:                pWriter
7989:                        .println("                    if (lNewRecord.InstanceId == null)");
7990:                pWriter
7991:                        .println("                        throw new PSAttributeConstraintViolationException(\""
7992:                                + lEntityStylesheet.getStorageRecordFullName()
7993:                                + ".InstanceId is not expected to be undefined for insert() operation.\");");
7994:                pWriter
7995:                        .println("                    if (lNewRecord.InstanceId.isEmpty())");
7996:                pWriter
7997:                        .println("                        throw new PSAttributeConstraintViolationException(\""
7998:                                + lEntityStylesheet.getStorageRecordFullName()
7999:                                + ".InstanceId is not expected to be empty for insert() operation.\");");
8000:                pWriter
8001:                        .println("                    if (lNewRecord.InstanceId.isConcealed())");
8002:                pWriter
8003:                        .println("                        throw new PSAttributeConstraintViolationException(\""
8004:                                + lEntityStylesheet.getStorageRecordFullName()
8005:                                + ".InstanceId is not expected to be concealed for insert() operation.\");");
8006:                pWriter
8007:                        .println("                    lProposedTextOfInsert.append(\""
8008:                                + lInstanceIdColumnName + "\");");
8009:                pWriter
8010:                        .println("                    lProposedTextOfValues.append(\"?\");");
8011:                if (lIsModifiable) {
8012:                    pWriter
8013:                            .println("                    // VersionId is mandatory and must be the initial version");
8014:                    pWriter
8015:                            .println("                    if (lNewRecord.VersionId == null)");
8016:                    pWriter
8017:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8018:                                    + lEntityStylesheet
8019:                                            .getStorageRecordFullName()
8020:                                    + ".VersionId is not expected to be undefined for insert() operation.\");");
8021:                    pWriter
8022:                            .println("                    if (lNewRecord.VersionId.isEmpty())");
8023:                    pWriter
8024:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8025:                                    + lEntityStylesheet
8026:                                            .getStorageRecordFullName()
8027:                                    + ".VersionId is not expected to be empty for insert() operation.\");");
8028:                    pWriter
8029:                            .println("                    if (lNewRecord.VersionId.isConcealed())");
8030:                    pWriter
8031:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8032:                                    + lEntityStylesheet
8033:                                            .getStorageRecordFullName()
8034:                                    + ".VersionId is not expected to be concealed for insert() operation.\");");
8035:                    pWriter
8036:                            .println("                    if (!lNewRecord.VersionId.isInitial())");
8037:                    pWriter
8038:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8039:                                    + lEntityStylesheet
8040:                                            .getStorageRecordFullName()
8041:                                    + ".VersionId expected to be '\" + "
8042:                                    + lVersionIdDatatypeStylesheet
8043:                                            .getClassFullName()
8044:                                    + ".createInitial() + \"'  for insert() operation. Version id '\" + lNewRecord.VersionId + \"' is not valid for insert() operation.\");");
8045:                    pWriter
8046:                            .println("                    lProposedTextOfInsert.append(\","
8047:                                    + lVersionIdColumnName + "\");");
8048:                    pWriter
8049:                            .println("                    lProposedTextOfValues.append(\",?\");");
8050:                }
8051:                if (lHasState) {
8052:                    pWriter
8053:                            .println("                    // State is mandatory and must be the initial state");
8054:                    pWriter.println("                    if (lNewRecord."
8055:                            + lEntityStylesheet
8056:                                    .getStateStorageStructureAttributeName()
8057:                            + " == null)");
8058:                    pWriter
8059:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8060:                                    + lEntityStylesheet
8061:                                            .getStorageRecordFullName()
8062:                                    + "."
8063:                                    + lEntityStylesheet
8064:                                            .getStateStorageStructureAttributeName()
8065:                                    + " is not expected to be undefined for insert() operation.\");");
8066:                    pWriter.println("                    if (lNewRecord."
8067:                            + lEntityStylesheet
8068:                                    .getStateStorageStructureAttributeName()
8069:                            + ".isEmpty())");
8070:                    pWriter
8071:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8072:                                    + lEntityStylesheet
8073:                                            .getStorageRecordFullName()
8074:                                    + "."
8075:                                    + lEntityStylesheet
8076:                                            .getStateStorageStructureAttributeName()
8077:                                    + " is not expected to be empty for insert() operation.\");");
8078:                    pWriter.println("                    if (lNewRecord."
8079:                            + lEntityStylesheet
8080:                                    .getStateStorageStructureAttributeName()
8081:                            + ".isConcealed())");
8082:                    pWriter
8083:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8084:                                    + lEntityStylesheet
8085:                                            .getStorageRecordFullName()
8086:                                    + "."
8087:                                    + lEntityStylesheet
8088:                                            .getStateStorageStructureAttributeName()
8089:                                    + " is not expected to be concealed for insert() operation.\");");
8090:                    pWriter.println("                    if (!lNewRecord."
8091:                            + lEntityStylesheet
8092:                                    .getStateStorageStructureAttributeName()
8093:                            + ".isInitial())");
8094:                    pWriter.println("                    {");
8095:                    pWriter.println("                        "
8096:                            + lStateDatatypeStylesheet.getClassFullName()
8097:                            + " lInitialState = "
8098:                            + lStateDatatypeStylesheet.getClassFullName()
8099:                            + ".createInitial();");
8100:                    pWriter
8101:                            .println("                        if (!lInitialState.canTransition(lNewRecord."
8102:                                    + lEntityStylesheet
8103:                                            .getStateStorageStructureAttributeName()
8104:                                    + "))");
8105:                    pWriter
8106:                            .println("                            throw new PSAttributeConstraintViolationException(\"For insert() operation the "
8107:                                    + lEntityStylesheet
8108:                                            .getStorageRecordFullName()
8109:                                    + "."
8110:                                    + lEntityStylesheet
8111:                                            .getStateStorageStructureAttributeName()
8112:                                    + " field is expected to be set to initial state or any of the states immediately navigable from the initial state. Value '\" + lNewRecord."
8113:                                    + lEntityStylesheet
8114:                                            .getStateStorageStructureAttributeName()
8115:                                    + " + \"' is not valid for insert() operation.\");");
8116:                    pWriter.println("                    }");
8117:                    pWriter
8118:                            .println("                    lProposedTextOfInsert.append(\","
8119:                                    + lStateColumnName + "\");");
8120:                    pWriter
8121:                            .println("                    lProposedTextOfValues.append(\",?\");");
8122:                }
8123:                // Deal with attributes
8124:                for (Iterator lAttributesIterator = lAttributes.iterator(); lAttributesIterator
8125:                        .hasNext();) {
8126:                    Attribute lAttribute = (Attribute) lAttributesIterator
8127:                            .next();
8128:                    RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
8129:                            .getAttributeColumn(lAttribute);
8130:                    String lAttributeColumnName = lRelationalEntityTableAttribute
8131:                            .getColumnNameOverride();
8132:                    if (lAttributeColumnName == null
8133:                            || lAttributeColumnName.length() == 0)
8134:                        lAttributeColumnName = lRelationalEntityTableAttribute
8135:                                .getColumnNameSuggestion();
8136:
8137:                    // Do not look at SQL_BLOB and SQL_CLOB here
8138:                    STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
8139:                            .getAttributeStylesheet(lAttribute);
8140:                    STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
8141:                            .getDatatypeTranslationStylesheet(lAttribute
8142:                                    .getDataType());
8143:                    DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
8144:                            .createFromName(lAttributeDatatypeTranslationStylesheet
8145:                                    .getSqlTypeName());
8146:                    if (lAttribute.isOptional()) {
8147:                        // Do not even bother inserting optional attribute - null will just appear automatically
8148:                        pWriter.println("                    // "
8149:                                + lAttribute.getName() + " is optional");
8150:                        pWriter.println("                    if (lNewRecord."
8151:                                + lAttributeStylesheet.getNormalisedName()
8152:                                + " != null && lNewRecord."
8153:                                + lAttributeStylesheet.getNormalisedName()
8154:                                + ".isEmpty() == false)");
8155:                        pWriter.println("                    {");
8156:                        pWriter
8157:                                .println("                        if (lNewRecord."
8158:                                        + lAttributeStylesheet
8159:                                                .getNormalisedName()
8160:                                        + ".isConcealed())");
8161:                        pWriter
8162:                                .println("                            throw new PSAttributeConstraintViolationException(\""
8163:                                        + lEntityStylesheet
8164:                                                .getStorageRecordFullName()
8165:                                        + "."
8166:                                        + lAttributeStylesheet
8167:                                                .getNormalisedName()
8168:                                        + " is not expected to be concealed for insert() operation.\");");
8169:                        pWriter
8170:                                .println("                        lProposedTextOfInsert.append(\","
8171:                                        + lAttributeColumnName + "\");");
8172:                        pWriter
8173:                                .println("                        lProposedTextOfValues.append(\",?\");");
8174:                        pWriter.println("                    }");
8175:                    } else {
8176:                        pWriter.println("                    // "
8177:                                + lAttributeStylesheet.getNormalisedName()
8178:                                + " is mandatory");
8179:                        pWriter.println("                    if (lNewRecord."
8180:                                + lAttributeStylesheet.getNormalisedName()
8181:                                + " == null)");
8182:                        pWriter
8183:                                .println("                        throw new PSAttributeConstraintViolationException(\""
8184:                                        + lEntityStylesheet
8185:                                                .getStorageRecordFullName()
8186:                                        + "."
8187:                                        + lAttributeStylesheet
8188:                                                .getNormalisedName()
8189:                                        + " is not expected to be undefined for insert() operation.\");");
8190:                        pWriter.println("                    if (lNewRecord."
8191:                                + lAttributeStylesheet.getNormalisedName()
8192:                                + ".isEmpty())");
8193:                        pWriter
8194:                                .println("                        throw new PSAttributeConstraintViolationException(\""
8195:                                        + lEntityStylesheet
8196:                                                .getStorageRecordFullName()
8197:                                        + "."
8198:                                        + lAttributeStylesheet
8199:                                                .getNormalisedName()
8200:                                        + " is not expected to be empty for insert() operation.\");");
8201:                        pWriter.println("                    if (lNewRecord."
8202:                                + lAttributeStylesheet.getNormalisedName()
8203:                                + ".isConcealed())");
8204:                        pWriter
8205:                                .println("                        throw new PSAttributeConstraintViolationException(\""
8206:                                        + lEntityStylesheet
8207:                                                .getStorageRecordFullName()
8208:                                        + "."
8209:                                        + lAttributeStylesheet
8210:                                                .getNormalisedName()
8211:                                        + " is not expected to be concealed for insert() operation.\");");
8212:                        pWriter
8213:                                .println("                    lProposedTextOfInsert.append(\","
8214:                                        + lAttributeColumnName + "\");");
8215:                        pWriter
8216:                                .println("                    lProposedTextOfValues.append(\",?\");");
8217:                    }
8218:                }
8219:                // Deal with associations
8220:                for (Iterator lReferencesIterator = lReferences.iterator(); lReferencesIterator
8221:                        .hasNext();) {
8222:                    AssociationRole lReference = (AssociationRole) lReferencesIterator
8223:                            .next();
8224:                    // Association constraint is only necessary if this entity has a reference
8225:                    if (CommonUtil.doesEntityStoreReference(lReference)) {
8226:                        RelationalEntityTableReferenceColumn lRelationalEntityTableAssociationRole = lEntityTable
8227:                                .getReferenceColumn(lReference);
8228:                        String lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
8229:                                .getColumnNameOverride();
8230:                        if (lAssociationRoleInstanceIdColumnName == null
8231:                                || lAssociationRoleInstanceIdColumnName
8232:                                        .length() == 0)
8233:                            lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
8234:                                    .getColumnNameSuggestion();
8235:                        if (lReference.isOptional()) {
8236:                            // Do not even bother inserting optional reference - null will just appear automatically
8237:                            pWriter
8238:                                    .println("                    if (lNewRecord."
8239:                                            + lReference.getName()
8240:                                            + "InstanceId != null && lNewRecord."
8241:                                            + lReference.getName()
8242:                                            + "InstanceId.isEmpty() == false)");
8243:                            pWriter.println("                    {");
8244:                            pWriter
8245:                                    .println("                        if (lNewRecord."
8246:                                            + lReference.getName()
8247:                                            + "InstanceId.isConcealed())");
8248:                            pWriter
8249:                                    .println("                            throw new PSAssociationConstraintViolationException(\""
8250:                                            + lEntityStylesheet
8251:                                                    .getStorageRecordFullName()
8252:                                            + "."
8253:                                            + lReference.getName()
8254:                                            + "InstanceId is not expected to be concealed for insert() operation.\");");
8255:                            pWriter
8256:                                    .println("                        lProposedTextOfInsert.append(\","
8257:                                            + lAssociationRoleInstanceIdColumnName
8258:                                            + "\");");
8259:                            pWriter
8260:                                    .println("                        lProposedTextOfValues.append(\",?\");");
8261:                            pWriter.println("                    }");
8262:                        } else {
8263:                            pWriter
8264:                                    .println("                    if (lNewRecord."
8265:                                            + lReference.getName()
8266:                                            + "InstanceId == null)");
8267:                            pWriter
8268:                                    .println("                        throw new PSAssociationConstraintViolationException(\""
8269:                                            + lEntityStylesheet
8270:                                                    .getStorageRecordFullName()
8271:                                            + "."
8272:                                            + lReference.getName()
8273:                                            + "InstanceId is not expected to be undefined for insert() operation.\");");
8274:                            pWriter
8275:                                    .println("                    if (lNewRecord."
8276:                                            + lReference.getName()
8277:                                            + "InstanceId.isEmpty())");
8278:                            pWriter
8279:                                    .println("                        throw new PSAssociationConstraintViolationException(\""
8280:                                            + lEntityStylesheet
8281:                                                    .getStorageRecordFullName()
8282:                                            + "."
8283:                                            + lReference.getName()
8284:                                            + "InstanceId is not expected to be empty for insert() operation.\");");
8285:                            pWriter
8286:                                    .println("                    if (lNewRecord."
8287:                                            + lReference.getName()
8288:                                            + "InstanceId.isConcealed())");
8289:                            pWriter
8290:                                    .println("                        throw new PSAssociationConstraintViolationException(\""
8291:                                            + lEntityStylesheet
8292:                                                    .getStorageRecordFullName()
8293:                                            + "."
8294:                                            + lReference.getName()
8295:                                            + "InstanceId is not expected to be concealed for insert() operation.\");");
8296:                            pWriter
8297:                                    .println("                    lProposedTextOfInsert.append(\","
8298:                                            + lAssociationRoleInstanceIdColumnName
8299:                                            + "\");");
8300:                            pWriter
8301:                                    .println("                    lProposedTextOfValues.append(\",?\");");
8302:                        }
8303:                    }
8304:                }
8305:                // We have built the statement for this insertion. Compare with saved one and make a decision to continue current batch or not
8306:                pWriter
8307:                        .println("                    String lProposedTextOfInsertStatement = lProposedTextOfInsert.toString() + lProposedTextOfValues.toString() + \")\";");
8308:                pWriter
8309:                        .println("                    if (lCurrentStatement != null)");
8310:                pWriter.println("                    {");
8311:                pWriter
8312:                        .println("                        if (!lCurrentTextOfInsertStatement.equals(lProposedTextOfInsertStatement))");
8313:                pWriter.println("                        {");
8314:                // Execute batched up previous sttement
8315:                pWriter
8316:                        .println("                            lCurrentStatement.executeBatch();");
8317:                pWriter
8318:                        .println("                            lCurrentStatement.close();");
8319:                pWriter
8320:                        .println("                            lCurrentStatement = null;");
8321:                pWriter.println("                        }");
8322:                pWriter.println("                    }");
8323:                pWriter
8324:                        .println("                    if (lCurrentStatement == null)");
8325:                pWriter.println("                    {");
8326:                pWriter
8327:                        .println("                        lCurrentTextOfInsertStatement = lProposedTextOfInsertStatement;");
8328:                pWriter
8329:                        .println("                        if (sLogger.isDebugEnabled())");
8330:                pWriter
8331:                        .println("                            sLogger.debug(\"About to execute SQL statement: \" + lCurrentTextOfInsertStatement + \";\");");
8332:                pWriter
8333:                        .println("                        lCurrentStatement = pConnection.prepareStatement(lCurrentTextOfInsertStatement);");
8334:                pWriter.println("                    }");
8335:                // Now populate the statement
8336:                pWriter.println("                    int lParameterIndex = 1;");
8337:                pWriter
8338:                        .println("                    if (sLogger.isDebugEnabled())");
8339:                pWriter
8340:                        .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lNewRecord.InstanceId);");
8341:                pWriter.println("                    lCurrentStatement."
8342:                        + getDataBaseMetaData().suggestStatementSetMethod(
8343:                                lInstanceIdDatatype)
8344:                        + "( lParameterIndex++, TypesConvertor.getSqlValueFrom"
8345:                        + getUniqueDatatypeName(lInstanceIdDatatype)
8346:                        + "(lNewRecord.InstanceId));");
8347:                if (lIsModifiable) {
8348:                    pWriter
8349:                            .println("                    if (sLogger.isDebugEnabled())");
8350:                    pWriter
8351:                            .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lNewRecord.VersionId);");
8352:                    pWriter
8353:                            .println("                    lCurrentStatement."
8354:                                    + getDataBaseMetaData()
8355:                                            .suggestStatementSetMethod(
8356:                                                    lVersionIdDatatype)
8357:                                    + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
8358:                                    + getUniqueDatatypeName(lVersionIdDatatype)
8359:                                    + "(lNewRecord.VersionId));");
8360:                }
8361:                if (lHasState) {
8362:                    pWriter
8363:                            .println("                    if (sLogger.isDebugEnabled())");
8364:                    pWriter
8365:                            .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lNewRecord."
8366:                                    + lEntityStylesheet
8367:                                            .getStateStorageStructureAttributeName()
8368:                                    + ");");
8369:                    pWriter
8370:                            .println("                    lCurrentStatement."
8371:                                    + getDataBaseMetaData()
8372:                                            .suggestStatementSetMethod(
8373:                                                    lStateDatatype)
8374:                                    + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
8375:                                    + getUniqueDatatypeName(lStateDatatype)
8376:                                    + "(lNewRecord."
8377:                                    + lEntityStylesheet
8378:                                            .getStateStorageStructureAttributeName()
8379:                                    + "));");
8380:                }
8381:                // Deal with attributes
8382:                for (Iterator lAttributesIterator = lAttributes.iterator(); lAttributesIterator
8383:                        .hasNext();) {
8384:                    Attribute lAttribute = (Attribute) lAttributesIterator
8385:                            .next();
8386:                    STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
8387:                            .getAttributeStylesheet(lAttribute);
8388:                    DataType lAttributeDatatype = lAttribute.getDataType();
8389:                    STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
8390:                            .getDatatypeTranslationStylesheet(lAttribute
8391:                                    .getDataType());
8392:                    DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
8393:                            .createFromName(lAttributeDatatypeTranslationStylesheet
8394:                                    .getSqlTypeName());
8395:                    if (lAttribute.isOptional()) {
8396:                        pWriter.println("                    if (lNewRecord."
8397:                                + lAttributeStylesheet.getNormalisedName()
8398:                                + " != null && lNewRecord."
8399:                                + lAttributeStylesheet.getNormalisedName()
8400:                                + ".isEmpty() == false)");
8401:                        pWriter.println("                    {");
8402:                        // Limit output at 30 characters we only do it for attributes as other parameters are quite short an also might be important for debugging
8403:                        pWriter
8404:                                .println("                        if (sLogger.isDebugEnabled())");
8405:                        pWriter
8406:                                .println("                            sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + com.metaboss.util.StringUtils.suggestTruncatedOutput(lNewRecord."
8407:                                        + lAttributeStylesheet
8408:                                                .getNormalisedName()
8409:                                        + ".toString(),30));");
8410:                        pWriter
8411:                                .println("                        lCurrentStatement."
8412:                                        + getDataBaseMetaData()
8413:                                                .suggestStatementSetMethod(
8414:                                                        lAttributeDatatype)
8415:                                        + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
8416:                                        + getUniqueDatatypeName(lAttributeDatatype)
8417:                                        + "(lNewRecord."
8418:                                        + lAttributeStylesheet
8419:                                                .getNormalisedName() + "));");
8420:                        pWriter.println("                    }");
8421:                    } else {
8422:                        // Limit output at 30 characters we only do it for attributes as other parameters are quite short an also might be important for debugging
8423:                        pWriter
8424:                                .println("                    if (sLogger.isDebugEnabled())");
8425:                        pWriter
8426:                                .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + com.metaboss.util.StringUtils.suggestTruncatedOutput(lNewRecord."
8427:                                        + lAttributeStylesheet
8428:                                                .getNormalisedName()
8429:                                        + ".toString(),30));");
8430:                        pWriter
8431:                                .println("                    lCurrentStatement."
8432:                                        + getDataBaseMetaData()
8433:                                                .suggestStatementSetMethod(
8434:                                                        lAttributeDatatype)
8435:                                        + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
8436:                                        + getUniqueDatatypeName(lAttributeDatatype)
8437:                                        + "(lNewRecord."
8438:                                        + lAttributeStylesheet
8439:                                                .getNormalisedName() + "));");
8440:                    }
8441:                }
8442:                // Deal with associations
8443:                for (Iterator lReferencesIterator = lReferences.iterator(); lReferencesIterator
8444:                        .hasNext();) {
8445:                    AssociationRole lRole = (AssociationRole) lReferencesIterator
8446:                            .next();
8447:                    // Association constraint is only necessary if this entity has a reference
8448:                    if (CommonUtil.doesEntityStoreReference(lRole)) {
8449:                        DataType lRoleEntityInstanceIdDatatype = lRole
8450:                                .getEntity().getInstanceIdDataType();
8451:                        if (lRole.isOptional()) {
8452:                            pWriter
8453:                                    .println("                    if (lNewRecord."
8454:                                            + lRole.getName()
8455:                                            + "InstanceId != null && lNewRecord."
8456:                                            + lRole.getName()
8457:                                            + "InstanceId.isEmpty() == false)");
8458:                            pWriter.println("                    {");
8459:                            pWriter
8460:                                    .println("                        if (sLogger.isDebugEnabled())");
8461:                            pWriter
8462:                                    .println("                            sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lNewRecord."
8463:                                            + lRole.getName() + "InstanceId);");
8464:                            pWriter
8465:                                    .println("                        lCurrentStatement."
8466:                                            + getDataBaseMetaData()
8467:                                                    .suggestStatementSetMethod(
8468:                                                            lRoleEntityInstanceIdDatatype)
8469:                                            + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
8470:                                            + getUniqueDatatypeName(lRoleEntityInstanceIdDatatype)
8471:                                            + "(lNewRecord."
8472:                                            + lRole.getName()
8473:                                            + "InstanceId));");
8474:                            pWriter.println("                    }");
8475:                        } else {
8476:                            pWriter
8477:                                    .println("                    if (sLogger.isDebugEnabled())");
8478:                            pWriter
8479:                                    .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lNewRecord."
8480:                                            + lRole.getName() + "InstanceId);");
8481:                            pWriter
8482:                                    .println("                    lCurrentStatement."
8483:                                            + getDataBaseMetaData()
8484:                                                    .suggestStatementSetMethod(
8485:                                                            lRoleEntityInstanceIdDatatype)
8486:                                            + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
8487:                                            + getUniqueDatatypeName(lRoleEntityInstanceIdDatatype)
8488:                                            + "(lNewRecord."
8489:                                            + lRole.getName()
8490:                                            + "InstanceId));");
8491:                        }
8492:                    }
8493:                }
8494:                pWriter
8495:                        .println("                    lCurrentStatement.addBatch();");
8496:                pWriter.println("                }");
8497:                pWriter
8498:                        .println("                lCurrentStatement.executeBatch();");
8499:                pWriter.println("                lCurrentStatement.close();");
8500:                pWriter.println("                lCurrentStatement = null;");
8501:                pWriter.println("            }");
8502:                pWriter.println("            finally");
8503:                pWriter.println("            {");
8504:                pWriter
8505:                        .println("                if (lCurrentStatement != null)");
8506:                pWriter
8507:                        .println("                    lCurrentStatement.close();");
8508:                pWriter.println("            }");
8509:                pWriter.println("        }");
8510:                pWriter
8511:                        .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
8512:                pWriter.println("        {");
8513:                pWriter
8514:                        .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for empty instance\",e);");
8515:                pWriter.println("        }");
8516:                pWriter
8517:                        .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
8518:                pWriter.println("        {");
8519:                pWriter
8520:                        .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for concealed instance\",e);");
8521:                pWriter.println("        }");
8522:                writeSQLExceptionHandlerForInsertEntity(pWriter, pEntity,
8523:                        lEntityTable);
8524:                pWriter.println("    }");
8525:            }
8526:
8527:            // This helper writes out the SQLException catch block for the insert entity operation
8528:            // The body of the catch block must resut in throwing some kind of PSException 
8529:            protected void writeSQLExceptionHandlerForInsertEntity(
8530:                    PrintWriter pWriter, Entity pEntity,
8531:                    RelationalEntityTable pEntityTable) throws BSException {
8532:                STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
8533:                        .getEntityStylesheet(pEntity);
8534:
8535:                String lEntityTableName = pEntityTable.getNameOverride();
8536:                if (lEntityTableName == null || lEntityTableName.length() == 0)
8537:                    lEntityTableName = pEntityTable.getNameSuggestion();
8538:
8539:                pWriter.println("        catch(java.sql.SQLException e)");
8540:                pWriter.println("        {");
8541:                pWriter
8542:                        .println("            String lMessage = e.getMessage();");
8543:                pWriter.println("            if (lMessage != null)");
8544:                pWriter.println("            {");
8545:                pWriter.println("                lMessage = lMessage.trim();");
8546:                pWriter
8547:                        .println("                if (lMessage.startsWith(\"INSERT on table '"
8548:                                + lEntityTableName.toUpperCase()
8549:                                + "' caused a violation of foreign key constraint '\"))");
8550:                pWriter
8551:                        .println("                    throw new PSAssociationConstraintViolationException(\"Error on insert("
8552:                                + lEntityStylesheet.getStorageRecordFullName()
8553:                                + ")\", e);");
8554:                pWriter
8555:                        .println("                if (lMessage.startsWith(\"The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint\"))");
8556:                pWriter
8557:                        .println("                    throw new PSAttributeConstraintViolationException(\"Error on insert("
8558:                                + lEntityStylesheet.getStorageRecordFullName()
8559:                                + ")\", e);");
8560:                pWriter.println("            }");
8561:                pWriter
8562:                        .println("            throw new PSDataSourceOperationInvocationException(\"Error on insert("
8563:                                + lEntityStylesheet.getStorageRecordFullName()
8564:                                + ")\", e);");
8565:                pWriter.println("        }");
8566:            }
8567:
8568:            // This helper writes out the SQLException catch block for the update entity operation
8569:            // The body of the catch block must resut in throwing some kind of PSException 
8570:            protected void writeSQLExceptionHandlerForUpdateEntity(
8571:                    PrintWriter pWriter, Entity pEntity,
8572:                    RelationalEntityTable pEntityTable) throws BSException {
8573:                STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
8574:                        .getEntityStylesheet(pEntity);
8575:
8576:                String lEntityTableName = pEntityTable.getNameOverride();
8577:                if (lEntityTableName == null || lEntityTableName.length() == 0)
8578:                    lEntityTableName = pEntityTable.getNameSuggestion();
8579:
8580:                pWriter.println("        catch(java.sql.SQLException e)");
8581:                pWriter.println("        {");
8582:                pWriter
8583:                        .println("            String lMessage = e.getMessage();");
8584:                pWriter.println("            if (lMessage != null)");
8585:                pWriter.println("            {");
8586:                pWriter.println("                lMessage = lMessage.trim();");
8587:                pWriter
8588:                        .println("                if (lMessage.startsWith(\"UPDATE on table '"
8589:                                + lEntityTableName.toUpperCase()
8590:                                + "' caused a violation of foreign key constraint '\"))");
8591:                pWriter
8592:                        .println("                    throw new PSAssociationConstraintViolationException(\"Error on update("
8593:                                + lEntityStylesheet.getStorageRecordFullName()
8594:                                + ")\", e);");
8595:                pWriter
8596:                        .println("                if (lMessage.startsWith(\"The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint\"))");
8597:                pWriter
8598:                        .println("                    throw new PSAttributeConstraintViolationException(\"Error on update("
8599:                                + lEntityStylesheet.getStorageRecordFullName()
8600:                                + ")\", e);");
8601:                pWriter.println("            }");
8602:                pWriter
8603:                        .println("            throw new PSDataSourceOperationInvocationException(\"Error on update("
8604:                                + lEntityStylesheet.getStorageRecordFullName()
8605:                                + ")\", e);");
8606:                pWriter.println("        }");
8607:            }
8608:
8609:            // This hepler writes out the helper method to delete the entity record
8610:            protected void writeDeleteEntityHelperOperation(
8611:                    PrintWriter pWriter, Entity pTopEntity, Entity pEntity,
8612:                    DomainRelationalStorageDefinition pDomainStorage)
8613:                    throws BOException, BSException {
8614:                STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
8615:                        .getEntityStylesheet(pEntity);
8616:
8617:                DataType lTopEntityInstanceIdDatatype = pTopEntity
8618:                        .getInstanceIdDataType();
8619:                STDatatypeStylesheet lTopEntityInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
8620:                        .getDatatypeStylesheet(lTopEntityInstanceIdDatatype);
8621:                STDatatypeTranslationStylesheet lTopEntityInstanceIdDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
8622:                        .getDatatypeTranslationStylesheet(lTopEntityInstanceIdDatatype);
8623:                DataTypeTranslationMetadata.SqlType lInstanceIdDatatypeSqlType = DataTypeTranslationMetadata.SqlType
8624:                        .createFromName(lTopEntityInstanceIdDatatypeTranslationStylesheet
8625:                                .getSqlTypeName());
8626:
8627:                RelationalEntityTable lEntityTable = pDomainStorage
8628:                        .getEntityTable(pEntity);
8629:                String lEntityTableName = lEntityTable.getNameOverride();
8630:                if (lEntityTableName == null || lEntityTableName.length() == 0)
8631:                    lEntityTableName = lEntityTable.getNameSuggestion();
8632:                String lInstanceIdColumnName = lEntityTable
8633:                        .getInstanceIdColumnNameOverride();
8634:                if (lInstanceIdColumnName == null
8635:                        || lInstanceIdColumnName.length() == 0)
8636:                    lInstanceIdColumnName = lEntityTable
8637:                            .getInstanceIdColumnNameSuggestion();
8638:
8639:                pWriter.println();
8640:                pWriter.println("    // Helper. Deletes one or more "
8641:                        + pEntity.getName() + " records from the database");
8642:                pWriter.print("    private static final String sTextOf"
8643:                        + pEntity.getName()
8644:                        + "DeleteStatement = \"DELETE FROM ");
8645:                pWriter.print(lEntityTableName);
8646:                pWriter.print(" WHERE ");
8647:                pWriter.print(lInstanceIdColumnName);
8648:                pWriter.println(" = ?\";");
8649:                pWriter.println("    private void delete"
8650:                        + pEntity.getName()
8651:                        + "Records( java.sql.Connection pConnection, "
8652:                        + lTopEntityInstanceIdDatatypeStylesheet
8653:                                .getClassFullName()
8654:                        + "[] pInstanceIdsToDelete) throws PSException");
8655:                pWriter.println("    {");
8656:                pWriter
8657:                        .println("        java.sql.PreparedStatement lDeleteStatement = null;");
8658:                pWriter.println("        try");
8659:                pWriter.println("        {");
8660:                pWriter.println("            if (sLogger.isDebugEnabled())");
8661:                pWriter
8662:                        .println("                sLogger.debug(\"About to execute SQL statement: \" + sTextOf"
8663:                                + pEntity.getName()
8664:                                + "DeleteStatement + \";\");");
8665:                pWriter
8666:                        .println("            lDeleteStatement = pConnection.prepareStatement(sTextOf"
8667:                                + pEntity.getName() + "DeleteStatement);");
8668:                pWriter.println("            try");
8669:                pWriter.println("            {");
8670:                pWriter
8671:                        .println("                lDeleteStatement.clearBatch();");
8672:                pWriter
8673:                        .println("                for (int i = 0; i < pInstanceIdsToDelete.length; i++)");
8674:                pWriter.println("                {");
8675:                pWriter.print("                    ");
8676:                pWriter.print(lTopEntityInstanceIdDatatypeStylesheet
8677:                        .getClassFullName());
8678:                pWriter
8679:                        .println(" lInstanceIdToDelete = pInstanceIdsToDelete[i];");
8680:                pWriter
8681:                        .println("                    if (lInstanceIdToDelete == null)");
8682:                pWriter
8683:                        .print("                        throw new PSAttributeConstraintViolationException(\"");
8684:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
8685:                pWriter
8686:                        .println(".InstanceId is not expected to be undefined for delete() operation.\");");
8687:                pWriter
8688:                        .println("                    if (lInstanceIdToDelete.isEmpty())");
8689:                pWriter
8690:                        .print("                        throw new PSAttributeConstraintViolationException(\"");
8691:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
8692:                pWriter
8693:                        .println(".InstanceId is not expected to be empty for delete() operation.\");");
8694:                pWriter
8695:                        .println("                    if (lInstanceIdToDelete.isConcealed())");
8696:                pWriter
8697:                        .print("                        throw new PSAttributeConstraintViolationException(\"");
8698:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
8699:                pWriter
8700:                        .println(".InstanceId is not expected to be concealed for delete() operation.\");");
8701:                pWriter
8702:                        .println("                    if (sLogger.isDebugEnabled())");
8703:                pWriter
8704:                        .println("                        sLogger.debug(\"Parameter 1 value: \" + lInstanceIdToDelete);");
8705:                pWriter.print("                    lDeleteStatement.");
8706:                pWriter.print(getDataBaseMetaData().suggestStatementSetMethod(
8707:                        lTopEntityInstanceIdDatatype));
8708:                pWriter.println("( 1, TypesConvertor.getSqlValueFrom"
8709:                        + getUniqueDatatypeName(lTopEntityInstanceIdDatatype)
8710:                        + "(lInstanceIdToDelete));");
8711:                pWriter
8712:                        .println("                    lDeleteStatement.addBatch();");
8713:                pWriter.println("                }");
8714:                pWriter
8715:                        .println("                lDeleteStatement.executeBatch();");
8716:                pWriter.println("            }");
8717:                pWriter.println("            finally");
8718:                pWriter.println("            {");
8719:                pWriter
8720:                        .println("                if (lDeleteStatement != null)");
8721:                pWriter
8722:                        .println("                    lDeleteStatement.close();");
8723:                pWriter.println("            }");
8724:                pWriter.println("        }");
8725:                pWriter
8726:                        .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
8727:                pWriter.println("        {");
8728:                pWriter
8729:                        .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for empty instance\",e);");
8730:                pWriter.println("        }");
8731:                pWriter
8732:                        .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
8733:                pWriter.println("        {");
8734:                pWriter
8735:                        .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for concealed instance\",e);");
8736:                pWriter.println("        }");
8737:                pWriter.println("        catch(java.sql.SQLException e)");
8738:                pWriter.println("        {");
8739:                pWriter
8740:                        .print("            throw new PSDataSourceOperationInvocationException(\"Error on delete(");
8741:                pWriter.print(lEntityStylesheet.getStorageRecordFullName());
8742:                pWriter.println(")\", e);");
8743:                pWriter.println("        }");
8744:                pWriter.println("    }");
8745:            }
8746:
8747:            // This hepler writes out the helpwer method to insert the entity record
8748:            protected void writeOptionalUpdateEntityHelperOperation(
8749:                    PrintWriter pWriter, Entity pEntity,
8750:                    DomainRelationalStorageDefinition pDomainStorage)
8751:                    throws BOException, BSException {
8752:                if (pEntity.isModifiable()) {
8753:                    // This should be in storage definition latter on
8754:                    boolean lUpdateInBatches = false;
8755:
8756:                    STEntityStylesheet lEntityStylesheet = CodeGenerationStylesheetAccessor
8757:                            .getEntityStylesheet(pEntity);
8758:
8759:                    Collection lAttributes = pEntity.getAttributes();
8760:                    Collection lReferences = pEntity.getReferences();
8761:
8762:                    DataType lInstanceIdDatatype = pEntity
8763:                            .getInstanceIdDataType();
8764:                    STDatatypeStylesheet lInstanceIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
8765:                            .getDatatypeStylesheet(lInstanceIdDatatype);
8766:
8767:                    DataType lVersionIdDatatype = pEntity
8768:                            .getVersionIdDataType();
8769:                    STDatatypeStylesheet lVersionIdDatatypeStylesheet = CodeGenerationStylesheetAccessor
8770:                            .getDatatypeStylesheet(lVersionIdDatatype);
8771:
8772:                    boolean lHasState = pEntity.getStateMachine() != null;
8773:                    DataType lStateDatatype = (lHasState) ? pEntity
8774:                            .getStateDataType() : null;
8775:                    STDatatypeStylesheet lStateDatatypeStylesheet = (lHasState) ? CodeGenerationStylesheetAccessor
8776:                            .getDatatypeStylesheet(lStateDatatype)
8777:                            : null;
8778:
8779:                    RelationalEntityTable lEntityTable = pDomainStorage
8780:                            .getEntityTable(pEntity);
8781:                    String lEntityTableName = lEntityTable.getNameOverride();
8782:                    if (lEntityTableName == null
8783:                            || lEntityTableName.length() == 0)
8784:                        lEntityTableName = lEntityTable.getNameSuggestion();
8785:
8786:                    String lInstanceIdColumnName = lEntityTable
8787:                            .getInstanceIdColumnNameOverride();
8788:                    if (lInstanceIdColumnName == null
8789:                            || lInstanceIdColumnName.length() == 0)
8790:                        lInstanceIdColumnName = lEntityTable
8791:                                .getInstanceIdColumnNameSuggestion();
8792:
8793:                    String lVersionIdColumnName = lVersionIdColumnName = lEntityTable
8794:                            .getVersionIdColumnNameOverride();
8795:                    if (lVersionIdColumnName == null
8796:                            || lVersionIdColumnName.length() == 0)
8797:                        lVersionIdColumnName = lEntityTable
8798:                                .getVersionIdColumnNameSuggestion();
8799:
8800:                    String lStateColumnName = null;
8801:                    if (lHasState) {
8802:                        lStateColumnName = lEntityTable
8803:                                .getStateColumnNameOverride();
8804:                        if (lStateColumnName == null
8805:                                || lStateColumnName.length() == 0)
8806:                            lStateColumnName = lEntityTable
8807:                                    .getStateColumnNameSuggestion();
8808:                    }
8809:                    pWriter.println();
8810:                    pWriter.println("    // Inserts one or more new "
8811:                            + pEntity.getName() + " records into the database");
8812:                    pWriter.println("    private void update"
8813:                            + pEntity.getName()
8814:                            + "Records( java.sql.Connection pConnection, "
8815:                            + lEntityStylesheet.getStorageRecordFullName()
8816:                            + "[] pModifiedRecords) throws PSException");
8817:                    pWriter.println("    {");
8818:                    pWriter.println("        try");
8819:                    pWriter.println("        {");
8820:                    if (lUpdateInBatches) {
8821:                        pWriter
8822:                                .println("            java.sql.CallableStatement lCurrentStatement = null;");
8823:                    } else {
8824:                        pWriter
8825:                                .println("            java.sql.PreparedStatement lCurrentStatement = null;");
8826:                    }
8827:                    pWriter
8828:                            .println("            String lCurrentTextOfUpdateStatement = null;");
8829:                    pWriter.println("            try");
8830:                    pWriter.println("            {");
8831:                    if (lUpdateInBatches) {
8832:                        pWriter
8833:                                .println("                int lCurrentBatchBaseIndex = 0;");
8834:                    }
8835:                    pWriter
8836:                            .println("                StringBuffer lProposedTextOfUpdate = new StringBuffer();");
8837:                    pWriter
8838:                            .println("                for (int i = 0; i < pModifiedRecords.length; i++)");
8839:                    pWriter.println("                {");
8840:                    pWriter.println("                    "
8841:                            + lEntityStylesheet.getStorageRecordFullName()
8842:                            + " lModifiedRecord = pModifiedRecords[i];");
8843:                    pWriter
8844:                            .println("                    // InstanceId is mandatory");
8845:                    pWriter
8846:                            .println("                    if (lModifiedRecord.InstanceId == null)");
8847:                    pWriter
8848:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8849:                                    + lEntityStylesheet
8850:                                            .getStorageRecordFullName()
8851:                                    + ".InstanceId is not expected to be undefined for update() operation.\");");
8852:                    pWriter
8853:                            .println("                    if (lModifiedRecord.InstanceId.isEmpty())");
8854:                    pWriter
8855:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8856:                                    + lEntityStylesheet
8857:                                            .getStorageRecordFullName()
8858:                                    + ".InstanceId is not expected to be empty for update() operation.\");");
8859:                    pWriter
8860:                            .println("                    if (lModifiedRecord.InstanceId.isConcealed())");
8861:                    pWriter
8862:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8863:                                    + lEntityStylesheet
8864:                                            .getStorageRecordFullName()
8865:                                    + ".InstanceId is not expected to be concealed for update() operation.\");");
8866:                    pWriter
8867:                            .println("                    // VersionId is mandatory");
8868:                    pWriter
8869:                            .println("                    if (lModifiedRecord.VersionId == null)");
8870:                    pWriter
8871:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8872:                                    + lEntityStylesheet
8873:                                            .getStorageRecordFullName()
8874:                                    + ".VersionId is not expected to be undefined for update() operation.\");");
8875:                    pWriter
8876:                            .println("                    if (lModifiedRecord.VersionId.isEmpty())");
8877:                    pWriter
8878:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8879:                                    + lEntityStylesheet
8880:                                            .getStorageRecordFullName()
8881:                                    + ".VersionId is not expected to be empty for update() operation.\");");
8882:                    pWriter
8883:                            .println("                    if (lModifiedRecord.VersionId.isConcealed())");
8884:                    pWriter
8885:                            .println("                        throw new PSAttributeConstraintViolationException(\""
8886:                                    + lEntityStylesheet
8887:                                            .getStorageRecordFullName()
8888:                                    + ".VersionId is not expected to be concealed for update() operation.\");");
8889:                    pWriter
8890:                            .println("                    lProposedTextOfUpdate.setLength(0);");
8891:                    pWriter
8892:                            .println("                    lProposedTextOfUpdate.append(\"UPDATE "
8893:                                    + lEntityTableName
8894:                                    + " SET "
8895:                                    + lVersionIdColumnName + " = ?\");");
8896:                    if (lHasState) {
8897:                        pWriter
8898:                                .println("                    // State may not be submitted for update, which is perfectly valid");
8899:                        pWriter
8900:                                .println("                    if (lModifiedRecord."
8901:                                        + lEntityStylesheet
8902:                                                .getStateStorageStructureAttributeName()
8903:                                        + " != null)");
8904:                        pWriter.println("                    {");
8905:                        pWriter
8906:                                .println("                        if (lModifiedRecord."
8907:                                        + lEntityStylesheet
8908:                                                .getStateStorageStructureAttributeName()
8909:                                        + ".isEmpty())");
8910:                        pWriter
8911:                                .println("                            throw new PSAttributeConstraintViolationException(\""
8912:                                        + lEntityStylesheet
8913:                                                .getStorageRecordFullName()
8914:                                        + "."
8915:                                        + lEntityStylesheet
8916:                                                .getStateStorageStructureAttributeName()
8917:                                        + " is not expected to be empty for update() operation.\");");
8918:                        pWriter
8919:                                .println("                        if (lModifiedRecord."
8920:                                        + lEntityStylesheet
8921:                                                .getStateStorageStructureAttributeName()
8922:                                        + ".isConcealed())");
8923:                        pWriter
8924:                                .println("                            throw new PSAttributeConstraintViolationException(\""
8925:                                        + lEntityStylesheet
8926:                                                .getStorageRecordFullName()
8927:                                        + "."
8928:                                        + lEntityStylesheet
8929:                                                .getStateStorageStructureAttributeName()
8930:                                        + " is not expected to be concealed for update() operation.\");");
8931:                        pWriter
8932:                                .println("                        lProposedTextOfUpdate.append(\" ,"
8933:                                        + lStateColumnName + " = ?\");");
8934:                        pWriter.println("                    }");
8935:                    }
8936:                    for (Iterator lAttributesIterator = lAttributes.iterator(); lAttributesIterator
8937:                            .hasNext();) {
8938:                        Attribute lAttribute = (Attribute) lAttributesIterator
8939:                                .next();
8940:                        STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
8941:                                .getAttributeStylesheet(lAttribute);
8942:                        RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
8943:                                .getAttributeColumn(lAttribute);
8944:                        String lAttributeColumnName = lRelationalEntityTableAttribute
8945:                                .getColumnNameOverride();
8946:                        if (lAttributeColumnName == null
8947:                                || lAttributeColumnName.length() == 0)
8948:                            lAttributeColumnName = lRelationalEntityTableAttribute
8949:                                    .getColumnNameSuggestion();
8950:                        DataType lAttributeDatatype = lAttribute.getDataType();
8951:                        STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
8952:                                .getDatatypeTranslationStylesheet(lAttribute
8953:                                        .getDataType());
8954:                        DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
8955:                                .createFromName(lAttributeDatatypeTranslationStylesheet
8956:                                        .getSqlTypeName());
8957:                        pWriter
8958:                                .println("                    if (lModifiedRecord."
8959:                                        + lAttributeStylesheet
8960:                                                .getNormalisedName()
8961:                                        + " != null)");
8962:                        pWriter.println("                    {");
8963:                        pWriter
8964:                                .println("                        if (lModifiedRecord."
8965:                                        + lAttributeStylesheet
8966:                                                .getNormalisedName()
8967:                                        + ".isConcealed())");
8968:                        pWriter
8969:                                .println("                            throw new PSAttributeConstraintViolationException(\""
8970:                                        + lEntityStylesheet
8971:                                                .getStorageRecordFullName()
8972:                                        + "."
8973:                                        + lAttribute.getName()
8974:                                        + " is not expected to be concealed for update() operation.\");");
8975:                        if (lAttribute.isOptional()) {
8976:                            // Do not even bother inserting optional attribute - null will just appear automatically
8977:                            pWriter.println("                        // "
8978:                                    + lAttribute.getName() + " is optional");
8979:                        } else {
8980:                            pWriter.println("                        // "
8981:                                    + lAttribute.getName() + " is mandatory");
8982:                            pWriter
8983:                                    .println("                        if (lModifiedRecord."
8984:                                            + lAttributeStylesheet
8985:                                                    .getNormalisedName()
8986:                                            + ".isEmpty())");
8987:                            pWriter
8988:                                    .println("                            throw new PSAttributeConstraintViolationException(\""
8989:                                            + lEntityStylesheet
8990:                                                    .getStorageRecordFullName()
8991:                                            + "."
8992:                                            + lAttribute.getName()
8993:                                            + " is not expected to be empty for update() operation.\");");
8994:                        }
8995:                        pWriter
8996:                                .println("                        lProposedTextOfUpdate.append(\", "
8997:                                        + lAttributeColumnName + " = ?\");");
8998:                        pWriter.println("                    }");
8999:                    }
9000:                    // Deal with associations
9001:                    for (Iterator lReferencesIterator = lReferences.iterator(); lReferencesIterator
9002:                            .hasNext();) {
9003:                        AssociationRole lReference = (AssociationRole) lReferencesIterator
9004:                                .next();
9005:                        // Association constraint is only necessary if this entity has a reference
9006:                        if (CommonUtil.doesEntityStoreReference(lReference)) {
9007:                            RelationalEntityTableReferenceColumn lRelationalEntityTableAssociationRole = lEntityTable
9008:                                    .getReferenceColumn(lReference);
9009:                            String lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
9010:                                    .getColumnNameOverride();
9011:                            if (lAssociationRoleInstanceIdColumnName == null
9012:                                    || lAssociationRoleInstanceIdColumnName
9013:                                            .length() == 0)
9014:                                lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
9015:                                        .getColumnNameSuggestion();
9016:
9017:                            // Singular multiplicities resolved simply by having the other entity id as the member of the structure
9018:                            pWriter
9019:                                    .println("                    if (lModifiedRecord."
9020:                                            + lReference.getName()
9021:                                            + "InstanceId != null)");
9022:                            pWriter.println("                    {");
9023:                            pWriter
9024:                                    .println("                        if (lModifiedRecord."
9025:                                            + lReference.getName()
9026:                                            + "InstanceId.isConcealed())");
9027:                            pWriter
9028:                                    .println("                            throw new PSAttributeConstraintViolationException(\""
9029:                                            + lEntityStylesheet
9030:                                                    .getStorageRecordFullName()
9031:                                            + "."
9032:                                            + lReference.getName()
9033:                                            + "InstanceId is not expected to be concealed for update() operation.\");");
9034:                            // If cardinality is mandatory we need to disallow empty value
9035:                            if (!lReference.isOptional()) {
9036:                                pWriter
9037:                                        .println("                        if (lModifiedRecord."
9038:                                                + lReference.getName()
9039:                                                + "InstanceId.isEmpty())");
9040:                                pWriter
9041:                                        .println("                            throw new PSAttributeConstraintViolationException(\""
9042:                                                + lEntityStylesheet
9043:                                                        .getStorageRecordFullName()
9044:                                                + "."
9045:                                                + lReference.getName()
9046:                                                + "InstanceId is not expected to be empty for update() operation.\");");
9047:                            }
9048:                            pWriter
9049:                                    .println("                        lProposedTextOfUpdate.append(\","
9050:                                            + lAssociationRoleInstanceIdColumnName
9051:                                            + " = ?\");");
9052:                            pWriter.println("                    }");
9053:                        }
9054:                    }
9055:                    pWriter
9056:                            .println("                    lProposedTextOfUpdate.append(\" WHERE "
9057:                                    + lInstanceIdColumnName
9058:                                    + " = ? AND "
9059:                                    + lVersionIdColumnName + " = ?\");");
9060:                    pWriter
9061:                            .println("                    // We have built the statement for this insertion. Compare with saved one and make a decision to continue current batch or not");
9062:                    pWriter
9063:                            .println("                    String lProposedTextOfUpdateStatement = lProposedTextOfUpdate.toString();");
9064:                    if (lUpdateInBatches) {
9065:                        pWriter
9066:                                .println("                    if (lCurrentStatement != null)");
9067:                        pWriter.println("                    {");
9068:                        pWriter
9069:                                .println("                        if (!lCurrentTextOfUpdateStatement.equals(lProposedTextOfUpdateStatement))");
9070:                        pWriter.println("                        {");
9071:                        // Do the previous statement
9072:                        pWriter
9073:                                .println("                            int[] lBatchResult = lCurrentStatement.executeBatch();");
9074:                        pWriter
9075:                                .println("                            lCurrentStatement.close();");
9076:                        pWriter
9077:                                .println("                            lCurrentStatement = null;");
9078:                        // Verify that every statement has resulted in one and only one update
9079:                        pWriter
9080:                                .println("                            for (int lBatchResultIndex = 0; lBatchResultIndex < lBatchResult.length; lBatchResultIndex++)");
9081:                        pWriter.println("                            {");
9082:                        pWriter
9083:                                .println("                                if (lBatchResult[lBatchResultIndex] != 1)");
9084:                        pWriter
9085:                                .println("                                    throw new PSUpdateDataIntegrityViolationException(\"Unable to update "
9086:                                        + pEntity.getName()
9087:                                        + " record with Instance Id \" + pModifiedRecords[lCurrentBatchBaseIndex + lBatchResultIndex].InstanceId);");
9088:                        pWriter.println("                            }");
9089:                        pWriter.println("                        }");
9090:                        pWriter.println("                    }");
9091:                        pWriter
9092:                                .println("                    if (lCurrentStatement == null)");
9093:                        pWriter.println("                    {");
9094:                        pWriter
9095:                                .println("                        lCurrentTextOfUpdateStatement = lProposedTextOfUpdateStatement;");
9096:                        pWriter
9097:                                .println("                        if (sLogger.isDebugEnabled())");
9098:                        pWriter
9099:                                .println("                            sLogger.debug(\"About to execute SQL statement: \" + lCurrentTextOfUpdateStatement + \";\");");
9100:                        pWriter
9101:                                .println("                        lCurrentStatement = pConnection.prepareCall(lCurrentTextOfUpdateStatement);");
9102:                        pWriter
9103:                                .println("                        lCurrentBatchBaseIndex = i;");
9104:                        pWriter.println("                    }");
9105:                    } else {
9106:                        pWriter
9107:                                .println("                    if (lCurrentStatement != null)");
9108:                        pWriter.println("                    {");
9109:                        pWriter
9110:                                .println("                        if (!lCurrentTextOfUpdateStatement.equals(lProposedTextOfUpdateStatement))");
9111:                        pWriter.println("                        {");
9112:                        // Do the previous statement
9113:                        pWriter
9114:                                .println("                            lCurrentStatement.close();");
9115:                        pWriter
9116:                                .println("                            lCurrentStatement = null;");
9117:                        pWriter.println("                        }");
9118:                        pWriter.println("                    }");
9119:                        pWriter
9120:                                .println("                    if (lCurrentStatement == null)");
9121:                        pWriter.println("                    {");
9122:                        pWriter
9123:                                .println("                        lCurrentTextOfUpdateStatement = lProposedTextOfUpdateStatement;");
9124:                        pWriter
9125:                                .println("                        if (sLogger.isDebugEnabled())");
9126:                        pWriter
9127:                                .println("                            sLogger.debug(\"About to execute SQL statement: \" + lCurrentTextOfUpdateStatement + \";\");");
9128:                        pWriter
9129:                                .println("                        lCurrentStatement = pConnection.prepareStatement(lCurrentTextOfUpdateStatement);");
9130:                        pWriter.println("                    }");
9131:                    }
9132:
9133:                    // Now populate the statement
9134:                    pWriter
9135:                            .println("                    int lParameterIndex = 1;");
9136:                    pWriter
9137:                            .println("                    if (sLogger.isDebugEnabled())");
9138:                    pWriter
9139:                            .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lModifiedRecord."
9140:                                    + lEntityStylesheet
9141:                                            .getVersionIdStorageStructureAttributeName()
9142:                                    + ");");
9143:                    pWriter
9144:                            .println("                    lCurrentStatement."
9145:                                    + getDataBaseMetaData()
9146:                                            .suggestStatementSetMethod(
9147:                                                    lVersionIdDatatype)
9148:                                    + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9149:                                    + getUniqueDatatypeName(lVersionIdDatatype)
9150:                                    + "(lModifiedRecord."
9151:                                    + lEntityStylesheet
9152:                                            .getVersionIdStorageStructureAttributeName()
9153:                                    + "));");
9154:                    if (lHasState) {
9155:                        pWriter
9156:                                .println("                    if (lModifiedRecord."
9157:                                        + lEntityStylesheet
9158:                                                .getStateStorageStructureAttributeName()
9159:                                        + " != null)");
9160:                        pWriter.println("                    {");
9161:                        pWriter
9162:                                .println("                        if (sLogger.isDebugEnabled())");
9163:                        pWriter
9164:                                .println("                            sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lModifiedRecord."
9165:                                        + lEntityStylesheet
9166:                                                .getStateStorageStructureAttributeName()
9167:                                        + ");");
9168:                        pWriter
9169:                                .println("                        lCurrentStatement."
9170:                                        + getDataBaseMetaData()
9171:                                                .suggestStatementSetMethod(
9172:                                                        lStateDatatype)
9173:                                        + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9174:                                        + getUniqueDatatypeName(lStateDatatype)
9175:                                        + "(lModifiedRecord."
9176:                                        + lEntityStylesheet
9177:                                                .getStateStorageStructureAttributeName()
9178:                                        + "));");
9179:                        pWriter.println("                    }");
9180:                    }
9181:                    // Deal with attributes
9182:                    for (Iterator lAttributesIterator = lAttributes.iterator(); lAttributesIterator
9183:                            .hasNext();) {
9184:                        Attribute lAttribute = (Attribute) lAttributesIterator
9185:                                .next();
9186:                        STAttributeStylesheet lAttributeStylesheet = CodeGenerationStylesheetAccessor
9187:                                .getAttributeStylesheet(lAttribute);
9188:                        DataType lAttributeDatatype = lAttribute.getDataType();
9189:                        STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
9190:                                .getDatatypeTranslationStylesheet(lAttribute
9191:                                        .getDataType());
9192:                        DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
9193:                                .createFromName(lAttributeDatatypeTranslationStylesheet
9194:                                        .getSqlTypeName());
9195:                        pWriter
9196:                                .println("                    if (lModifiedRecord."
9197:                                        + lAttributeStylesheet
9198:                                                .getNormalisedName()
9199:                                        + " != null)");
9200:                        pWriter.println("                    {");
9201:                        if (lAttribute.isOptional()) {
9202:                            pWriter
9203:                                    .println("                        if (lModifiedRecord."
9204:                                            + lAttributeStylesheet
9205:                                                    .getNormalisedName()
9206:                                            + ".isEmpty())");
9207:                            pWriter.println("                        {");
9208:                            pWriter
9209:                                    .println("                            if (sLogger.isDebugEnabled())");
9210:                            pWriter
9211:                                    .println("                                sLogger.debug(\"Parameter \" + lParameterIndex + \" is null\");");
9212:                            pWriter
9213:                                    .println("                            lCurrentStatement.setNull( lParameterIndex++, "
9214:                                            + getDataBaseMetaData()
9215:                                                    .suggestJDBCMetadataId(
9216:                                                            lAttributeDatatype)
9217:                                            + ");");
9218:                            pWriter.println("                        }");
9219:                            pWriter.println("                        else");
9220:                            pWriter.println("                        {");
9221:                            // Limit output at 30 characters we only do it for attributes as other parameters are quite short an also might be important for debugging
9222:                            pWriter
9223:                                    .println("                            if (sLogger.isDebugEnabled())");
9224:                            pWriter
9225:                                    .println("                                sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + com.metaboss.util.StringUtils.suggestTruncatedOutput(lModifiedRecord."
9226:                                            + lAttributeStylesheet
9227:                                                    .getNormalisedName()
9228:                                            + ".toString(),30));");
9229:                            pWriter
9230:                                    .println("                            lCurrentStatement."
9231:                                            + getDataBaseMetaData()
9232:                                                    .suggestStatementSetMethod(
9233:                                                            lAttributeDatatype)
9234:                                            + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9235:                                            + getUniqueDatatypeName(lAttributeDatatype)
9236:                                            + "(lModifiedRecord."
9237:                                            + lAttributeStylesheet
9238:                                                    .getNormalisedName()
9239:                                            + "));");
9240:                            pWriter.println("                        }");
9241:                        } else {
9242:                            // Limit output at 30 characters we only do it for attributes as other parameters are quite short an also might be important for debugging
9243:                            pWriter
9244:                                    .println("                        if (sLogger.isDebugEnabled())");
9245:                            pWriter
9246:                                    .println("                            sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + com.metaboss.util.StringUtils.suggestTruncatedOutput(lModifiedRecord."
9247:                                            + lAttributeStylesheet
9248:                                                    .getNormalisedName()
9249:                                            + ".toString(),30));");
9250:                            pWriter
9251:                                    .println("                        lCurrentStatement."
9252:                                            + getDataBaseMetaData()
9253:                                                    .suggestStatementSetMethod(
9254:                                                            lAttributeDatatype)
9255:                                            + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9256:                                            + getUniqueDatatypeName(lAttributeDatatype)
9257:                                            + "(lModifiedRecord."
9258:                                            + lAttributeStylesheet
9259:                                                    .getNormalisedName()
9260:                                            + "));");
9261:                        }
9262:                        pWriter.println("                    }");
9263:                    }
9264:                    // Deal with associations
9265:                    for (Iterator lReferencesIterator = lReferences.iterator(); lReferencesIterator
9266:                            .hasNext();) {
9267:                        AssociationRole lRole = (AssociationRole) lReferencesIterator
9268:                                .next();
9269:                        // Association constraint is only necessary if this entity has a reference
9270:                        if (CommonUtil.doesEntityStoreReference(lRole)) {
9271:                            DataType lRoleEntityInstanceIdDatatype = lRole
9272:                                    .getEntity().getInstanceIdDataType();
9273:                            pWriter
9274:                                    .println("                    if (lModifiedRecord."
9275:                                            + lRole.getName()
9276:                                            + "InstanceId != null)");
9277:                            pWriter.println("                    {");
9278:                            if (lRole.isOptional()) {
9279:                                pWriter
9280:                                        .println("                        if (lModifiedRecord."
9281:                                                + lRole.getName()
9282:                                                + "InstanceId.isEmpty())");
9283:                                pWriter.println("                        {");
9284:                                pWriter
9285:                                        .println("                            if (sLogger.isDebugEnabled())");
9286:                                pWriter
9287:                                        .println("                                sLogger.debug(\"Parameter \" + lParameterIndex + \" is null\");");
9288:                                pWriter
9289:                                        .println("                            lCurrentStatement.setNull( lParameterIndex++, "
9290:                                                + getDataBaseMetaData()
9291:                                                        .suggestJDBCMetadataId(
9292:                                                                lRoleEntityInstanceIdDatatype)
9293:                                                + ");");
9294:                                pWriter.println("                        }");
9295:                                pWriter.println("                        else");
9296:                                pWriter.println("                        {");
9297:                                pWriter
9298:                                        .println("                            if (sLogger.isDebugEnabled())");
9299:                                pWriter
9300:                                        .println("                                sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lModifiedRecord."
9301:                                                + lRole.getName()
9302:                                                + "InstanceId);");
9303:                                pWriter
9304:                                        .println("                            lCurrentStatement."
9305:                                                + getDataBaseMetaData()
9306:                                                        .suggestStatementSetMethod(
9307:                                                                lRoleEntityInstanceIdDatatype)
9308:                                                + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9309:                                                + getUniqueDatatypeName(lRoleEntityInstanceIdDatatype)
9310:                                                + "(lModifiedRecord."
9311:                                                + lRole.getName()
9312:                                                + "InstanceId));");
9313:                                pWriter.println("                        }");
9314:                            } else {
9315:                                pWriter
9316:                                        .println("                        if (sLogger.isDebugEnabled())");
9317:                                pWriter
9318:                                        .println("                            sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lModifiedRecord."
9319:                                                + lRole.getName()
9320:                                                + "InstanceId);");
9321:                                pWriter
9322:                                        .println("                        lCurrentStatement."
9323:                                                + getDataBaseMetaData()
9324:                                                        .suggestStatementSetMethod(
9325:                                                                lRoleEntityInstanceIdDatatype)
9326:                                                + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9327:                                                + getUniqueDatatypeName(lRoleEntityInstanceIdDatatype)
9328:                                                + "(lModifiedRecord."
9329:                                                + lRole.getName()
9330:                                                + "InstanceId));");
9331:                            }
9332:                            pWriter.println("                    }");
9333:                        }
9334:                    }
9335:                    pWriter
9336:                            .println("                    if (sLogger.isDebugEnabled())");
9337:                    pWriter
9338:                            .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lModifiedRecord."
9339:                                    + lEntityStylesheet
9340:                                            .getInstanceIdStorageStructureAttributeName()
9341:                                    + ");");
9342:                    pWriter
9343:                            .println("                    lCurrentStatement."
9344:                                    + getDataBaseMetaData()
9345:                                            .suggestStatementSetMethod(
9346:                                                    lInstanceIdDatatype)
9347:                                    + "( lParameterIndex++, TypesConvertor.getSqlValueFrom"
9348:                                    + getUniqueDatatypeName(lInstanceIdDatatype)
9349:                                    + "(lModifiedRecord."
9350:                                    + lEntityStylesheet
9351:                                            .getInstanceIdStorageStructureAttributeName()
9352:                                    + "));");
9353:                    pWriter
9354:                            .println("                    "
9355:                                    + lVersionIdDatatypeStylesheet
9356:                                            .getClassFullName()
9357:                                    + " lPreviousVersionId = lModifiedRecord."
9358:                                    + lEntityStylesheet
9359:                                            .getVersionIdStorageStructureAttributeName()
9360:                                    + ".getPrevious();");
9361:                    pWriter
9362:                            .println("                    if (sLogger.isDebugEnabled())");
9363:                    pWriter
9364:                            .println("                        sLogger.debug(\"Parameter \" + lParameterIndex + \" value: \" + lPreviousVersionId);");
9365:                    pWriter
9366:                            .println("                    lCurrentStatement."
9367:                                    + getDataBaseMetaData()
9368:                                            .suggestStatementSetMethod(
9369:                                                    lVersionIdDatatype)
9370:                                    + "(lParameterIndex++, TypesConvertor.getSqlValueFrom"
9371:                                    + getUniqueDatatypeName(lVersionIdDatatype)
9372:                                    + "(lPreviousVersionId));");
9373:                    if (lUpdateInBatches) {
9374:                        pWriter
9375:                                .println("                    lCurrentStatement.addBatch();");
9376:                        pWriter.println("                }");
9377:                        pWriter
9378:                                .println("                int[] lBatchResult = lCurrentStatement.executeBatch();");
9379:                        pWriter
9380:                                .println("                lCurrentStatement.close();");
9381:                        pWriter
9382:                                .println("                lCurrentStatement = null;");
9383:                        // Verify that every statement has resulted in one and only one update
9384:                        pWriter
9385:                                .println("                for (int lBatchResultIndex = 0; lBatchResultIndex < lBatchResult.length; lBatchResultIndex++)");
9386:                        pWriter.println("                {");
9387:                        pWriter
9388:                                .println("                    if (lBatchResult[lBatchResultIndex] != 1)");
9389:                        pWriter
9390:                                .println("                        throw new PSUpdateDataIntegrityViolationException(\"Unable to update "
9391:                                        + pEntity.getName()
9392:                                        + " record with Instance Id \" + pModifiedRecords[lCurrentBatchBaseIndex + lBatchResultIndex].InstanceId + \". Expected updated rows count: 1. Actual updated rows count: \" + lBatchResult[lBatchResultIndex]);");
9393:                        pWriter.println("                }");
9394:                    } else {
9395:                        pWriter
9396:                                .println("                    int lRowCount = lCurrentStatement.executeUpdate();");
9397:                        pWriter
9398:                                .println("                    if (lRowCount != 1)");
9399:                        pWriter
9400:                                .println("                        throw new PSUpdateDataIntegrityViolationException(\"Unable to update "
9401:                                        + pEntity.getName()
9402:                                        + " record with Instance Id \" + pModifiedRecords[i].InstanceId + \". Expected updated rows count: 1. Actual updated rows count: \" + lRowCount);");
9403:                        pWriter.println("                }");
9404:                        pWriter
9405:                                .println("                lCurrentStatement.close();");
9406:                        pWriter
9407:                                .println("                lCurrentStatement = null;");
9408:                    }
9409:                    pWriter.println("            }");
9410:                    pWriter.println("            finally");
9411:                    pWriter.println("            {");
9412:                    pWriter
9413:                            .println("                if (lCurrentStatement != null)");
9414:                    pWriter
9415:                            .println("                    lCurrentStatement.close();");
9416:                    pWriter.println("            }");
9417:                    pWriter.println("        }");
9418:                    pWriter
9419:                            .println("        catch(DataTypeInvalidOperationForEmptyInstanceException e)");
9420:                    pWriter.println("        {");
9421:                    pWriter
9422:                            .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for empty instance\",e);");
9423:                    pWriter.println("        }");
9424:                    pWriter
9425:                            .println("        catch(DataTypeInvalidOperationForConcealedInstanceException e)");
9426:                    pWriter.println("        {");
9427:                    pWriter
9428:                            .println("            throw new PSUnexpectedProgramConditionException(\"Should not occur as generated code must check for concealed instance\",e);");
9429:                    pWriter.println("        }");
9430:                    writeSQLExceptionHandlerForUpdateEntity(pWriter, pEntity,
9431:                            lEntityTable);
9432:                    pWriter.println("    }");
9433:                }
9434:            }
9435:
9436:            // This hepler writes out additional helper methods may be required by the derived implementation generators
9437:            protected void writeOptionalServiceImplementationHelpers(
9438:                    PrintWriter pWriter, Entity pEntity,
9439:                    DomainRelationalStorageDefinition pDomainStorage)
9440:                    throws BOException, BSException {
9441:                // Nothing is written by default
9442:            }
9443:
9444:            private static class SelectStatementParts {
9445:                // Column list used in instance query - uses alias unique for table
9446:                // Includes clobs and blobs
9447:                public String WhatClauseForGetInstance;
9448:                // Column list used in inner collection query (or the only query if it is not paged) - uses alias unique for table
9449:                // Ommits clobs and blobs
9450:                public String WhatClauseForGetCollection;
9451:                // Column list used in outer query if it is paged - same as inner only uses constant and unique alias 
9452:                // Ommits clobs and blobs
9453:                public String WhatClauseForOuterQuery;
9454:            }
9455:
9456:            private static SelectStatementParts generateSelectStatementParts(
9457:                    Entity pEntity,
9458:                    DomainRelationalStorageDefinition pDomainStorage)
9459:                    throws BSException {
9460:                RelationalEntityTable lEntityTable = pDomainStorage
9461:                        .getEntityTable(pEntity);
9462:
9463:                String lEntityTableAlias = lEntityTable.getTableAlias();
9464:
9465:                String lInstanceIdColumnName = lEntityTable
9466:                        .getInstanceIdColumnNameOverride();
9467:                if (lInstanceIdColumnName == null
9468:                        || lInstanceIdColumnName.length() == 0)
9469:                    lInstanceIdColumnName = lEntityTable
9470:                            .getInstanceIdColumnNameSuggestion();
9471:
9472:                String lVersionIdColumnName = null;
9473:                if (pEntity.isModifiable()) {
9474:                    lVersionIdColumnName = lEntityTable
9475:                            .getVersionIdColumnNameOverride();
9476:                    if (lVersionIdColumnName == null
9477:                            || lVersionIdColumnName.length() == 0)
9478:                        lVersionIdColumnName = lEntityTable
9479:                                .getVersionIdColumnNameSuggestion();
9480:                }
9481:
9482:                String lStateColumnName = null;
9483:                if (pEntity.getStateMachine() != null) {
9484:                    lStateColumnName = lEntityTable
9485:                            .getStateColumnNameOverride();
9486:                    if (lStateColumnName == null
9487:                            || lStateColumnName.length() == 0)
9488:                        lStateColumnName = lEntityTable
9489:                                .getStateColumnNameSuggestion();
9490:                }
9491:
9492:                StringBuffer lColumnsForInstanceBuffer = new StringBuffer();
9493:                StringBuffer lInnerColumnsForCollectionBuffer = new StringBuffer();
9494:                StringBuffer lOuterColumnsForCollectionBuffer = new StringBuffer();
9495:
9496:                lColumnsForInstanceBuffer.append(lEntityTableAlias);
9497:                lColumnsForInstanceBuffer.append(".");
9498:                lColumnsForInstanceBuffer.append(lInstanceIdColumnName);
9499:
9500:                lInnerColumnsForCollectionBuffer.append(lEntityTableAlias);
9501:                lInnerColumnsForCollectionBuffer.append(".");
9502:                lInnerColumnsForCollectionBuffer.append(lInstanceIdColumnName);
9503:
9504:                lOuterColumnsForCollectionBuffer.append("A");
9505:                lOuterColumnsForCollectionBuffer.append(".");
9506:                lOuterColumnsForCollectionBuffer.append(lInstanceIdColumnName);
9507:
9508:                if (pEntity.isModifiable()) {
9509:                    lColumnsForInstanceBuffer.append(",");
9510:                    lColumnsForInstanceBuffer.append(lEntityTableAlias);
9511:                    lColumnsForInstanceBuffer.append(".");
9512:                    lColumnsForInstanceBuffer.append(lVersionIdColumnName);
9513:
9514:                    lInnerColumnsForCollectionBuffer.append(",");
9515:                    lInnerColumnsForCollectionBuffer.append(lEntityTableAlias);
9516:                    lInnerColumnsForCollectionBuffer.append(".");
9517:                    lInnerColumnsForCollectionBuffer
9518:                            .append(lVersionIdColumnName);
9519:
9520:                    lOuterColumnsForCollectionBuffer.append(",");
9521:                    lOuterColumnsForCollectionBuffer.append("A");
9522:                    lOuterColumnsForCollectionBuffer.append(".");
9523:                    lOuterColumnsForCollectionBuffer
9524:                            .append(lVersionIdColumnName);
9525:                }
9526:                if (pEntity.getStateMachine() != null) {
9527:                    lColumnsForInstanceBuffer.append(",");
9528:                    lColumnsForInstanceBuffer.append(lEntityTableAlias);
9529:                    lColumnsForInstanceBuffer.append(".");
9530:                    lColumnsForInstanceBuffer.append(lStateColumnName);
9531:
9532:                    lInnerColumnsForCollectionBuffer.append(",");
9533:                    lInnerColumnsForCollectionBuffer.append(lEntityTableAlias);
9534:                    lInnerColumnsForCollectionBuffer.append(".");
9535:                    lInnerColumnsForCollectionBuffer.append(lStateColumnName);
9536:
9537:                    lOuterColumnsForCollectionBuffer.append(",");
9538:                    lOuterColumnsForCollectionBuffer.append("A");
9539:                    lOuterColumnsForCollectionBuffer.append(".");
9540:                    lOuterColumnsForCollectionBuffer.append(lStateColumnName);
9541:                }
9542:                // Deal with attributes
9543:                for (Iterator lAttributesIterator = pEntity.getAttributes()
9544:                        .iterator(); lAttributesIterator.hasNext();) {
9545:                    Attribute lAttribute = (Attribute) lAttributesIterator
9546:                            .next();
9547:                    RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
9548:                            .getAttributeColumn(lAttribute);
9549:                    String lAttributeColumnName = lRelationalEntityTableAttribute
9550:                            .getColumnNameOverride();
9551:                    if (lAttributeColumnName == null
9552:                            || lAttributeColumnName.length() == 0)
9553:                        lAttributeColumnName = lRelationalEntityTableAttribute
9554:                                .getColumnNameSuggestion();
9555:
9556:                    // Add Lobs only to instance columns list
9557:                    // Add all others to both						
9558:                    STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
9559:                            .getDatatypeTranslationStylesheet(lAttribute
9560:                                    .getDataType());
9561:                    DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
9562:                            .createFromName(lAttributeDatatypeTranslationStylesheet
9563:                                    .getSqlTypeName());
9564:                    if (lAttributeDatatypeSqlType
9565:                            .equals(DataTypeTranslationMetadata.SQL_BLOB)
9566:                            || lAttributeDatatypeSqlType
9567:                                    .equals(DataTypeTranslationMetadata.SQL_CLOB)) {
9568:                        lColumnsForInstanceBuffer.append(",");
9569:                        lColumnsForInstanceBuffer.append(lEntityTableAlias);
9570:                        lColumnsForInstanceBuffer.append(".");
9571:                        lColumnsForInstanceBuffer.append(lAttributeColumnName);
9572:                    } else {
9573:                        lColumnsForInstanceBuffer.append(",");
9574:                        lColumnsForInstanceBuffer.append(lEntityTableAlias);
9575:                        lColumnsForInstanceBuffer.append(".");
9576:                        lColumnsForInstanceBuffer.append(lAttributeColumnName);
9577:
9578:                        lInnerColumnsForCollectionBuffer.append(",");
9579:                        lInnerColumnsForCollectionBuffer
9580:                                .append(lEntityTableAlias);
9581:                        lInnerColumnsForCollectionBuffer.append(".");
9582:                        lInnerColumnsForCollectionBuffer
9583:                                .append(lAttributeColumnName);
9584:
9585:                        lOuterColumnsForCollectionBuffer.append(",");
9586:                        lOuterColumnsForCollectionBuffer.append("A");
9587:                        lOuterColumnsForCollectionBuffer.append(".");
9588:                        lOuterColumnsForCollectionBuffer
9589:                                .append(lAttributeColumnName);
9590:                    }
9591:                }
9592:                // Deal with associations
9593:                for (Iterator lReferencesIterator = pEntity.getReferences()
9594:                        .iterator(); lReferencesIterator.hasNext();) {
9595:                    AssociationRole lReference = (AssociationRole) lReferencesIterator
9596:                            .next();
9597:
9598:                    // Association constraint is only necessary if this entity has a reference
9599:                    if (CommonUtil.doesEntityStoreReference(lReference)) {
9600:                        RelationalEntityTableReferenceColumn lRelationalEntityTableAssociationRole = lEntityTable
9601:                                .getReferenceColumn(lReference);
9602:                        String lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
9603:                                .getColumnNameOverride();
9604:                        if (lAssociationRoleInstanceIdColumnName == null
9605:                                || lAssociationRoleInstanceIdColumnName
9606:                                        .length() == 0)
9607:                            lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
9608:                                    .getColumnNameSuggestion();
9609:
9610:                        lColumnsForInstanceBuffer.append(",");
9611:                        lColumnsForInstanceBuffer.append(lEntityTableAlias);
9612:                        lColumnsForInstanceBuffer.append(".");
9613:                        lColumnsForInstanceBuffer
9614:                                .append(lAssociationRoleInstanceIdColumnName);
9615:
9616:                        lInnerColumnsForCollectionBuffer.append(",");
9617:                        lInnerColumnsForCollectionBuffer
9618:                                .append(lEntityTableAlias);
9619:                        lInnerColumnsForCollectionBuffer.append(".");
9620:                        lInnerColumnsForCollectionBuffer
9621:                                .append(lAssociationRoleInstanceIdColumnName);
9622:
9623:                        lOuterColumnsForCollectionBuffer.append(",");
9624:                        lOuterColumnsForCollectionBuffer.append("A");
9625:                        lOuterColumnsForCollectionBuffer.append(".");
9626:                        lOuterColumnsForCollectionBuffer
9627:                                .append(lAssociationRoleInstanceIdColumnName);
9628:                    }
9629:                }
9630:                SelectStatementParts lSelectStatementParts = new SelectStatementParts();
9631:                lSelectStatementParts.WhatClauseForGetInstance = lColumnsForInstanceBuffer
9632:                        .toString();
9633:                lSelectStatementParts.WhatClauseForGetCollection = lInnerColumnsForCollectionBuffer
9634:                        .toString();
9635:                lSelectStatementParts.WhatClauseForOuterQuery = lOuterColumnsForCollectionBuffer
9636:                        .toString();
9637:                return lSelectStatementParts;
9638:            }
9639:
9640:            // Helper. generates a string in form "xxx","yyyy","zzzz" etc which can be used to initialise java array
9641:            // String itself represents column names for the particular entity
9642:            private static String generateEntityColumnsArrayInitialiser(
9643:                    Entity pEntity,
9644:                    DomainRelationalStorageDefinition pDomainStorage,
9645:                    boolean pLightColumnsOnly) throws BSException {
9646:                StringBuffer lResultBuffer = new StringBuffer();
9647:
9648:                RelationalEntityTable lEntityTable = pDomainStorage
9649:                        .getEntityTable(pEntity);
9650:                String lInstanceIdColumnName = lEntityTable
9651:                        .getInstanceIdColumnNameOverride();
9652:                if (lInstanceIdColumnName == null
9653:                        || lInstanceIdColumnName.length() == 0)
9654:                    lInstanceIdColumnName = lEntityTable
9655:                            .getInstanceIdColumnNameSuggestion();
9656:                lResultBuffer.append("\"");
9657:                lResultBuffer.append(lInstanceIdColumnName);
9658:                lResultBuffer.append("\"");
9659:
9660:                if (pEntity.isModifiable()) {
9661:                    String lVersionIdColumnName = lEntityTable
9662:                            .getVersionIdColumnNameOverride();
9663:                    if (lVersionIdColumnName == null
9664:                            || lVersionIdColumnName.length() == 0)
9665:                        lVersionIdColumnName = lEntityTable
9666:                                .getVersionIdColumnNameSuggestion();
9667:                    lResultBuffer.append(",\"");
9668:                    lResultBuffer.append(lVersionIdColumnName);
9669:                    lResultBuffer.append("\"");
9670:                }
9671:                if (pEntity.getStateMachine() != null) {
9672:                    String lStateColumnName = lEntityTable
9673:                            .getStateColumnNameOverride();
9674:                    if (lStateColumnName == null
9675:                            || lStateColumnName.length() == 0)
9676:                        lStateColumnName = lEntityTable
9677:                                .getStateColumnNameSuggestion();
9678:                    lResultBuffer.append(",\"");
9679:                    lResultBuffer.append(lStateColumnName);
9680:                    lResultBuffer.append("\"");
9681:                }
9682:
9683:                // Deal with attributes
9684:                for (Iterator lAttributesIterator = pEntity.getAttributes()
9685:                        .iterator(); lAttributesIterator.hasNext();) {
9686:                    Attribute lAttribute = (Attribute) lAttributesIterator
9687:                            .next();
9688:                    if (pLightColumnsOnly) {
9689:                        STDatatypeTranslationStylesheet lAttributeDatatypeTranslationStylesheet = CodeGenerationStylesheetAccessor
9690:                                .getDatatypeTranslationStylesheet(lAttribute
9691:                                        .getDataType());
9692:                        DataTypeTranslationMetadata.SqlType lAttributeDatatypeSqlType = DataTypeTranslationMetadata.SqlType
9693:                                .createFromName(lAttributeDatatypeTranslationStylesheet
9694:                                        .getSqlTypeName());
9695:                        if (lAttributeDatatypeSqlType
9696:                                .equals(DataTypeTranslationMetadata.SQL_BLOB)
9697:                                || lAttributeDatatypeSqlType
9698:                                        .equals(DataTypeTranslationMetadata.SQL_CLOB))
9699:                            continue; // This is not a light column
9700:                    }
9701:                    RelationalEntityTableAttributeColumn lRelationalEntityTableAttribute = lEntityTable
9702:                            .getAttributeColumn(lAttribute);
9703:                    String lAttributeColumnName = lRelationalEntityTableAttribute
9704:                            .getColumnNameOverride();
9705:                    if (lAttributeColumnName == null
9706:                            || lAttributeColumnName.length() == 0)
9707:                        lAttributeColumnName = lRelationalEntityTableAttribute
9708:                                .getColumnNameSuggestion();
9709:                    lResultBuffer.append(",\"");
9710:                    lResultBuffer.append(lAttributeColumnName);
9711:                    lResultBuffer.append("\"");
9712:                }
9713:                // Deal with associations
9714:                for (Iterator lReferencesIterator = pEntity.getReferences()
9715:                        .iterator(); lReferencesIterator.hasNext();) {
9716:                    AssociationRole lReference = (AssociationRole) lReferencesIterator
9717:                            .next();
9718:                    // Association constraint is only necessary if this entity has a reference
9719:                    if (CommonUtil.doesEntityStoreReference(lReference)) {
9720:                        RelationalEntityTableReferenceColumn lRelationalEntityTableAssociationRole = lEntityTable
9721:                                .getReferenceColumn(lReference);
9722:                        String lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
9723:                                .getColumnNameOverride();
9724:                        if (lAssociationRoleInstanceIdColumnName == null
9725:                                || lAssociationRoleInstanceIdColumnName
9726:                                        .length() == 0)
9727:                            lAssociationRoleInstanceIdColumnName = lRelationalEntityTableAssociationRole
9728:                                    .getColumnNameSuggestion();
9729:                        lResultBuffer.append(",\"");
9730:                        lResultBuffer
9731:                                .append(lAssociationRoleInstanceIdColumnName);
9732:                        lResultBuffer.append("\"");
9733:                    }
9734:                }
9735:                return lResultBuffer.toString();
9736:            }
9737:        }
ww_w_.j_a__v_a2_s___.___com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.