Source Code Cross Referenced for Profile.java in  » Content-Management-System » harmonise » org » openharmonise » rm » metadata » 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 » Content Management System » harmonise » org.openharmonise.rm.metadata 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * The contents of this file are subject to the 
0003:         * Mozilla Public License Version 1.1 (the "License"); 
0004:         * you may not use this file except in compliance with the License. 
0005:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0006:         *
0007:         * Software distributed under the License is distributed on an "AS IS"
0008:         * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
0009:         * See the License for the specific language governing rights and 
0010:         * limitations under the License.
0011:         *
0012:         * The Initial Developer of the Original Code is Simulacra Media Ltd.
0013:         * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
0014:         *
0015:         * All Rights Reserved.
0016:         *
0017:         * Contributor(s):
0018:         */
0019:        package org.openharmonise.rm.metadata;
0020:
0021:        import java.sql.*;
0022:        import java.util.*;
0023:        import java.util.logging.*;
0024:
0025:        import org.openharmonise.commons.dsi.*;
0026:        import org.openharmonise.commons.dsi.dml.*;
0027:        import org.openharmonise.commons.xml.XMLUtils;
0028:        import org.openharmonise.rm.*;
0029:        import org.openharmonise.rm.dsi.*;
0030:        import org.openharmonise.rm.factory.*;
0031:        import org.openharmonise.rm.publishing.*;
0032:        import org.openharmonise.rm.resources.*;
0033:        import org.openharmonise.rm.resources.lifecycle.EditException;
0034:        import org.openharmonise.rm.resources.metadata.properties.*;
0035:        import org.openharmonise.rm.resources.metadata.properties.domains.Domain;
0036:        import org.openharmonise.rm.resources.metadata.properties.ranges.*;
0037:        import org.openharmonise.rm.resources.publishing.Template;
0038:        import org.openharmonise.rm.search.Search;
0039:        import org.w3c.dom.*;
0040:
0041:        /**
0042:         * <code>Profile</code> represents a collection of <code>AbstractPropertyInstance</code>s.
0043:         * 
0044:         * @author Michael Bell
0045:         * @version $Revision: 1.8.2.1 $
0046:         *
0047:         */
0048:        public class Profile extends AbstractObject implements  Publishable,
0049:                DataStoreObject, Cloneable {
0050:
0051:            // XML constants
0052:            private static final String CONST_TRUE = "true";
0053:
0054:            /**
0055:             * Profile XML element name
0056:             */
0057:            public static final String TAG_PROFILE = "Profile";
0058:
0059:            /**
0060:             * Property value XML element name
0061:             */
0062:            public static final String TAG_PROPERTY_VALUE = "PropertyValue";
0063:
0064:            /**
0065:             * 'Is default' XML attribute name
0066:             */
0067:            public static final String ATTRIB_ISDEFAULT = "isdefault";
0068:
0069:            /**
0070:             * Profiled object key XML attribute name
0071:             */
0072:            public static final String ATTRIB_OBJECT_KEY = "objectKey";
0073:
0074:            /**
0075:             * Value of <code>ATTRIB_ISDEFAULT</code> which indicates
0076:             * that a <code>Profile</code> is default
0077:             */
0078:            public static final String IS_DEFAULT_PROFILE_VALUE = "1";
0079:
0080:            /**
0081:             * 'default' XML attribute name
0082:             */
0083:            public static final String ATTRIB_DEFAULT = "default";
0084:
0085:            /**
0086:             * All property instance XML element name
0087:             */
0088:            public static final String TAG_ALLPROPERTYINSTANCES = "AllPropertyInstances";
0089:
0090:            //DB constants
0091:            /**
0092:             * Version comment database column name
0093:             */
0094:            private static final String CLMN_VERSION_COMMENT = "version_comment";
0095:
0096:            /**
0097:             * Object key database column name
0098:             */
0099:            private static final String CLMN_OBJECT_KEY = "object_key";
0100:
0101:            /**
0102:             * 'is default' database column name
0103:             */
0104:            private static final String CLMN_IS_DEFAULT = "is_default";
0105:
0106:            /**
0107:             * <code>String</code> constant extension used for building profile
0108:             * database table name. The naming convention for <code>Profile</code>
0109:             * database table names is as follows:
0110:             * 
0111:             * AbstractProfiledObject.getTableName() + EXT_PROFILE
0112:             */
0113:            protected static final String EXT_PROFILE = "_profile";
0114:
0115:            /**
0116:             * The profile database sequence name
0117:             */
0118:            private static final String SEQ_PROFILE = "seq_profile";
0119:
0120:            /**
0121:             * <code>String</code> constant used for unknown profiles
0122:             */
0123:            public static final String UNKNOWN_PROFILE = "?";
0124:
0125:            /**
0126:             * <code>String</code> constant to indicate temporary profiles 
0127:             * that will not be saved
0128:             */
0129:            public static final String TEXT_MARKER = "XXXX";
0130:
0131:            /**
0132:             * <code>Map</code> to hold all <code>PropertyInstanceStore</code>s
0133:             */
0134:            private Map m_propStores = new Hashtable();
0135:
0136:            /**
0137:             * The version comment for this profile
0138:             */
0139:            protected String m_sVersionComment = null;
0140:
0141:            /**
0142:             * <code>true</code> if this is a new <code>Profile</code>
0143:             */
0144:            private boolean m_bNew = false;
0145:
0146:            /**
0147:             * The profiled object this <code>Profile</code> belongs to
0148:             */
0149:            private AbstractProfiledObject m_profObj = null;
0150:
0151:            /**
0152:             * <code>boolean</code> flag to indicate that the historical status has changed
0153:             */
0154:            private boolean m_bIsHistoricalChange = false;
0155:
0156:            /**
0157:             * <code>boolean</code> flag to indicate that this is a default <code>Profile</code>
0158:             */
0159:            private boolean m_bIsDefault = false;
0160:
0161:            /**
0162:             * Logger for this class
0163:             */
0164:            private static final Logger m_logger = Logger
0165:                    .getLogger(Profile.class.getName());
0166:
0167:            /**
0168:             * Constructs a <code>Profile</code> without an interface to the
0169:             * data store.
0170:             *
0171:             */
0172:            public Profile() {
0173:                super ();
0174:            }
0175:
0176:            /**
0177:             * Constructs a <code>Profile</code> with an interface to the data store.
0178:             * 
0179:             * @param dbintrf the data store interface
0180:             */
0181:            public Profile(AbstractDataStoreInterface dbintrf) {
0182:                super (dbintrf);
0183:                m_bNew = true;
0184:                m_sTable = UNKNOWN_PROFILE;
0185:
0186:            }
0187:
0188:            /**
0189:             * Constructs a <code>Profile</code> which has an interface to the data store
0190:             * and a reference to it's 'owner' <code>AbstractProfiledObject</code>.
0191:             * 
0192:             * @param dbintrf the data store interface
0193:             * @param obj the 'owning' profiled object
0194:             */
0195:            public Profile(AbstractDataStoreInterface dbintrf,
0196:                    AbstractProfiledObject obj) {
0197:                super (dbintrf, obj.isHistorical());
0198:                m_bNew = true;
0199:                m_profObj = obj;
0200:
0201:            }
0202:
0203:            /**
0204:             * Constructs the <code>Profile</code> with the given id, a reference to it's 
0205:             * 'owning' <code>AbstractProfiledObject</code> and an interface to the data 
0206:             * store.
0207:             * 
0208:             * @param dbintrf the data store interface
0209:             * @param nId the profile id
0210:             * @param obj the 'owning' profiled object
0211:             */
0212:            public Profile(AbstractDataStoreInterface dbintrf, int nId,
0213:                    AbstractProfiledObject obj) {
0214:                super (dbintrf, nId, 0, obj.isHistorical());
0215:
0216:                m_profObj = obj;
0217:
0218:            }
0219:
0220:            /* (non-Javadoc)
0221:             * @see org.openharmonise.rm.resources.AbstractObject#isChanged()
0222:             */
0223:            public boolean isChanged() throws DataAccessException {
0224:                boolean bReturn = super .isChanged();
0225:
0226:                // if necessary check propertyInstances too but only if we have to
0227:                if (bReturn == false) {
0228:                    Iterator iter = null;
0229:
0230:                    iter = m_propStores.values().iterator();
0231:
0232:                    while (iter.hasNext() == true && bReturn == false) {
0233:                        PropertyInstanceStore propStore = (PropertyInstanceStore) iter
0234:                                .next();
0235:                        bReturn = propStore.isChanged();
0236:                    }
0237:
0238:                }
0239:
0240:                return bReturn;
0241:            }
0242:
0243:            /**
0244:             * Returns <code>true</code> if this <code>Profile</code> is the default 
0245:             * for its owning <code>AbstractProfiledObject</code>, otherwise <code>false</code>.
0246:             * 
0247:             * @return <code>true</code> if this <code>Profile</code> is the default
0248:             * @throws DataAccessException if an error occurs populating this profile
0249:             * from the database
0250:             */
0251:            public boolean isDefault() throws DataAccessException {
0252:                if ((m_bIsDefault == false) && (m_bIsPopulated == false)) {
0253:                    try {
0254:                        populateFromDatabase();
0255:                    } catch (PopulateException pop_e) {
0256:                        throw new DataAccessException(pop_e
0257:                                .getLocalizedMessage());
0258:                    }
0259:                }
0260:
0261:                return m_bIsDefault;
0262:            }
0263:
0264:            /**
0265:             * Returns <code>true</code> if this <code>Profile</code> is new, 
0266:             * otherwise <code>false</code>.
0267:             * 
0268:             * @return <code>true</code> if this <code>Profile</code> is new
0269:             */
0270:            public boolean isNew() {
0271:                return m_bNew;
0272:            }
0273:
0274:            /** 
0275:             * Returns the list of all property instances contained in this 
0276:             * <code>Profile</code>.
0277:             *
0278:             * @return the list of all property instances of the profile
0279:             * @throws DataAccessException if an error occurs populating this profile
0280:             * from the database
0281:             */
0282:            public List getPropertyInstances() throws DataAccessException {
0283:
0284:                //ensure all propInsts are loaded
0285:                try {
0286:                    if (isNew() == false) {
0287:                        populatePropertyInstancesFromDatabase();
0288:                    }
0289:                } catch (PopulateException pop_e) {
0290:                    throw new DataAccessException(
0291:                            "Problem occured when populating", pop_e);
0292:                }
0293:
0294:                Vector props = new Vector();
0295:
0296:                Iterator iter = this .m_propStores.values().iterator();
0297:
0298:                while (iter.hasNext()) {
0299:                    PropertyInstanceStore propStore = (PropertyInstanceStore) iter
0300:                            .next();
0301:
0302:                    Collection propInsts = propStore.getValues();
0303:
0304:                    Iterator propiter = propInsts.iterator();
0305:
0306:                    List deadProps = new ArrayList();
0307:
0308:                    while (propiter.hasNext()) {
0309:                        AbstractPropertyInstance propInst = (AbstractPropertyInstance) propiter
0310:                                .next();
0311:
0312:                        Property prop = propInst.getProperty();
0313:
0314:                        //need to check if property still exists by
0315:                        //asking for property from prop inst
0316:                        //if it no longer exist have to delete prop inst from prof
0317:                        if (prop != null) {
0318:                            props.add(propInst);
0319:                        } else {
0320:                            try {
0321:                                deletePropertyInstanceData(propInst);
0322:                                if (m_logger.isLoggable(Level.INFO)) {
0323:                                    m_logger.logp(Level.INFO, this .getClass()
0324:                                            .getName(), "getPropertyInstances",
0325:                                            "Deleting dead property instance on "
0326:                                                    + m_profObj.getClass()
0327:                                                            .getName() + " "
0328:                                                    + m_profObj.getKey());
0329:                                }
0330:                                deadProps.add(propInst);
0331:                            } catch (InvalidPropertyInstanceException e) {
0332:                                m_logger
0333:                                        .log(
0334:                                                Level.WARNING,
0335:                                                "error removing dead property instance",
0336:                                                e);
0337:                            } catch (ProfileException e) {
0338:                                m_logger
0339:                                        .log(
0340:                                                Level.WARNING,
0341:                                                "error removing dead property instance",
0342:                                                e);
0343:                            } catch (DataAccessException e) {
0344:                                m_logger
0345:                                        .log(
0346:                                                Level.WARNING,
0347:                                                "error removing dead property instance",
0348:                                                e);
0349:                            }
0350:                        }
0351:                    }
0352:
0353:                    if (deadProps.size() > 0) {
0354:                        Iterator deadPropIter = deadProps.iterator();
0355:
0356:                        while (deadPropIter.hasNext()) {
0357:                            AbstractPropertyInstance propInst = (AbstractPropertyInstance) deadPropIter
0358:                                    .next();
0359:                            propStore.removePropertyInstance(propInst);
0360:                        }
0361:                    }
0362:
0363:                }
0364:
0365:                return props;
0366:            }
0367:
0368:            /**
0369:             * Sets whether this <code>Profile</code> is the default for the owning 
0370:             * <code>AbstractProfiledObject</code>.
0371:             * 
0372:             * @param bIsDefault <code>true</code> if this <code>Profile</code> is
0373:             * the default, otherwise <code>false</code>.
0374:             */
0375:            public void setIsDefault(boolean bIsDefault) {
0376:                m_bIsDefault = bIsDefault;
0377:            }
0378:
0379:            /* (non-Javadoc)
0380:             * @see org.openharmonise.rm.resources.AbstractObject#setHistorical(boolean)
0381:             */
0382:            public void setHistorical(boolean bIsHistorical) {
0383:                m_bIsHistoricalChange = true;
0384:                super .setHistorical(bIsHistorical);
0385:
0386:                try {
0387:                    if (m_propStores.size() > 0) {
0388:                        // pass historical property to PropertyInstance
0389:                        Iterator iter = getPropertyInstances().iterator();
0390:
0391:                        while (iter.hasNext()) {
0392:                            AbstractPropertyInstance next = (AbstractPropertyInstance) iter
0393:                                    .next();
0394:                            next.setHistorical(bIsHistorical);
0395:                        }
0396:                    }
0397:
0398:                } catch (DataAccessException e) {
0399:                    // TODO can't throw exception, so log
0400:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0401:
0402:                }
0403:            }
0404:
0405:            /**
0406:             * Sets the version comment for this version of the <code>Profile</code>.
0407:             * 
0408:             * @param sComment the version comment
0409:             */
0410:            public void setVersionComment(String sComment) {
0411:                if (isPopulated() == true) {
0412:                    if (m_sVersionComment == null && sComment != null) {
0413:                        setIsChanged(true);
0414:                    } else if (m_sVersionComment.equals(sComment) == false) {
0415:                        setIsChanged(true);
0416:                    }
0417:                }
0418:
0419:                m_sVersionComment = sComment;
0420:            }
0421:
0422:            /**
0423:             * Returns the version comment for this <code>Profile</code>.
0424:             * 
0425:             * @return the version comment for this <code>Profile</code>
0426:             * @throws DataAccessException if an error occurs populating this profile
0427:             * from the database
0428:             */
0429:            public String getVersionComment() throws DataAccessException {
0430:                if (isPopulated() == false && m_sVersionComment == null) {
0431:                    try {
0432:                        populateFromDatabase();
0433:                    } catch (PopulateException e) {
0434:                        throw new DataAccessException(
0435:                                "Problem occurred populating profile", e);
0436:                    }
0437:                }
0438:
0439:                return m_sVersionComment;
0440:            }
0441:
0442:            /**
0443:             * Returns the list of properties which can be added to this <code>Profile</code>, dependant
0444:             * on the profiled object associated.
0445:             * 
0446:             * @return the list of properties which can be added to this <code>Profile</code>
0447:             * @throws DataAccessException if 
0448:             */
0449:            public List getAvailableProperties() throws DataAccessException {
0450:
0451:                if (m_profObj == null) {
0452:                    throw new DataAccessException(
0453:                            "No profiled object attached to this profile");
0454:                }
0455:
0456:                List propList = null;
0457:
0458:                propList = Domain.getAvailableProperties(m_dsi, m_profObj);
0459:
0460:                return propList;
0461:            }
0462:
0463:            /**
0464:             * Returns <code>true<code> if the specified <code>AbstractPropertyInstance</code> 
0465:             * is valid for this <code>Profile</code>.
0466:             * 
0467:             * @param propInst the property instance
0468:             * @return <code>true<code> if the specified <code>AbstractPropertyInstance</code> 
0469:             * is valid
0470:             * @throws ProfileException if an error occurs getting the <code>Property</code>
0471:             * associated to the given property instance
0472:             */
0473:            public boolean isValidPropertyInstance(
0474:                    AbstractPropertyInstance propInst) throws ProfileException {
0475:
0476:                boolean bIsValid = false;
0477:
0478:                try {
0479:                    Property propInstProp = propInst.getProperty();
0480:
0481:                    bIsValid = isValidProperty(propInstProp);
0482:                } catch (DataAccessException e) {
0483:                    throw new ProfileException(e.getLocalizedMessage(), e);
0484:                }
0485:
0486:                return bIsValid;
0487:
0488:            }
0489:
0490:            /**
0491:             * Returns <code>true</code> an instance of the specified <code>Property</code> 
0492:             * can be added to this <code>Profile</code>
0493:             * 
0494:             * @param prop the <code>Property</code>
0495:             * @return <code>true</code> an instance of the specified <code>Property</code> 
0496:             * can be added to this <code>Profile</code>
0497:             */
0498:            public boolean isValidProperty(Property prop) {
0499:                boolean bIsValid = false;
0500:
0501:                try {
0502:                    if (prop != null) {
0503:                        List availProps = getAvailableProperties();
0504:
0505:                        bIsValid = availProps.contains(prop);
0506:                    }
0507:
0508:                } catch (DataAccessException da_e) {
0509:                    m_logger.log(Level.WARNING, da_e.getLocalizedMessage(),
0510:                            da_e);
0511:
0512:                    bIsValid = false;
0513:                }
0514:
0515:                return bIsValid;
0516:
0517:            }
0518:
0519:            /** 
0520:             * Adds a property instance to this <code>Profile</code>.
0521:             *
0522:             * @param propInst the property instance to add
0523:             * @throws ProfileException if the given property instance is invalid
0524:             * or there is an error getting details from the property instance
0525:             */
0526:            public void addPropertyInstance(AbstractPropertyInstance propInst)
0527:                    throws ProfileException {
0528:                propInst.setProfile(this );
0529:
0530:                if (propInst == null) {
0531:                    throw new InvalidPropertyInstanceException(
0532:                            "null property passed in");
0533:                } else if (isValidPropertyInstance(propInst) == false) {
0534:                    throw new InvalidPropertyInstanceException(
0535:                            "Invalid property passed in");
0536:                }
0537:
0538:                try {
0539:
0540:                    String sKey = propInst.getName();
0541:                    if (sKey.length() == 0) {
0542:                        throw new InvalidPropertyInstanceException(
0543:                                "Invalid key");
0544:                    }
0545:
0546:                    Property prop = propInst.getProperty();
0547:
0548:                    if (hasProperty(prop) == false) {
0549:
0550:                        PropertyInstanceStore propStore = this 
0551:                                .getPropertyInstanceStore(prop);
0552:
0553:                        propStore.addPropertyInstance(propInst);
0554:                    } else {
0555:                        throw new InvalidPropertyInstanceException(
0556:                                "Profile already has property instance - "
0557:                                        + sKey);
0558:                    }
0559:
0560:                } catch (DataAccessException da_e) {
0561:                    throw new ProfileException(
0562:                            "Error occured accessing property instance name",
0563:                            da_e);
0564:                }
0565:
0566:            }
0567:
0568:            /** 
0569:             * Removes instances of the specified <code>Property</code> from this 
0570:             * <code>Profile</code>.
0571:             *
0572:             * @param prop the <code>Property</code> to remove
0573:             * @throws ProfileException if an error occurs removing the property
0574:             * from this <code>Profile</code>
0575:             */
0576:            public void removeProperty(Property prop) throws ProfileException {
0577:                try {
0578:                    PropertyInstanceStore propStore = getPropertyInstanceStore(prop);
0579:
0580:                    if (propStore.isPopulated() == false) {
0581:                        populatePropertyInstanceStore(propStore);
0582:                    }
0583:
0584:                    propStore.removePropertyInstance(prop);
0585:                } catch (DataAccessException e) {
0586:                    throw new ProfileException(
0587:                            "Error occured getting property instances", e);
0588:                } catch (PopulateException e) {
0589:                    throw new ProfileException(
0590:                            "Error occured populating prop insts", e);
0591:                }
0592:            }
0593:
0594:            /** 
0595:             * Returns <code>true</code> if the <code>Profile</code> has an instance of the 
0596:             * specified <code>Property</code>.
0597:             *
0598:             * @param prop the <code>Property</code>
0599:             * @throws DataAccessException if there is an error populating the property
0600:             * instances of this <code>Profile></code>
0601:             * 
0602:             */
0603:            public boolean hasProperty(Property prop)
0604:                    throws DataAccessException {
0605:                try {
0606:                    AbstractPropertyInstance propInst = getPropertyInstance(prop);
0607:                    return (propInst != null);
0608:                } catch (InvalidPropertyInstanceException e) {
0609:                    return false;
0610:                }
0611:            }
0612:
0613:            /** 
0614:             * Returns the instance of the given <code>Property</code> held by this 
0615:             * <code>Profile</code> if there is one.
0616:             *
0617:             * @param property the <code>Property</code>
0618:             * @return the instance of the given <code>Property</code>, 
0619:             * <code>null</code> if there is no instance
0620:             * @throws InvalidPropertyInstanceException if the specified <code>Property</code>
0621:             * is invalid for this <code>Profile</code>
0622:             * @throws DataAccessException if there is an error populating this
0623:             * <code>Profile</code>
0624:             */
0625:            public AbstractPropertyInstance getPropertyInstance(
0626:                    Property property) throws InvalidPropertyInstanceException,
0627:                    DataAccessException {
0628:                AbstractPropertyInstance propReturn = null;
0629:
0630:                PropertyInstanceStore propStore = null;
0631:
0632:                propStore = getPropertyInstanceStore(property);
0633:
0634:                if (propStore.isPopulated() == false) {
0635:                    try {
0636:                        populatePropertyInstanceStore(propStore);
0637:                    } catch (PopulateException e) {
0638:                        throw new DataAccessException(
0639:                                "Problem occurred populate values", e);
0640:                    }
0641:                }
0642:
0643:                propReturn = propStore.getPropertyInstance(property);
0644:
0645:                if (propReturn != null && property.exists() == false) {
0646:                    try {
0647:                        deletePropertyInstanceData(propReturn);
0648:                    } catch (InvalidPropertyInstanceException e) {
0649:                        m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0650:                        throw new DataAccessException(e);
0651:                    } catch (ProfileException e) {
0652:                        m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0653:                        throw new DataAccessException(e);
0654:                    } catch (DataAccessException e) {
0655:                        m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0656:                        throw new DataAccessException(e);
0657:                    }
0658:                }
0659:
0660:                return propReturn;
0661:            }
0662:
0663:            /** 
0664:             * Returns a instance of the <code>Property</code> with the specified
0665:             * name if one exists in this <code>Profile</code>.
0666:             *
0667:             * @param sPropName the name of the <code>Property</code> 
0668:             * @return the instance of the <code>Property</code>, 
0669:             * <code>null</code> no instance exists
0670:             * 
0671:             * @throws InvalidPropertyInstanceException if the specified <code>Property</code>
0672:             * is invalid for this <code>Profile</code>
0673:             * @throws DataAccessException if there is an error populating this
0674:             * <code>Profile</code>
0675:             */
0676:            public AbstractPropertyInstance getPropertyInstance(String sPropName)
0677:                    throws InvalidPropertyInstanceException,
0678:                    DataAccessException {
0679:                AbstractPropertyInstance propReturn = null;
0680:
0681:                try {
0682:                    Property prop = PropertyFactory.getPropertyFromName(m_dsi,
0683:                            sPropName);
0684:                    propReturn = getPropertyInstance(prop);
0685:                } catch (HarmoniseFactoryException e) {
0686:                    throw new DataAccessException(
0687:                            "Problem occurred getting property from name:", e);
0688:                }
0689:
0690:                return propReturn;
0691:            }
0692:
0693:            /**
0694:             * Saves this <code>Profile</code> to the data store.
0695:             * 
0696:             * @param proObj the 'owner' <code>AbstractProfiledObject</code>
0697:             * @return the resultant <code>Profile</code> of the save operation
0698:             * @throws ProfileException if a profiled object is not specified
0699:             * or, if this is not a new <code>Profile</code>, there is an error populating 
0700:             * this <code>Profile</code> with existing property instances
0701:             * @throws EditException if there is an error saving the data to the 
0702:             * database
0703:             */
0704:            public Profile save(AbstractProfiledObject proObj)
0705:                    throws ProfileException, EditException {
0706:                if (proObj == null) {
0707:                    throw new ProfileException(
0708:                            "No ProfiledObject given so can't save");
0709:                }
0710:
0711:                // before we start ensure that we have the correct info
0712:                if (m_bIsPopulated == false) {
0713:                    try {
0714:                        populateFromDatabase();
0715:                    } catch (PopulateException e) {
0716:                        throw new ProfileException(
0717:                                "Problem occurred populating the profile", e);
0718:                    }
0719:                }
0720:
0721:                try {
0722:
0723:                    if (isNew() == false
0724:                            && isPropertyInstancesPopulated() == false) {
0725:                        populatePropertyInstancesFromDatabase();
0726:                    }
0727:                } catch (DataAccessException da_e) {
0728:                    throw new ProfileException(
0729:                            "Error occured while accessing property instances:",
0730:                            da_e);
0731:                } catch (PopulateException pop_e) {
0732:                    throw new ProfileException(
0733:                            "Error occured while accessing property instances:",
0734:                            pop_e);
0735:                }
0736:
0737:                //check to see if profiled object has changed
0738:                boolean bProfObjChange = false;
0739:
0740:                try {
0741:                    bProfObjChange = (m_profObj.getKey() != proObj.getKey());
0742:                } catch (DataAccessException da_e) {
0743:                    throw new ProfileException(
0744:                            "Problem occurred accessing data from profiled object:",
0745:                            da_e);
0746:                }
0747:
0748:                //ensure that profiled object is set
0749:                m_profObj = proObj;
0750:
0751:                Profile profileReturn = null;
0752:                // if this is a new profile, create a new record
0753:                if ((m_nId == 0) || (m_nId == AbstractObject.NOTDBSAVED_ID)
0754:                        || m_bIsHistoricalChange) {
0755:                    //do this before getting the id sequence so that the equals()
0756:                    //comparison doesn't try to call populateFromDatabase() on a
0757:                    //id not in the database. Comprende?!
0758:                    int nIsDefault = 0;
0759:                    if (proObj.isDefaultProfile(this )) {
0760:                        nIsDefault = 1;
0761:                    }
0762:                    try {
0763:
0764:                        //gets new id even if historical because it's been cleared in the markAsNew method
0765:                        m_nId = m_dsi.getSequenceNextValue(SEQ_PROFILE);
0766:
0767:                        // insert into correct profile table
0768:                        InsertStatement insert = new InsertStatement();
0769:
0770:                        insert.addColumnValue(this .getInstanceColumnRef(
0771:                                ATTRIB_ID, false), m_nId);
0772:                        insert.addColumnValue(this .getInstanceColumnRef(
0773:                                ATTRIB_KEY, false), proObj.getKey());
0774:                        insert.addColumnValue(this .getInstanceColumnRef(
0775:                                TAG_NAME, false), m_sName);
0776:                        if (m_sSummary != null) {
0777:                            insert.addColumnValue(this .getInstanceColumnRef(
0778:                                    TAG_SUMMARY, false), m_sSummary);
0779:                        }
0780:
0781:                        if (m_sVersionComment != null) {
0782:                            insert.addColumnValue(this .getInstanceColumnRef(
0783:                                    CLMN_VERSION_COMMENT, false),
0784:                                    m_sVersionComment);
0785:                        }
0786:
0787:                        if (m_sType != null) {
0788:                            insert.addColumnValue(this .getInstanceColumnRef(
0789:                                    ATTRIB_TYPE, false), m_sType);
0790:                        }
0791:
0792:                        insert.addColumnValue(this .getInstanceColumnRef(
0793:                                CLMN_IS_DEFAULT, false), nIsDefault);
0794:                        m_dsi.execute(insert);
0795:                        // insert properties
0796:                        Iterator iter = getPropertyInstances().iterator();
0797:                        int nErrors = 0;
0798:                        List errorDescs = null;
0799:                        while (iter.hasNext()) {
0800:                            AbstractPropertyInstance next = (AbstractPropertyInstance) iter
0801:                                    .next();
0802:                            //try to save all prop insts even if individual propInsts fail
0803:                            try {
0804:
0805:                                next.save(this );
0806:                            } catch (InvalidPropertyInstanceException val_e) {
0807:                                //remove offending prop inst
0808:                                removePropertyInstance(next);
0809:                                nErrors++;
0810:                                if (errorDescs == null) {
0811:                                    errorDescs = new ArrayList();
0812:                                }
0813:                                errorDescs.add(val_e.getLocalizedMessage()
0814:                                        + " - " + next.toString());
0815:                            }
0816:                        }
0817:                        //reset flags
0818:                        m_bIsChanged = false;
0819:                        iter = m_propStores.values().iterator();
0820:
0821:                        while (iter.hasNext()) {
0822:                            PropertyInstanceStore propStore = (PropertyInstanceStore) iter
0823:                                    .next();
0824:                            propStore.setIsChanged(false);
0825:                        }
0826:
0827:                        m_bIsHistoricalChange = false;
0828:                        m_bIsPopulated = true;
0829:                        m_bNew = false;
0830:                        profileReturn = this ;
0831:
0832:                        if (nErrors > 0) {
0833:                            throw new EditException(
0834:                                    "Problem saving prop insts - " + errorDescs);
0835:                        }
0836:
0837:                    } catch (DataStoreException ds_e) {
0838:                        throw new ProfileException(
0839:                                "Problem occured saving profile:", ds_e);
0840:                    } catch (DataAccessException da_e) {
0841:                        throw new ProfileException(
0842:                                "Problem occured saving profile:", da_e);
0843:                    } catch (SQLException sql_e) {
0844:                        throw new ProfileException(
0845:                                "Problem occured saving profile:", sql_e);
0846:                    }
0847:                } else if (m_bIsChanged == true || bProfObjChange == true) {
0848:                    // if this is an existing profile and changes have been made,
0849:                    // create a new version
0850:                    // do this by temporarily setting our id to NOTDBSAVED_PRO_ID and cloning ourselves
0851:                    Profile profileNew = (Profile) this .clone();
0852:                    try {
0853:                        profileNew.markAsNew();
0854:                    } catch (PopulateException e) {
0855:                        throw new EditException(
0856:                                "Problem occurred marking object as new", e);
0857:                    }
0858:                    profileReturn = profileNew.save(proObj);
0859:                } else {
0860:                    // nothing to do, just return the profile as is
0861:                    profileReturn = this ;
0862:                }
0863:                return profileReturn;
0864:            }
0865:
0866:            /**
0867:             * Deletes this <code>Profile</code> from the database.
0868:             * 
0869:             * @throws ProfileException if an error occurs deleting this
0870:             * <code>Profile</code> from the database
0871:             */
0872:            public void delete() throws ProfileException {
0873:                if (m_nId == NOTDBSAVED_ID) {
0874:                    return;
0875:                }
0876:
0877:                ResultSet rs = null;
0878:                try {
0879:
0880:                    if (isPropertyInstancesPopulated() == false) {
0881:                        populatePropertyInstancesFromDatabase();
0882:                    }
0883:
0884:                    //delete general prop insts first
0885:                    Iterator iter = m_propStores.values().iterator();
0886:
0887:                    while (iter.hasNext()) {
0888:                        PropertyInstanceStore propStore = (PropertyInstanceStore) iter
0889:                                .next();
0890:
0891:                        deletePropertyInstances(propStore);
0892:                    }
0893:
0894:                    DeleteStatement delete = new DeleteStatement();
0895:
0896:                    delete.addWhereCondition(getInstanceColumnRef(ATTRIB_ID,
0897:                            false), "=", m_nId);
0898:
0899:                    m_dsi.execute(delete);
0900:                    //reset all datamembers
0901:                    m_nId = NOTDBSAVED_ID;
0902:                } catch (DataStoreException ds_e) {
0903:                    throw new ProfileException(
0904:                            "Problem occured deleting profile:", ds_e);
0905:                } catch (DataAccessException e) {
0906:                    throw new ProfileException(
0907:                            "Problem occured populating property instances:", e);
0908:                } catch (PopulateException e) {
0909:                    throw new ProfileException(
0910:                            "Problem occured populating property instances:", e);
0911:                } finally {
0912:                    if (rs != null) {
0913:                        try {
0914:                            rs.close();
0915:                        } catch (SQLException sql_e) {
0916:                            throw new ProfileException(
0917:                                    "Problem occured closing result set", sql_e);
0918:                        }
0919:
0920:                    }
0921:                }
0922:            }
0923:
0924:            /**
0925:             * Matches this <code>Profile</code> against the given <code>Profile</code>.
0926:             * 
0927:             * @param prof the <code>Profile</code> to match this 
0928:             * <code>Profile</code> against
0929:             * 
0930:             * @return <code>true</code> if both <code>Profile</code>s match
0931:             * @throws ProfileException if any errors occur
0932:             */
0933:            public boolean match(Profile prof) throws ProfileException {
0934:                boolean bMatch = false;
0935:                try {
0936:
0937:                    Iterator iter = getPropertyInstances().iterator();
0938:                    while (iter.hasNext()) {
0939:                        AbstractPropertyInstance this Prop = (AbstractPropertyInstance) iter
0940:                                .next();
0941:                        AbstractPropertyInstance otherProp = prof
0942:                                .getPropertyInstance(this Prop.getProperty());
0943:                        bMatch = this Prop.match(otherProp);
0944:                        if (bMatch == false) {
0945:                            break;
0946:                        }
0947:                    }
0948:                } catch (DataAccessException da_e) {
0949:                    throw new ProfileException(
0950:                            "Problem occurred accessing properties", da_e);
0951:                }
0952:
0953:                return bMatch;
0954:            }
0955:
0956:            /**
0957:             * Matches this <code>Profile</code> against the given <code>Profile</code>.
0958:             * 
0959:             * @param prof the <code>Profile</code> to match this 
0960:             * <code>Profile</code> against
0961:             * 
0962:             * @return <code>true</code> if both <code>Profile</code>s match
0963:             * @throws ProfileException if any errors occur
0964:             */
0965:            public boolean match(List propInstList) throws ProfileException {
0966:                boolean bMatch = false;
0967:                try {
0968:
0969:                    Iterator iter = propInstList.iterator();
0970:
0971:                    while (iter.hasNext()) {
0972:                        AbstractPropertyInstance otherProp = (AbstractPropertyInstance) iter
0973:                                .next();
0974:                        AbstractPropertyInstance this Prop = getPropertyInstance(otherProp
0975:                                .getProperty());
0976:
0977:                        bMatch = otherProp.match(this Prop);
0978:                        if (bMatch == false) {
0979:                            break;
0980:                        }
0981:                    }
0982:                } catch (DataAccessException da_e) {
0983:                    throw new ProfileException(
0984:                            "Problem occurred accessing properties", da_e);
0985:                }
0986:
0987:                return bMatch;
0988:            }
0989:
0990:            /* (non-Javadoc)
0991:             * @see java.lang.Object#toString()
0992:             */
0993:            public String toString() {
0994:                StringBuffer strbuf = new StringBuffer();
0995:                try {
0996:                    strbuf.append(" Summary:").append(m_sSummary)
0997:                            .append(" Id:").append(m_nId).append(
0998:                                    " Profile Table:").append(m_sTable).append(
0999:                                    " name:").append(m_sName).append(
1000:                                    "[value][labels]:{");
1001:                    String sName = "";
1002:
1003:                    Iterator propStoreIterator = m_propStores.values()
1004:                            .iterator();
1005:
1006:                    while (propStoreIterator.hasNext()) {
1007:                        PropertyInstanceStore propStore = (PropertyInstanceStore) propStoreIterator
1008:                                .next();
1009:
1010:                        if (propStore.m_propInsts != null) {
1011:                            Iterator propInstIter = propStore.m_propInsts
1012:                                    .values().iterator();
1013:
1014:                            while (propInstIter.hasNext()) {
1015:                                AbstractPropertyInstance propInst = (AbstractPropertyInstance) propInstIter
1016:                                        .next();
1017:                                sName = propInst.getProperty().getName();
1018:                                List values = propInst.getValues();
1019:
1020:                                strbuf.append(sName).append(": ");
1021:
1022:                                if (values != null) {
1023:                                    //need to avoid possible infnite recursion
1024:                                    //with toString() on ChildObjectPropertyInstances
1025:                                    if (propInst instanceof  ChildObjectPropertyInstance) {
1026:                                        Iterator valIter = values.iterator();
1027:
1028:                                        while (valIter.hasNext()) {
1029:                                            AbstractChildObject child = (AbstractChildObject) valIter
1030:                                                    .next();
1031:                                            strbuf.append(
1032:                                                    child.getClass().getName())
1033:                                                    .append(":").append(
1034:                                                            child.getId());
1035:                                            if (valIter.hasNext()) {
1036:                                                strbuf.append(",");
1037:                                            }
1038:                                        }
1039:                                    } else {
1040:                                        strbuf.append(values);
1041:                                    }
1042:                                }
1043:                                strbuf.append(".");
1044:                            }
1045:                        }
1046:
1047:                    }
1048:
1049:                    strbuf.append("}. ");
1050:                } catch (Exception e) {
1051:                    strbuf.append("Exception :").append(e.getMessage());
1052:                }
1053:
1054:                return strbuf.toString();
1055:            }
1056:
1057:            /* (non-Javadoc)
1058:             * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
1059:             */
1060:            public Element publish(Element topEl, HarmoniseOutput xmlDoc,
1061:                    State state) throws PublishException {
1062:
1063:                Element docEl = xmlDoc.createElement(topEl.getTagName());
1064:
1065:                if (((String) topEl.getTagName()).equals(TAG_PROFILE)) {
1066:                    String sTempName = null;
1067:
1068:                    try {
1069:
1070:                        sTempName = getName();
1071:                    } catch (DataAccessException da_e) {
1072:                        sTempName = "There was an error getting the name";
1073:                    }
1074:
1075:                    if ((sTempName == null) || sTempName.equalsIgnoreCase("")) {
1076:                        sTempName = topEl.getAttribute(Profile.ATTRIB_NAME);
1077:                    }
1078:
1079:                    docEl.setAttribute(ATTRIB_NAME, sTempName);
1080:                    if (m_nId != NOTDBSAVED_ID) {
1081:                        docEl.setAttribute(ATTRIB_ID, Integer.toString(m_nId));
1082:                    }
1083:
1084:                    String sDefault = topEl.getAttribute(ATTRIB_DEFAULT);
1085:                    if (sDefault.equals(CONST_TRUE)) {
1086:                        docEl.setAttribute(ATTRIB_ISDEFAULT, CONST_TRUE);
1087:                    }
1088:                }
1089:
1090:                NodeList nodes = topEl.getChildNodes();
1091:                Element formEl;
1092:                Element el = null;
1093:                Text txt = null;
1094:                String sTagName;
1095:                for (int i = 0; i < nodes.getLength(); i++) {
1096:                    if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
1097:                        continue;
1098:                    }
1099:
1100:                    formEl = (Element) nodes.item(i);
1101:                    sTagName = formEl.getTagName();
1102:                    if (sTagName.equals(TAG_SUMMARY)) {
1103:                        el = xmlDoc.createElement(sTagName);
1104:                        try {
1105:
1106:                            txt = xmlDoc.createTextNode(getSummary());
1107:                            el.appendChild(txt);
1108:                        } catch (DataAccessException da_e) {
1109:                            txt = xmlDoc
1110:                                    .createTextNode("A problem occured accessing the summary");
1111:                            el.appendChild(txt);
1112:                        }
1113:                        docEl.appendChild(el);
1114:                    } else if (sTagName
1115:                            .equals(AbstractEditableObject.TAG_VERSION_COMMENT)) {
1116:                        el = xmlDoc.createElement(sTagName);
1117:                        try {
1118:                            txt = xmlDoc.createTextNode(getVersionComment());
1119:                            el.appendChild(txt);
1120:                        } catch (DataAccessException da_e) {
1121:                            txt = xmlDoc
1122:                                    .createTextNode("A problem occured accessing the version comment");
1123:                            el.appendChild(txt);
1124:                        }
1125:                        docEl.appendChild(el);
1126:                    } else if (sTagName
1127:                            .equals(AbstractPropertyInstance.TAG_PROPERTYINSTANCE)) {
1128:                        AbstractPropertyInstance propInstance = null;
1129:                        String sPropName = null;
1130:                        try {
1131:                            NodeList propNodes = formEl
1132:                                    .getElementsByTagName(Property.TAG_PROPERTY);
1133:                            Element propEl = (Element) propNodes.item(0);
1134:                            Element nameEl = XMLUtils.getFirstNamedChild(
1135:                                    propEl, TAG_NAME);
1136:                            if (nameEl != null) {
1137:                                sPropName = XMLUtils.getChildTextValue(nameEl);
1138:                                propInstance = getPropertyInstance(sPropName);
1139:                            } else {
1140:                                Element pathEl = XMLUtils.getFirstNamedChild(
1141:                                        propEl, Property.TAG_PATH);
1142:                                String sPath = XMLUtils
1143:                                        .getChildTextValue(pathEl);
1144:                                Property prop = (Property) HarmoniseObjectFactory
1145:                                        .instantiateHarmoniseObject(m_dsi,
1146:                                                Property.class.getName(), sPath);
1147:                                propInstance = getPropertyInstance(prop);
1148:                            }
1149:
1150:                        } catch (DOMException e) {
1151:                            txt = xmlDoc
1152:                                    .createTextNode("A problem occured processing the property elements");
1153:                            el.appendChild(txt);
1154:                        } catch (InvalidPropertyInstanceException e) {
1155:                            el = e.publish(xmlDoc);
1156:                        } catch (DataAccessException e) {
1157:                            throw new PublishException(
1158:                                    "An error occured when trying to access a PropertyInstance",
1159:                                    e);
1160:                        } catch (HarmoniseFactoryException e) {
1161:                            el = e.publish(xmlDoc);
1162:                        }
1163:
1164:                        if (propInstance != null) {
1165:                            el = propInstance.publish(formEl, xmlDoc, state);
1166:                            docEl.appendChild(el);
1167:                        }
1168:
1169:                    } else if (sTagName.equals(TAG_ALLPROPERTYINSTANCES)) {
1170:                        try {
1171:
1172:                            NamedNodeMap attrs = formEl.getAttributes();
1173:
1174:                            Element propInstEl = xmlDoc
1175:                                    .createElement(AbstractPropertyInstance.TAG_PROPERTYINSTANCE);
1176:
1177:                            Element propEl = xmlDoc
1178:                                    .createElement(Property.TAG_PROPERTY);
1179:
1180:                            propInstEl.appendChild(propEl);
1181:
1182:                            Element valueEl = xmlDoc
1183:                                    .createElement(AbstractPropertyInstance.TAG_PROP_INSTANCE_VALUES);
1184:
1185:                            for (int j = 0; j < attrs.getLength(); j++) {
1186:                                Attr attr = (Attr) attrs.item(j);
1187:
1188:                                valueEl.setAttribute(attr.getName(), attr
1189:                                        .getValue());
1190:                            }
1191:
1192:                            propInstEl.appendChild(valueEl);
1193:
1194:                            //get the <AllPropertyInstances/> tag for compound props
1195:                            Element allPropEl = xmlDoc
1196:                                    .createElement(TAG_ALLPROPERTYINSTANCES);
1197:
1198:                            for (int j = 0; j < attrs.getLength(); j++) {
1199:                                Attr attr = (Attr) attrs.item(j);
1200:
1201:                                allPropEl.setAttribute(attr.getName(), attr
1202:                                        .getValue());
1203:                            }
1204:
1205:                            Element templateEl = XMLUtils.getFirstNamedChild(
1206:                                    formEl, Template.TAG_TEMPLATE);
1207:
1208:                            if (templateEl != null) {
1209:                                templateEl = (Element) xmlDoc.importNode(
1210:                                        templateEl, true);
1211:                                allPropEl.appendChild(templateEl
1212:                                        .cloneNode(true));
1213:                            }
1214:
1215:                            Element origPropEl = XMLUtils.getFirstNamedChild(
1216:                                    formEl, Property.TAG_PROPERTY);
1217:
1218:                            if (origPropEl != null) {
1219:                                NodeList propChildren = origPropEl
1220:                                        .getChildNodes();
1221:
1222:                                for (int j = 0; j < propChildren.getLength(); j++) {
1223:                                    Node node = (Node) propChildren.item(j);
1224:                                    propEl.appendChild(xmlDoc.importNode(node,
1225:                                            true));
1226:
1227:                                }
1228:                            }
1229:
1230:                            Element propCloneEl = (Element) propEl
1231:                                    .cloneNode(true);
1232:
1233:                            allPropEl.appendChild(propCloneEl);
1234:
1235:                            Element condEl = XMLUtils.getFirstNamedChild(
1236:                                    formEl, Search.TAG_CONDITIONS);
1237:
1238:                            Collection propInsts = null;
1239:
1240:                            if (condEl == null) {
1241:                                propInsts = getPropertyInstances();
1242:                            } else {
1243:                                List condProps = getConditionalPropertyInstances(condEl);
1244:                                propInsts = getMatchingPropertyInstances(condProps);
1245:                            }
1246:
1247:                            Iterator iter = propInsts.iterator();
1248:
1249:                            while (iter.hasNext()) {
1250:                                AbstractPropertyInstance propInst = (AbstractPropertyInstance) iter
1251:                                        .next();
1252:
1253:                                if (templateEl != null) {
1254:                                    if (propInst instanceof  ChildObjectPropertyInstance) {
1255:                                        valueEl.appendChild(templateEl);
1256:                                    }
1257:                                }
1258:
1259:                                if (propInst instanceof  ProfilePropertyInstance) {
1260:                                    valueEl.appendChild(allPropEl);
1261:
1262:                                }
1263:
1264:                                el = propInst
1265:                                        .publish(propInstEl, xmlDoc, state);
1266:                                docEl.appendChild(el);
1267:
1268:                                if (templateEl != null) {
1269:                                    if (propInst instanceof  ChildObjectPropertyInstance) {
1270:                                        valueEl.removeChild(templateEl);
1271:                                    }
1272:                                }
1273:
1274:                                if (propInst instanceof  ProfilePropertyInstance) {
1275:                                    valueEl.removeChild(allPropEl);
1276:                                }
1277:                            }
1278:                        } catch (DataAccessException da_e) {
1279:                            throw new PublishException(
1280:                                    "An error occured when trying to access the PropertyInstances",
1281:                                    da_e);
1282:                        }
1283:                    } else {
1284:                        // copy all nodes we don't recognise
1285:                        docEl.appendChild(xmlDoc.copyNode(formEl));
1286:                    }
1287:                }
1288:
1289:                return docEl;
1290:            }
1291:
1292:            /**
1293:             * Returns a <code>List</code> of <code>AbstractPropertyInstance</code>s
1294:             * whose defining <code>Property</code>s have the given conditional
1295:             * <code>AbstractPropertyInstance</code>s in their <code>Profile</code>.
1296:             * 
1297:             * @param condProps
1298:             * @return
1299:             */
1300:            public List getMatchingPropertyInstances(List condProps)
1301:                    throws DataAccessException {
1302:                List propInsts = new ArrayList();
1303:
1304:                Iterator iter = getPropertyInstances().iterator();
1305:
1306:                while (iter.hasNext()) {
1307:                    AbstractPropertyInstance propInst = (AbstractPropertyInstance) iter
1308:                            .next();
1309:
1310:                    Property prop = propInst.getProperty();
1311:
1312:                    Profile propProf = prop.getProfile();
1313:
1314:                    try {
1315:                        if (propProf.match(condProps) == true) {
1316:                            propInsts.add(propInst);
1317:                        }
1318:                    } catch (InvalidPropertyInstanceException e) {
1319:                        //ignore invalid properties
1320:                        if (m_logger.isLoggable(Level.FINE)) {
1321:                            m_logger.logp(Level.FINE,
1322:                                    this .getClass().getName(),
1323:                                    "getMatchingPropertyInstances",
1324:                                    "Ignoring property - " + prop.getName());
1325:                        }
1326:
1327:                    } catch (ProfileException e) {
1328:                        throw new DataAccessException(e);
1329:                    }
1330:                }
1331:
1332:                return propInsts;
1333:            }
1334:
1335:            /**
1336:             * Returns a <code>List</code> of <code>AbstractPropertyInstance</code>s
1337:             * which have been represented in the specified 'Conditions' XML element.
1338:             * 
1339:             * @param condEl the 'Conditions' XML element
1340:             * @return a <code>List</code> of <code>AbstractPropertyInstance</code>s
1341:             */
1342:            private List getConditionalPropertyInstances(Element condEl)
1343:                    throws PublishException {
1344:                List propInsts = new ArrayList();
1345:
1346:                if (condEl.getTagName().equals(Search.TAG_CONDITIONS) == true) {
1347:                    List nodes = XMLUtils.getChildrenByName(condEl,
1348:                            AbstractPropertyInstance.TAG_PROPERTYINSTANCE);
1349:
1350:                    for (Iterator iter = nodes.iterator(); iter.hasNext();) {
1351:                        Element propInstEl = (Element) iter.next();
1352:
1353:                        try {
1354:                            AbstractPropertyInstance propInst = PropertyInstanceFactory
1355:                                    .getPropertyInstance(m_dsi, propInstEl);
1356:
1357:                            propInst.populate(propInstEl, null);
1358:
1359:                            propInsts.add(propInst);
1360:                        } catch (DataAccessException e) {
1361:                            throw new PublishException(e);
1362:                        } catch (HarmoniseFactoryException e) {
1363:                            throw new PublishException(e);
1364:                        } catch (PopulateException e) {
1365:                            throw new PublishException(e);
1366:                        }
1367:                    }
1368:                }
1369:
1370:                return propInsts;
1371:            }
1372:
1373:            /* (non-Javadoc)
1374:             * @see org.openharmonise.rm.publishing.Publishable#populate(org.w3c.dom.Element, org.openharmonise.rm.publishing.State)
1375:             */
1376:            public void populate(Element xmlElement, State state)
1377:                    throws PopulateException {
1378:
1379:                if (xmlElement.getTagName().equals(TAG_PROFILE) == false) {
1380:                    throw new PopulateException("Expecting " + TAG_PROFILE
1381:                            + " got " + xmlElement.getTagName());
1382:                }
1383:                try {
1384:                    if (((AbstractChildObject) m_profObj).getParents()
1385:                            .isEmpty()) {
1386:                        throw new PopulateDependencyException(
1387:                                "Profiled object must have a parent before populating profile");
1388:                    }
1389:                } catch (DataAccessException e) {
1390:                    throw new PopulateException(e);
1391:                }
1392:
1393:                try {
1394:                    String sName = xmlElement.getAttribute(ATTRIB_NAME);
1395:                    if (sName != null && sName.length() > 0) {
1396:                        setName(sName);
1397:                    }
1398:                } catch (InvalidNameException e) {
1399:                    throw new PopulateException(e);
1400:                }
1401:                NodeList nodes = xmlElement.getChildNodes();
1402:                Element formEl;
1403:                String sTagName;
1404:                String sProperty;
1405:                Vector values = new Vector();
1406:                Element el;
1407:                NodeList valueNodes;
1408:                NodeList availableValueNodes;
1409:                for (int i = 0; i < nodes.getLength(); i++) {
1410:                    if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
1411:                        continue;
1412:                    }
1413:
1414:                    formEl = (Element) nodes.item(i);
1415:                    sTagName = formEl.getTagName();
1416:                    Text txt = null;
1417:                    if (sTagName.equals(TAG_SUMMARY)) {
1418:                        txt = (Text) formEl.getFirstChild();
1419:                        setSummary(txt.getNodeValue());
1420:                    } else if (sTagName
1421:                            .equals(AbstractEditableObject.TAG_VERSION_COMMENT)) {
1422:                        txt = (Text) formEl.getFirstChild();
1423:                        setVersionComment(txt.getNodeValue());
1424:                    } else if (sTagName
1425:                            .equals(AbstractPropertyInstance.TAG_PROPERTYINSTANCE)) {
1426:
1427:                        try {
1428:                            AbstractPropertyInstance propInst = PropertyInstanceFactory
1429:                                    .getPropertyInstance(m_dsi, formEl, this );
1430:                            Property prop = propInst.getProperty();
1431:                            if (hasProperty(prop)) {
1432:                                propInst = this .getPropertyInstance(prop);
1433:                            } else {
1434:                                addPropertyInstance(propInst);
1435:                            }
1436:
1437:                            propInst.populate(formEl, state);
1438:
1439:                        } catch (DataAccessException e) {
1440:                            throw new PopulateException(e);
1441:                        } catch (HarmoniseFactoryException e) {
1442:                            throw new PopulateException(e);
1443:                        } catch (ProfileException e) {
1444:                            throw new PopulateException(e);
1445:                        }
1446:
1447:                    }
1448:                }
1449:            }
1450:
1451:            /**
1452:             * Populates the <code>Profile</code> data.
1453:             * 
1454:             * @throws ProfileException
1455:             */
1456:            public void fillProfileData() throws ProfileException {
1457:                try {
1458:
1459:                    if (m_bIsPopulated == false) {
1460:                        populateFromDatabase();
1461:                    }
1462:
1463:                    if (isPropertyInstancesPopulated() == false) {
1464:                        populatePropertyInstancesFromDatabase();
1465:                    }
1466:                } catch (PopulateException pop_e) {
1467:                    throw new ProfileException(
1468:                            "Problem occured populating Profile", pop_e);
1469:                } catch (DataAccessException da_e) {
1470:                    throw new ProfileException(
1471:                            "Problem occured populating Profile", da_e);
1472:                }
1473:            }
1474:
1475:            /* (non-Javadoc)
1476:             * @see org.openharmonise.rm.dsi.DataStoreObject#getDBTableName()
1477:             */
1478:            public String getDBTableName() {
1479:                String sTable = getDBTableName(m_profObj);
1480:
1481:                return sTable;
1482:            }
1483:
1484:            /* (non-Javadoc)
1485:             * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceJoinConditions(java.lang.String, boolean)
1486:             */
1487:            public JoinConditions getInstanceJoinConditions(String sObjectTag,
1488:                    boolean bIsOuter) throws DataStoreException {
1489:
1490:                return null;
1491:            }
1492:
1493:            /* (non-Javadoc)
1494:             * @see org.openharmonise.rm.dsi.DataStoreObject#processResultSet(org.openharmonise.commons.dsi.CachedResultSet, org.openharmonise.commons.dsi.dml.SelectStatement)
1495:             */
1496:            public List processResultSet(CachedResultSet resultSet,
1497:                    SelectStatement select) {
1498:                //Not implemented as it's pretty complicated to handle with
1499:                //the possibility of profile property instances
1500:                //and objects will be populated when the data is requested
1501:                //anyway, if indeed it's not already populated
1502:                return null;
1503:            }
1504:
1505:            /* (non-Javadoc)
1506:             * @see org.openharmonise.rm.dsi.DataStoreObject#processResultSet(org.openharmonise.commons.dsi.CachedResultSet, org.openharmonise.commons.dsi.dml.SelectStatement, int)
1507:             */
1508:            public List processResultSet(CachedResultSet resultSet,
1509:                    SelectStatement select, int limit) {
1510:                //Not implemented as it's pretty complicated to handle with
1511:                //the possibility of profile property instances
1512:                //and objects will be populated when the data is requested
1513:                //anyway, if indeed it's not already populated
1514:                return null;
1515:            }
1516:
1517:            /* (non-Javadoc)
1518:             * @see java.lang.Object#clone()
1519:             */
1520:            public Object clone() {
1521:                //Note: if exception is thrown it is gonna cause problems with
1522:                //saving, etc so I've elected to throw a RuntimeException
1523:                try {
1524:                    if (m_bIsPopulated == false) {
1525:                        populateFromDatabase();
1526:                    }
1527:
1528:                    if (isPropertyInstancesPopulated() == false) {
1529:                        populatePropertyInstancesFromDatabase();
1530:                    }
1531:
1532:                    AbstractPropertyInstance nextProp = null;
1533:                    //clone the profile
1534:                    Profile other = (Profile) super .clone();
1535:
1536:                    //iterate through prop insts to clone and add to cloned profile
1537:                    Iterator iter = m_propStores.keySet().iterator();
1538:                    other.m_propStores = new Hashtable();
1539:
1540:                    while (iter.hasNext()) {
1541:                        String sKey = (String) iter.next();
1542:                        PropertyInstanceStore propStore = (PropertyInstanceStore) this .m_propStores
1543:                                .get(sKey);
1544:                        //note that the propstore clone method is not called as it
1545:                        //will have a relationship with this Profile rather
1546:                        //than the new cloned one
1547:                        other.m_propStores.put(sKey,
1548:                                other.new PropertyInstanceStore(propStore));
1549:                    }
1550:
1551:                    return other;
1552:                } catch (PopulateException e) {
1553:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
1554:                    throw new IllegalStateException(
1555:                            "Problem occured during clone"
1556:                                    + e.getLocalizedMessage());
1557:                } catch (DataAccessException e) {
1558:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
1559:                    throw new IllegalStateException(
1560:                            "Problem occured during clone"
1561:                                    + e.getLocalizedMessage());
1562:                }
1563:            }
1564:
1565:            /* (non-Javadoc)
1566:             * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceColumnRef(java.lang.String, boolean)
1567:             */
1568:            public ColumnRef getInstanceColumnRef(String sColumn,
1569:                    boolean bIsHist) throws DataStoreException {
1570:                ColumnRef returnColRef = null;
1571:
1572:                returnColRef = getColumnRef(m_profObj, sColumn);
1573:
1574:                if (returnColRef != null) {
1575:                    return returnColRef;
1576:                } else {
1577:                    return super .getInstanceColumnRef(sColumn, bIsHist);
1578:                }
1579:            }
1580:
1581:            /**
1582:             * Returns the database table name for the <code>Profile</code> of the 
1583:             * specified <code>AbstractProfiledObject</code>.
1584:             * 
1585:             * @param profObj the profiled object
1586:             * @return the database table name for the <code>Profile</code> of the 
1587:             * specified <code>AbstractProfiledObject</code>
1588:             */
1589:            public static String getDBTableName(AbstractProfiledObject profObj) {
1590:                String sTable = UNKNOWN_PROFILE;
1591:
1592:                if (profObj != null) {
1593:                    StringBuffer sbuf = new StringBuffer();
1594:
1595:                    sbuf.append(profObj.getDBTableName()).append(EXT_PROFILE);
1596:
1597:                    if (profObj.isHistorical() == true) {
1598:                        sbuf.append(EXT_HIST);
1599:                    }
1600:
1601:                    sTable = sbuf.toString();
1602:                }
1603:
1604:                return sTable;
1605:            }
1606:
1607:            /**
1608:             * Returns the appropriate <code>ColumnRef</code> for the column of the 
1609:             * <code>Profile</code> for the given <code>AbstractProfiledObject</code>.
1610:             * 
1611:             * @param profObj the profiled object
1612:             * @param sColumn the column name
1613:             * @return the appropriate <code>ColumnRef</code> for the specified column
1614:             * @throws DataStoreException if the specified column does not match any
1615:             * valid columns
1616:             */
1617:            public static ColumnRef getColumnRef(
1618:                    AbstractProfiledObject profObj, String sColumn)
1619:                    throws DataStoreException {
1620:                ColumnRef returnColRef = null;
1621:                return getColumnRef(profObj.getClass().getName(), sColumn,
1622:                        profObj.isHistorical());
1623:            }
1624:
1625:            /**
1626:             * Returns the table name for the object of the class name given, taking account
1627:             * for whether the historical table is needed or not.
1628:             * 
1629:             * @param sClassname the class name of an <code>AbstractObject</code>
1630:             * @param bHist <code>true</code> if the table name is 
1631:             * associated with a historical object
1632:             * @return the table name for the object
1633:             * @throws DataStoreException if an error occurs
1634:             */
1635:            public static String getTableName(String sClassname, boolean bHist)
1636:                    throws DataStoreException {
1637:                String sTable = null;
1638:
1639:                StringBuffer sbuf = new StringBuffer();
1640:
1641:                sbuf.append(AbstractObject.getTableName(sClassname, false));
1642:
1643:                sbuf.append(EXT_PROFILE);
1644:
1645:                if (bHist == true) {
1646:                    sbuf.append(EXT_HIST);
1647:                }
1648:
1649:                return sbuf.toString();
1650:            }
1651:
1652:            /**
1653:             * Returns a column reference appropriate for the given 
1654:             * parameters.
1655:             * 
1656:             * @param sClassname the class name of an <code>AbstractObject</code>
1657:             * @param sColumn the column, tag or attribute name
1658:             * @param bHist <code>true</code> if the column reference is 
1659:             * associated with a historical object
1660:             * @return the column reference corresponding to the parameters
1661:             * @throws DataStoreException if an error occurs
1662:             */
1663:            public static ColumnRef getColumnRef(String sClassname,
1664:                    String sColumn, boolean bHist) throws DataStoreException {
1665:                ColumnRef returnColRef = null;
1666:                String sTable = getTableName(sClassname, bHist);
1667:
1668:                if (sColumn.equals(ATTRIB_OBJECT_KEY) == true
1669:                        || sColumn.equals(CLMN_OBJECT_KEY) == true) {
1670:                    returnColRef = new ColumnRef(sTable, CLMN_OBJECT_KEY,
1671:                            ColumnRef.NUMBER);
1672:                } else if (sColumn.equals(CLMN_IS_DEFAULT) == true
1673:                        || sColumn.equals(Profile.ATTRIB_ISDEFAULT) == true) {
1674:                    returnColRef = new ColumnRef(sTable, CLMN_IS_DEFAULT,
1675:                            ColumnRef.NUMBER);
1676:                } else if (sColumn
1677:                        .equals(AbstractEditableObject.TAG_VERSION_COMMENT) == true
1678:                        || sColumn.equals(CLMN_VERSION_COMMENT) == true) {
1679:                    returnColRef = new ColumnRef(sTable, CLMN_VERSION_COMMENT,
1680:                            ColumnRef.TEXT);
1681:                }
1682:
1683:                if (returnColRef == null) {
1684:                    returnColRef = AbstractObject.getColumnRef(sClassname,
1685:                            sColumn);
1686:                    if (returnColRef != null) {
1687:                        returnColRef.setTable(sTable);
1688:                    }
1689:                }
1690:
1691:                return returnColRef;
1692:            }
1693:
1694:            /**
1695:             * Updates the data in the database for this <code>Profile</code>.
1696:             * 
1697:             * @throws PopulateException if any errors occur saving the profile details
1698:             * to the database
1699:             * @throws EditException if any errors occur saving the property instances
1700:             * to the database
1701:             */
1702:            public void update() throws PopulateException, EditException {
1703:
1704:                //first populate if necessary
1705:                if (m_bIsPopulated == false) {
1706:                    populateFromDatabase();
1707:                }
1708:
1709:                try {
1710:
1711:                    if (isPropertyInstancesPopulated() == false) {
1712:                        populatePropertyInstancesFromDatabase();
1713:                    }
1714:                } catch (DataAccessException da_e) {
1715:                    throw new PopulateException(
1716:                            "Error occured while accessing property instances",
1717:                            da_e);
1718:                }
1719:
1720:                //update property instances
1721:                updatePropertyInstances();
1722:
1723:                //Update profile data
1724:                UpdateStatement update = new UpdateStatement();
1725:
1726:                try {
1727:
1728:                    if (m_sSummary != null) {
1729:                        update.addColumnValue(getInstanceColumnRef(TAG_SUMMARY,
1730:                                false), m_sSummary);
1731:                    }
1732:
1733:                    if (m_sVersionComment != null) {
1734:                        update.addColumnValue(getInstanceColumnRef(
1735:                                Profile.CLMN_VERSION_COMMENT, false),
1736:                                m_sVersionComment);
1737:                    }
1738:
1739:                    int nIsDefault = 0;
1740:                    if (m_bIsDefault) {
1741:                        nIsDefault = 1;
1742:                    }
1743:
1744:                    update.addColumnValue(getInstanceColumnRef(CLMN_IS_DEFAULT,
1745:                            false), nIsDefault);
1746:                    update.addWhereCondition(getInstanceColumnRef(ATTRIB_ID,
1747:                            false), "=", m_nId);
1748:                } catch (DataStoreException ds_e) {
1749:                    throw new PopulateException(
1750:                            "Problem occurred while building update statement",
1751:                            ds_e);
1752:                }
1753:
1754:                try {
1755:
1756:                    m_dsi.executeUpdate(update);
1757:
1758:                } catch (DataStoreException ds_e) {
1759:                    throw new PopulateException(
1760:                            "Problem occurred while processing update statement",
1761:                            ds_e);
1762:                }
1763:            }
1764:
1765:            /* (non-Javadoc)
1766:             * @see org.openharmonise.rm.publishing.Publishable#getTagName()
1767:             */
1768:            public String getTagName() {
1769:                return TAG_PROFILE;
1770:            }
1771:
1772:            /*--------------------------------------------------------------------------
1773:            				
1774:            Protected Functions
1775:            
1776:            ---------------------------------------------------------------------------*/
1777:
1778:            /**
1779:             * Returns the <code>AbstractProfiledObject</code> associated with this 
1780:             * <code>Profile</code>.
1781:             */
1782:            protected AbstractProfiledObject getProfiledObject() {
1783:                return m_profObj;
1784:            }
1785:
1786:            /* (non-Javadoc)
1787:             * @see org.openharmonise.rm.resources.AbstractObject#populateFromResultSetRow(java.sql.ResultSet, org.openharmonise.commons.dsi.dml.SelectStatement)
1788:             */
1789:            protected void populateFromResultSetRow(ResultSet rs,
1790:                    SelectStatement select) throws PopulateException {
1791:
1792:                if (isPopulated() == false) {
1793:                    super .populateFromResultSetRow(rs, select);
1794:
1795:                    String sTemp = "";
1796:                    ColumnRef colref = null;
1797:                    boolean bIsHist = isHistorical();
1798:
1799:                    try {
1800:                        colref = getInstanceColumnRef(
1801:                                AbstractEditableObject.TAG_VERSION_COMMENT,
1802:                                bIsHist);
1803:
1804:                        if (select.containsSelectColumn(colref) == true) {
1805:                            m_sVersionComment = rs.getString(select
1806:                                    .getResultSetIndex(colref));
1807:                        }
1808:
1809:                        colref = getInstanceColumnRef(ATTRIB_ISDEFAULT, bIsHist);
1810:
1811:                        if (select.containsSelectColumn(colref) == true) {
1812:                            m_bIsDefault = rs.getBoolean(select
1813:                                    .getResultSetIndex(colref));
1814:                        }
1815:
1816:                    } catch (DataStoreException ds_e) {
1817:                        throw new PopulateException(ds_e.getLocalizedMessage());
1818:                    } catch (SQLException sql_e) {
1819:                        throw new PopulateException(sql_e.getLocalizedMessage());
1820:                    }
1821:                }
1822:            }
1823:
1824:            /* (non-Javadoc)
1825:             * @see org.openharmonise.rm.resources.AbstractObject#populateFromDatabase()
1826:             */
1827:            protected void populateFromDatabase() throws PopulateException {
1828:                super .populateFromDatabase();
1829:            }
1830:
1831:            /* (non-Javadoc)
1832:             * @see org.openharmonise.rm.resources.AbstractObject#addColumnsToPopulateQuery(org.openharmonise.commons.dsi.dml.SelectStatement, boolean)
1833:             */
1834:            protected void addColumnsToPopulateQuery(SelectStatement select,
1835:                    boolean bIsHist) throws DataStoreException {
1836:
1837:                select.addSelectColumn(getInstanceColumnRef(
1838:                        AbstractEditableObject.TAG_VERSION_COMMENT, bIsHist));
1839:                select.addSelectColumn(getInstanceColumnRef(ATTRIB_ISDEFAULT,
1840:                        bIsHist));
1841:                super .addColumnsToPopulateQuery(select, bIsHist);
1842:            }
1843:
1844:            /**
1845:             * Populates all the property instances in this <code>Profile</code>.
1846:             * 
1847:             * @throws PopulateException if an error occurs accessing the data from 
1848:             * the database 
1849:             */
1850:            protected void populatePropertyInstancesFromDatabase()
1851:                    throws PopulateException {
1852:                try {
1853:
1854:                    initialisePropertyInstanceStores();
1855:                } catch (DataAccessException e) {
1856:                    throw new PopulateException(
1857:                            "Problem occurred populating property instances", e);
1858:                }
1859:
1860:                Iterator iter = m_propStores.values().iterator();
1861:
1862:                while (iter.hasNext()) {
1863:                    PropertyInstanceStore propStore = (PropertyInstanceStore) iter
1864:                            .next();
1865:
1866:                    populatePropertyInstanceStore(propStore);
1867:                }
1868:            }
1869:
1870:            /**
1871:             * Populates the <code>ProfilePropertyInstance</code>s held by this 
1872:             * <code>Profile</code>.
1873:             * 
1874:             * @throws PopulateException if any errors occur
1875:             */
1876:            protected synchronized void populateProfilePropertyInstances()
1877:                    throws PopulateException {
1878:                PropertyInstanceStore propStore = (PropertyInstanceStore) m_propStores
1879:                        .get(Profile.class.getName());
1880:
1881:                if (propStore.isPopulated() == false) {
1882:
1883:                    SelectStatement select = new SelectStatement();
1884:
1885:                    boolean bIsHist = isHistorical();
1886:
1887:                    ColumnRef dataPropIdCol = null;
1888:
1889:                    try {
1890:
1891:                        String sProfDataTable = ProfilePropertyInstance
1892:                                .getDBTableName(this );
1893:
1894:                        select.addSelectColumn(getProfileDataColumn(
1895:                                sProfDataTable,
1896:                                AbstractPropertyInstance.CLMN_ID));
1897:
1898:                        dataPropIdCol = getProfileDataColumn(sProfDataTable,
1899:                                AbstractPropertyInstance.CLMN_PROPERTY_ID);
1900:
1901:                        select.addSelectColumn(dataPropIdCol);
1902:
1903:                        select.addSelectColumn(getProfileDataColumn(
1904:                                sProfDataTable,
1905:                                AbstractPropertyInstance.CLMN_VERSION_COMMENT));
1906:
1907:                        select.addSelectColumn(getProfileDataColumn(
1908:                                sProfDataTable, CLMN_NAME));
1909:
1910:                        select.addSelectColumn(getProfileDataColumn(
1911:                                sProfDataTable, CLMN_SUMMARY));
1912:
1913:                        ColumnRef profId_colref = getProfileDataColumn(
1914:                                sProfDataTable,
1915:                                ProfilePropertyInstance.CLMN_PROFILE_PARENT);
1916:
1917:                        select.addWhereCondition(profId_colref, "=", m_nId);
1918:
1919:                        //need to add order by to ensure that all property instances
1920:                        //of a property get handled consecutively
1921:                        select.setOrderBy(dataPropIdCol);
1922:
1923:                    } catch (DataStoreException da_e) {
1924:                        throw new PopulateException(
1925:                                "Error occured building query", da_e);
1926:                    }
1927:
1928:                    ResultSet rs = null;
1929:
1930:                    try {
1931:                        int nProfId = 0;
1932:                        int nPropId = 0;
1933:                        rs = m_dsi.execute(select);
1934:                        ProfilePropertyInstance propInst = null;
1935:                        while (rs.next()) {
1936:                            nProfId = rs.getInt(1);
1937:                            nPropId = rs.getInt(2);
1938:                            if (propInst == null
1939:                                    || propInst.getProperty().getId() != nPropId) {
1940:                                //before we're done set populated flag
1941:                                if (propInst != null) {
1942:                                    propInst.setIsPopulated(true);
1943:                                }
1944:
1945:                                propInst = new ProfilePropertyInstance(m_dsi,
1946:                                        this );
1947:
1948:                                Property prop = (Property) HarmoniseObjectFactory
1949:                                        .instantiateHarmoniseObject(m_dsi,
1950:                                                Property.class.getName(),
1951:                                                nPropId);
1952:
1953:                                //if prop no longer exists we hve to delete all prop insts with
1954:                                //this prop and not add it to this profile
1955:                                if (prop == null) {
1956:                                    if (m_logger.isLoggable(Level.INFO)) {
1957:                                        m_logger
1958:                                                .logp(
1959:                                                        Level.INFO,
1960:                                                        this .getClass()
1961:                                                                .getName(),
1962:                                                        "populateGeneralPropertyInstances",
1963:                                                        "Property "
1964:                                                                + nPropId
1965:                                                                + " no longer exists so removing value");
1966:                                    }
1967:
1968:                                    ProfileValue prof = new ProfileValue(m_dsi,
1969:                                            nProfId, m_profObj);
1970:                                    prof.setName(rs.getString(4));
1971:                                    prof.setSummary(rs.getString(5));
1972:
1973:                                    try {
1974:                                        prof.delete();
1975:                                    } catch (ProfileException e) {
1976:                                        //won't escalate this as the profile value
1977:                                        //will only hang around for this version of
1978:                                        //the object and the behaviour of this
1979:                                        //object should be fine
1980:                                        m_logger.log(Level.WARNING, e
1981:                                                .getLocalizedMessage(), e);
1982:                                    }
1983:
1984:                                    propInst = null;
1985:                                    continue;
1986:                                }
1987:
1988:                                propInst.setProperty(prop);
1989:                                propInst.setVersionComment(rs.getString(3));
1990:
1991:                                propStore.addPropertyInstance(propInst);
1992:                            }
1993:
1994:                            ProfileValue prof = new ProfileValue(m_dsi,
1995:                                    nProfId, m_profObj);
1996:                            prof.setName(rs.getString(4));
1997:                            prof.setSummary(rs.getString(5));
1998:                            prof.setProperty(propInst.getProperty());
1999:                            propInst.addValue(prof, nProfId);
2000:                        }
2001:                        if (propInst != null) {
2002:                            propInst.setIsPopulated(true);
2003:                        }
2004:
2005:                        propStore.setIsPopulated(true);
2006:                    } catch (SQLException sql_e) {
2007:                        throw new PopulateException(
2008:                                "Error occured processing query", sql_e);
2009:                    } catch (HarmoniseFactoryException f_e) {
2010:                        throw new PopulateException(
2011:                                "Error occured getting property from factory",
2012:                                f_e);
2013:                    } catch (DataStoreException ds_e) {
2014:                        throw new PopulateException(
2015:                                "Error occured processing query", ds_e);
2016:                    } catch (DataAccessException da_e) {
2017:                        throw new PopulateException(
2018:                                "Error occured populating property instance",
2019:                                da_e);
2020:                    } catch (InvalidPropertyValueException ipv_e) {
2021:                        // do nothing - the value just won't be added
2022:                        m_logger.log(Level.FINE, "Ignoring exception", ipv_e);
2023:                    } catch (InvalidNameException e) {
2024:                        throw new PopulateException(e);
2025:                    } finally {
2026:                        if (rs != null) {
2027:                            try {
2028:
2029:                                rs.close();
2030:                            } catch (SQLException sql_e) {
2031:                                throw new PopulateException(
2032:                                        "Had trouble closing result set", sql_e);
2033:                            }
2034:                        }
2035:                    }
2036:
2037:                }
2038:            }
2039:
2040:            /**
2041:             * Populates the <code>GeneralPropertyInstance</code>s held by this 
2042:             * <code>Profile</code>.
2043:             * 
2044:             * @throws PopulateException if any errors occur
2045:             */
2046:            protected synchronized void populateGeneralPropertyInstances()
2047:                    throws PopulateException {
2048:                PropertyInstanceStore propStore = (PropertyInstanceStore) m_propStores
2049:                        .get(GeneralPropertyInstance.class.getName());
2050:
2051:                if (propStore.isPopulated() == false) {
2052:
2053:                    SelectStatement select = new SelectStatement();
2054:
2055:                    boolean bIsHist = isHistorical();
2056:                    ColumnRef dataPropIdCol = null;
2057:
2058:                    try {
2059:
2060:                        String sProfDataTable = GeneralPropertyInstance
2061:                                .getDBTableName(this );
2062:
2063:                        select.addSelectColumn(getProfileDataColumn(
2064:                                sProfDataTable,
2065:                                AbstractPropertyInstance.CLMN_ID));
2066:
2067:                        dataPropIdCol = getProfileDataColumn(sProfDataTable,
2068:                                AbstractPropertyInstance.CLMN_PROPERTY_ID);
2069:
2070:                        select.addSelectColumn(dataPropIdCol);
2071:
2072:                        ColumnRef ver_com_colref = getProfileDataColumn(
2073:                                sProfDataTable,
2074:                                AbstractPropertyInstance.CLMN_VERSION_COMMENT);
2075:
2076:                        select.addSelectColumn(ver_com_colref);
2077:                        select.addSelectColumn(getProfileDataColumn(
2078:                                sProfDataTable,
2079:                                GeneralPropertyInstance.CLMN_VALUE));
2080:
2081:                        ColumnRef profId_colref = getProfileDataColumn(
2082:                                sProfDataTable,
2083:                                GeneralPropertyInstance.CLMN_PROFILE_ID);
2084:
2085:                        select.addWhereCondition(profId_colref, "=", m_nId);
2086:
2087:                        //need to add order by to ensure that all property instances
2088:                        //of a property get handled consecutively
2089:                        select.setOrderBy(dataPropIdCol);
2090:
2091:                    } catch (DataStoreException da_e) {
2092:                        throw new PopulateException(
2093:                                "Error occured building query", da_e);
2094:                    }
2095:
2096:                    ResultSet rs = null;
2097:
2098:                    try {
2099:
2100:                        rs = m_dsi.execute(select);
2101:                        GeneralPropertyInstance propInst = null;
2102:                        while (rs.next()) {
2103:                            int nPropId = rs.getInt(2);
2104:                            if (propInst == null
2105:                                    || propInst.getProperty().getId() != nPropId) {
2106:                                if (propInst != null) {
2107:                                    propInst.setIsPopulated(true);
2108:                                }
2109:                                propInst = new GeneralPropertyInstance(m_dsi,
2110:                                        this );
2111:
2112:                                Property prop = (Property) HarmoniseObjectFactory
2113:                                        .instantiateHarmoniseObject(m_dsi,
2114:                                                Property.class.getName(),
2115:                                                nPropId);
2116:
2117:                                //if prop no longer exists we hve to delete all prop insts with
2118:                                //this prop and not add it to this profile
2119:                                if (prop == null) {
2120:                                    if (m_logger.isLoggable(Level.INFO)) {
2121:                                        m_logger
2122:                                                .logp(
2123:                                                        Level.INFO,
2124:                                                        this .getClass()
2125:                                                                .getName(),
2126:                                                        "populateGeneralPropertyInstances",
2127:                                                        "Property "
2128:                                                                + nPropId
2129:                                                                + " no longer exists so removing value");
2130:                                    }
2131:
2132:                                    DeleteStatement delete = new DeleteStatement();
2133:
2134:                                    delete.addWhereCondition(dataPropIdCol,
2135:                                            "=", nPropId);
2136:
2137:                                    m_dsi.execute(delete);
2138:
2139:                                    propInst = null;
2140:
2141:                                    continue;
2142:                                }
2143:
2144:                                propInst.setProperty(prop);
2145:                                propInst.setVersionComment(rs.getString(3));
2146:
2147:                                propStore.addPropertyInstance(propInst);
2148:                            }
2149:                            propInst.addValue(rs.getString(4), rs.getInt(1));
2150:
2151:                        }
2152:                        if (propInst != null) {
2153:                            propInst.setIsPopulated(true);
2154:                        }
2155:
2156:                        propStore.setIsPopulated(true);
2157:                    } catch (SQLException sql_e) {
2158:                        throw new PopulateException(
2159:                                "Error occured processing query", sql_e);
2160:                    } catch (HarmoniseFactoryException f_e) {
2161:                        throw new PopulateException(
2162:                                "Error occured getting property from factory",
2163:                                f_e);
2164:                    } catch (DataStoreException ds_e) {
2165:                        throw new PopulateException(
2166:                                "Error occured processing query", ds_e);
2167:                    } catch (DataAccessException da_e) {
2168:                        throw new PopulateException(
2169:                                "Error occured populating property instance",
2170:                                da_e);
2171:                    } catch (InvalidPropertyValueException ipv_e) {
2172:                        //do nothing - the value just won't be added
2173:                        m_logger.log(Level.FINE, "Ignoring exception", ipv_e);
2174:                    } finally {
2175:                        if (rs != null) {
2176:                            try {
2177:
2178:                                rs.close();
2179:                            } catch (SQLException sql_e) {
2180:                                throw new PopulateException(
2181:                                        "Had trouble closing result set", sql_e);
2182:                            }
2183:                        }
2184:                    }
2185:                }
2186:            }
2187:
2188:            /**
2189:             * Populates the <code>ChildObjectPropertyInstance</code>s, of the type
2190:             * specified by the class name given, held by this <code>Profile</code>.
2191:             * 
2192:             * @param sTableName the database table name of the <code>AbstractChildObject</code>
2193:             * class which can be values for the property instances to be populated 
2194:             * 
2195:             * @throws PopulateException if any errors occur
2196:             */
2197:            protected synchronized void populateChildObjectPropertyInstances(
2198:                    String sTableName) throws PopulateException {
2199:                PropertyInstanceStore propStore = (PropertyInstanceStore) m_propStores
2200:                        .get(sTableName);
2201:
2202:                if (propStore.isPopulated() == false) {
2203:
2204:                    SelectStatement select = new SelectStatement();
2205:
2206:                    boolean bIsHist = isHistorical();
2207:                    ColumnRef dataPropIdCol = null;
2208:
2209:                    try {
2210:
2211:                        String sProfDataTable = ChildObjectPropertyInstance
2212:                                .constructDBTableName(this , sTableName);
2213:                        String sClassname = propStore.getAssociatedClassname();
2214:
2215:                        ColumnRef valIdCol = AbstractObject.getColumnRef(
2216:                                sClassname, ATTRIB_ID);
2217:                        ColumnRef valTypeCol = AbstractObject.getColumnRef(
2218:                                sClassname, ATTRIB_TYPE);
2219:                        ColumnRef propTypeCol = AbstractObject.getColumnRef(
2220:                                Property.class.getName(),
2221:                                AbstractObject.ATTRIB_TYPE);
2222:                        ColumnRef propIdCol = AbstractObject.getColumnRef(
2223:                                Property.class.getName(),
2224:                                AbstractObject.ATTRIB_ID);
2225:
2226:                        dataPropIdCol = getProfileDataColumn(sProfDataTable,
2227:                                AbstractPropertyInstance.CLMN_PROPERTY_ID);
2228:
2229:                        ColumnRef objIdCol = getProfileDataColumn(
2230:                                sProfDataTable,
2231:                                ChildObjectPropertyInstance.CLMN_OBJECT_ID);
2232:
2233:                        select.addSelectColumn(getProfileDataColumn(
2234:                                sProfDataTable,
2235:                                AbstractPropertyInstance.CLMN_ID));
2236:
2237:                        select.addSelectColumn(dataPropIdCol);
2238:
2239:                        ColumnRef ver_com_colref = getProfileDataColumn(
2240:                                sProfDataTable,
2241:                                AbstractPropertyInstance.CLMN_VERSION_COMMENT);
2242:
2243:                        select.addSelectColumn(ver_com_colref);
2244:                        select.addSelectColumn(objIdCol);
2245:
2246:                        select.addSelectColumn(valTypeCol);
2247:                        select.addSelectColumn(propTypeCol);
2248:
2249:                        ColumnRef profId_colref = getProfileDataColumn(
2250:                                sProfDataTable,
2251:                                AbstractPropertyInstance.CLMN_PROFILE_ID);
2252:
2253:                        select.addJoinCondition(valIdCol, objIdCol);
2254:                        select.addJoinCondition(propIdCol, dataPropIdCol);
2255:
2256:                        select.addWhereCondition(profId_colref, "=", m_nId);
2257:
2258:                        //need to add order by to ensure that all property instances
2259:                        //of a property get handled consecutively
2260:                        select.setOrderBy(dataPropIdCol);
2261:
2262:                    } catch (DataStoreException da_e) {
2263:                        throw new PopulateException(
2264:                                "Error occured building query", da_e);
2265:                    }
2266:
2267:                    ResultSet rs = null;
2268:
2269:                    try {
2270:                        int nPropId = 0;
2271:                        rs = m_dsi.execute(select);
2272:                        ChildObjectPropertyInstance propInst = null;
2273:                        while (rs.next()) {
2274:                            nPropId = rs.getInt(2);
2275:
2276:                            if (propInst == null
2277:                                    || propInst.getProperty().getId() != nPropId) {
2278:                                if (propInst != null) {
2279:                                    propInst.setIsPopulated(true);
2280:                                }
2281:
2282:                                Property prop = (Property) HarmoniseObjectFactory
2283:                                        .instantiateHarmoniseObject(m_dsi, rs
2284:                                                .getString(6), nPropId);
2285:
2286:                                //if prop no longer exists we hve to delete all prop insts with
2287:                                //this prop and not add it to this profile
2288:                                if (prop == null) {
2289:                                    if (m_logger.isLoggable(Level.INFO)) {
2290:                                        m_logger
2291:                                                .logp(
2292:                                                        Level.INFO,
2293:                                                        this .getClass()
2294:                                                                .getName(),
2295:                                                        "populateGeneralPropertyInstances",
2296:                                                        "Property "
2297:                                                                + nPropId
2298:                                                                + " no longer exists so removing value");
2299:                                    }
2300:
2301:                                    DeleteStatement delete = new DeleteStatement();
2302:
2303:                                    delete.addWhereCondition(dataPropIdCol,
2304:                                            "=", nPropId);
2305:
2306:                                    m_dsi.execute(delete);
2307:
2308:                                    propInst = null;
2309:
2310:                                    continue;
2311:                                }
2312:
2313:                                Range range = prop.getRange();
2314:
2315:                                if (range == null) {
2316:                                    throw new PopulateException(
2317:                                            "No range attached to property");
2318:                                }
2319:
2320:                                propInst = (ChildObjectPropertyInstance) range
2321:                                        .getPropertyInstanceClass()
2322:                                        .newInstance();
2323:                                propInst.setDataStoreInterface(m_dsi);
2324:                                propInst.setProfile(this );
2325:
2326:                                propInst.setProperty(prop);
2327:                                propInst.setVersionComment(rs.getString(3));
2328:
2329:                                propStore.addPropertyInstance(propInst);
2330:                            }
2331:
2332:                            AbstractChildObject child = (AbstractChildObject) HarmoniseObjectFactory
2333:                                    .instantiateHarmoniseObject(m_dsi, rs
2334:                                            .getString(5), rs.getInt(4));
2335:
2336:                            propInst.addValue(child, rs.getInt(1));
2337:                        }
2338:                        if (propInst != null) {
2339:                            propInst.setIsPopulated(true);
2340:                        }
2341:
2342:                        propStore.setIsPopulated(true);
2343:                    } catch (SQLException sql_e) {
2344:                        throw new PopulateException(
2345:                                "Error occured processing query", sql_e);
2346:                    } catch (HarmoniseFactoryException f_e) {
2347:                        throw new PopulateException(
2348:                                "Error occured getting property from factory",
2349:                                f_e);
2350:                    } catch (DataStoreException ds_e) {
2351:                        throw new PopulateException(
2352:                                "Error occured processing query", ds_e);
2353:                    } catch (DataAccessException da_e) {
2354:                        throw new PopulateException(
2355:                                "Error occured populating property instance",
2356:                                da_e);
2357:                    } catch (InvalidPropertyValueException ipv_e) {
2358:                        //do nothing - the value just won't be added
2359:                        m_logger.log(Level.FINE, "Ignoring exception", ipv_e);
2360:                    } catch (InstantiationException e) {
2361:                        throw new PopulateException(e.getLocalizedMessage(), e);
2362:                    } catch (IllegalAccessException e) {
2363:                        throw new PopulateException(e.getLocalizedMessage(), e);
2364:                    } catch (ClassNotFoundException e) {
2365:                        throw new PopulateException(e.getLocalizedMessage(), e);
2366:                    } finally {
2367:                        if (rs != null) {
2368:                            try {
2369:
2370:                                rs.close();
2371:                            } catch (SQLException sql_e) {
2372:                                throw new PopulateException(
2373:                                        "Had trouble closing result set", sql_e);
2374:                            }
2375:                        }
2376:                    }
2377:                }
2378:            }
2379:
2380:            /*--------------------------------------------------------------------------
2381:            				
2382:            Private Functions
2383:            
2384:            ---------------------------------------------------------------------------*/
2385:
2386:            /**
2387:             * Returns the <code>ColumnRef</code> for the profile data associated with
2388:             * the specified table and column.
2389:             * 
2390:             * @param sTable the property instance database table
2391:             * @param sCol the column name
2392:             * @return the matching column reference for the specified table and column
2393:             * @throws DataStoreException if no valid column references match the 
2394:             * specified table and column
2395:             */
2396:            private ColumnRef getProfileDataColumn(String sTable, String sCol)
2397:                    throws DataStoreException {
2398:                ColumnRef returnColRef = null;
2399:
2400:                if (sCol.equals(AbstractPropertyInstance.CLMN_PROPERTY_ID) == true) {
2401:                    returnColRef = new ColumnRef(sTable,
2402:                            AbstractPropertyInstance.CLMN_PROPERTY_ID,
2403:                            ColumnRef.NUMBER);
2404:                } else if (sCol.equals(GeneralPropertyInstance.CLMN_PROFILE_ID) == true) {
2405:                    returnColRef = new ColumnRef(sTable,
2406:                            GeneralPropertyInstance.CLMN_PROFILE_ID,
2407:                            ColumnRef.NUMBER);
2408:                } else if (sCol
2409:                        .equals(AbstractPropertyInstance.CLMN_VERSION_COMMENT) == true) {
2410:                    returnColRef = new ColumnRef(sTable,
2411:                            AbstractPropertyInstance.CLMN_VERSION_COMMENT,
2412:                            ColumnRef.TEXT);
2413:                } else if (sCol.equals(GeneralPropertyInstance.CLMN_VALUE) == true) {
2414:                    returnColRef = new ColumnRef(sTable,
2415:                            GeneralPropertyInstance.CLMN_VALUE, ColumnRef.TEXT);
2416:                } else if (sCol.equals(GeneralPropertyInstance.CLMN_ID) == true) {
2417:                    returnColRef = new ColumnRef(sTable,
2418:                            GeneralPropertyInstance.CLMN_ID, ColumnRef.NUMBER);
2419:                } else if (sCol
2420:                        .equals(ProfilePropertyInstance.CLMN_PROFILE_PARENT) == true) {
2421:                    returnColRef = new ColumnRef(sTable,
2422:                            ProfilePropertyInstance.CLMN_PROFILE_PARENT,
2423:                            ColumnRef.NUMBER);
2424:                } else if (sCol.equals(CLMN_NAME) == true) {
2425:                    returnColRef = new ColumnRef(sTable, CLMN_NAME,
2426:                            ColumnRef.NUMBER);
2427:                } else if (sCol.equals(CLMN_SUMMARY) == true) {
2428:                    returnColRef = new ColumnRef(sTable, CLMN_SUMMARY,
2429:                            ColumnRef.NUMBER);
2430:                } else if (sCol
2431:                        .equals(ChildObjectPropertyInstance.CLMN_OBJECT_ID) == true) {
2432:                    returnColRef = new ColumnRef(sTable,
2433:                            ChildObjectPropertyInstance.CLMN_OBJECT_ID,
2434:                            ColumnRef.NUMBER);
2435:                }
2436:
2437:                if (returnColRef != null) {
2438:                    return returnColRef;
2439:                } else {
2440:                    throw new InvalidColumnReferenceException(sCol);
2441:                }
2442:            }
2443:
2444:            /**
2445:             * Returns <code>true</code> if all the property instances have been 
2446:             * populated, otherwise <code>false</code>.
2447:             * 
2448:             * @return <code>true</code> if all the property instances have been 
2449:             * populated, otherwise <code>false</code>
2450:             * @throws DataAccessException if any errors occur accessing property 
2451:             * instance data
2452:             */
2453:            private boolean isPropertyInstancesPopulated()
2454:                    throws DataAccessException {
2455:                boolean bIsPopulated = true;
2456:
2457:                initialisePropertyInstanceStores();
2458:
2459:                Iterator iter = m_propStores.values().iterator();
2460:
2461:                while (bIsPopulated == true && iter.hasNext()) {
2462:                    PropertyInstanceStore propStore = (PropertyInstanceStore) iter
2463:                            .next();
2464:                    if (propStore.isPopulated() == false) {
2465:                        bIsPopulated = false;
2466:                    }
2467:                }
2468:
2469:                return bIsPopulated;
2470:            }
2471:
2472:            /**
2473:             * Initialises the collection of <code>PropertyInstanceStore</code>s.
2474:             * 
2475:             * @throws DataAccessException if an error occurs finding the available
2476:             * properties or initialising the appropriate <code>PropertyInstanceStore</code>s
2477:             * 
2478:             */
2479:            private void initialisePropertyInstanceStores()
2480:                    throws DataAccessException {
2481:                String sKey = null;
2482:                String sClassname = null;
2483:
2484:                List props = getAvailableProperties();
2485:
2486:                Iterator iter = props.iterator();
2487:
2488:                while (iter.hasNext()) {
2489:                    Property prop = (Property) iter.next();
2490:
2491:                    if (isPropertyInstanceProfile(prop) == true) {
2492:                        sKey = Profile.class.getName();
2493:
2494:                    } else if (isPropertyInstanceChildObject(prop) == true) {
2495:                        Range range = prop.getRange();
2496:                        if (m_profObj instanceof  AbstractChildObject) {
2497:                            sClassname = ((ChildObjectRange) range)
2498:                                    .getChildObjectValueClassName((AbstractChildObject) m_profObj);
2499:                        } else {
2500:                            sClassname = range.getObject();
2501:                        }
2502:
2503:                        try {
2504:                            sKey = DatabaseInfo.getInstance().getTableName(
2505:                                    sClassname);
2506:                        } catch (DataStoreException e) {
2507:                            throw new DataAccessException(
2508:                                    "Trouble finding class for " + sKey);
2509:                        }
2510:
2511:                    } else {
2512:                        sKey = GeneralPropertyInstance.class.getName();
2513:                    }
2514:
2515:                    if (m_propStores.containsKey(sKey) == false) {
2516:                        if (sClassname == null) {
2517:                            m_propStores.put(sKey, new PropertyInstanceStore(
2518:                                    sKey));
2519:                        } else {
2520:                            m_propStores.put(sKey, new PropertyInstanceStore(
2521:                                    sKey, sClassname));
2522:                        }
2523:                    }
2524:                }
2525:            }
2526:
2527:            /**
2528:             * Returns <code>true</code> if the specified <code>Property</code> 
2529:             * represents a general datatype property.
2530:             * 
2531:             * @param prop the <code>Property</code> to test
2532:             * @return <code>true</code> if the <code>Property</code> given 
2533:             * represents a general datatype property.
2534:             * @throws DataAccessException if there is an error accessing the
2535:             * <code>Range</code> of the <code>Property</code>
2536:             */
2537:            private boolean isPropertyInstanceGeneral(Property prop)
2538:                    throws DataAccessException {
2539:                boolean bIsGen = false;
2540:                if (prop != null) {
2541:                    Range range = prop.getRange();
2542:
2543:                    try {
2544:                        if (GeneralPropertyInstance.class
2545:                                .isAssignableFrom(range
2546:                                        .getPropertyInstanceClass())) {
2547:                            bIsGen = true;
2548:                        }
2549:                    } catch (ClassNotFoundException e) {
2550:                        m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
2551:                    }
2552:                }
2553:
2554:                return bIsGen;
2555:            }
2556:
2557:            /**
2558:             * Returns <code>true</code> if the specified <code>Property</code> 
2559:             * represents an <code>AbstractChildObject</code> datatype property.
2560:             * 
2561:             * @param prop the <code>Property</code> to test
2562:             * @return <code>true</code> if the specified <code>Property</code> 
2563:             * represents an <code>AbstractChildObject</code> datatype property.
2564:             * @throws DataAccessException if there is an error accessing the
2565:             * <code>Range</code> of the <code>Property</code>
2566:             */
2567:            private boolean isPropertyInstanceChildObject(Property prop)
2568:                    throws DataAccessException {
2569:
2570:                boolean bIsChild = false;
2571:                if (prop != null) {
2572:
2573:                    Range range = prop.getRange();
2574:
2575:                    if (range != null) {
2576:                        try {
2577:                            if (ChildObjectPropertyInstance.class
2578:                                    .isAssignableFrom(range
2579:                                            .getPropertyInstanceClass())) {
2580:                                bIsChild = true;
2581:                            }
2582:                        } catch (ClassNotFoundException e) {
2583:                            m_logger.log(Level.WARNING,
2584:                                    e.getLocalizedMessage(), e);
2585:                        }
2586:                    }
2587:                }
2588:
2589:                return bIsChild;
2590:            }
2591:
2592:            /**
2593:             * Returns <code>true</code> if the specified <code>Property</code> 
2594:             * represents a <code>Profile</code> datatype property.
2595:             * 
2596:             * @param prop the <code>Property</code> to test 
2597:             * @return <code>true</code> if the specified <code>Property</code> 
2598:             * represents a <code>Profile</code> datatype property.
2599:             * @throws DataAccessException if there is an error accessing the
2600:             * <code>Range</code> of the <code>Property</code>
2601:             */
2602:            private boolean isPropertyInstanceProfile(Property prop)
2603:                    throws DataAccessException {
2604:
2605:                boolean bIsProfile = false;
2606:                if (prop != null) {
2607:
2608:                    Range range = prop.getRange();
2609:                    if (range != null) {
2610:                        try {
2611:                            if (ProfilePropertyInstance.class
2612:                                    .isAssignableFrom(range
2613:                                            .getPropertyInstanceClass())) {
2614:                                bIsProfile = true;
2615:                            }
2616:                        } catch (ClassNotFoundException e) {
2617:                            m_logger.log(Level.WARNING,
2618:                                    e.getLocalizedMessage(), e);
2619:                        }
2620:                    }
2621:                }
2622:
2623:                return bIsProfile;
2624:            }
2625:
2626:            /**
2627:             * Updates all property instance data in the database.
2628:             * 
2629:             * @throws PopulateException if there is an error accessing data held in 
2630:             * the property instances
2631:             * @throws EditException if there is an error saving the data to the database
2632:             */
2633:            private void updatePropertyInstances() throws PopulateException,
2634:                    EditException {
2635:                Iterator iter = m_propStores.values().iterator();
2636:
2637:                while (iter.hasNext()) {
2638:
2639:                    try {
2640:                        ((PropertyInstanceStore) iter.next()).update();
2641:                    } catch (ProfileException e) {
2642:                        throw new PopulateException(e.getLocalizedMessage(), e);
2643:                    }
2644:
2645:                }
2646:            }
2647:
2648:            /**
2649:             * Deletes all property instances from the database for the specified
2650:             * <code>PropertyInstanceStore</code>.
2651:             * 
2652:             * @param store the <code>PropertyInstanceStore</code> to delete
2653:             * @throws ProfileException if an error occurs deleting the data
2654:             * from the database
2655:             */
2656:            private void deletePropertyInstances(PropertyInstanceStore store)
2657:                    throws ProfileException {
2658:                String sStoreLabel = store.getLabel();
2659:
2660:                if (sStoreLabel.equals(Profile.class.getName()) == true) {
2661:                    Iterator iter = store.getValues().iterator();
2662:
2663:                    while (iter.hasNext()) {
2664:                        ProfilePropertyInstance propInst = (ProfilePropertyInstance) iter
2665:                                .next();
2666:
2667:                        propInst.delete();
2668:                    }
2669:                } else {
2670:                    DeleteStatement delete = new DeleteStatement();
2671:
2672:                    String sDataTable = null;
2673:
2674:                    if (sStoreLabel.equals(GeneralPropertyInstance.class
2675:                            .getName()) == true) {
2676:                        sDataTable = GeneralPropertyInstance
2677:                                .getDBTableName(this );
2678:                    } else {
2679:                        try {
2680:                            sDataTable = ChildObjectPropertyInstance
2681:                                    .getDBTableName(this , store
2682:                                            .getAssociatedClassname());
2683:                        } catch (DataStoreException e) {
2684:                            throw new ProfileException(
2685:                                    "Problem finding profile data table", e);
2686:                        }
2687:                    }
2688:
2689:                    try {
2690:                        ColumnRef profId_colref = getProfileDataColumn(
2691:                                sDataTable,
2692:                                GeneralPropertyInstance.CLMN_PROFILE_ID);
2693:
2694:                        delete.addWhereCondition(profId_colref, "=", m_nId);
2695:                        m_dsi.execute(delete);
2696:                    } catch (DataStoreException e) {
2697:                        throw new ProfileException(
2698:                                "Error occured deleting property instances", e);
2699:                    }
2700:
2701:                }
2702:
2703:            }
2704:
2705:            /**
2706:             * Populates the given <code>PropertyInstanceStore</code> from the database.
2707:             * 
2708:             * @param propStore the <code>PropertyInstanceStore</code> to populate
2709:             * @throws PopulateException if there is an error populating the 
2710:             * <code>PropertyInstanceStore</code>
2711:             */
2712:            private void populatePropertyInstanceStore(
2713:                    PropertyInstanceStore propStore) throws PopulateException {
2714:                if (propStore.isPopulated() == false) {
2715:                    if (propStore.getLabel().equals(
2716:                            GeneralPropertyInstance.class.getName()) == true) {
2717:                        populateGeneralPropertyInstances();
2718:                    } else if (propStore.getLabel().equals(
2719:                            Profile.class.getName()) == true) {
2720:                        populateProfilePropertyInstances();
2721:                    } else {
2722:                        //assume it's a store for child object prop insts
2723:                        populateChildObjectPropertyInstances(propStore
2724:                                .getLabel());
2725:                    }
2726:                }
2727:
2728:            }
2729:
2730:            /**
2731:             * Returns the <code>PropertyInstanceStore</code> associated with the specified 
2732:             * <code>Property</code>.
2733:             * 
2734:             * @param prop the <code>Property</code>
2735:             * @return the <code>PropertyInstanceStore</code> associated with the specified 
2736:             * <code>Property</code>
2737:             * @throws InvalidPropertyInstanceException if the specified <code>Property</code>
2738:             * is invalid for this <code>Profile</code>
2739:             * @throws DataAccessException if there is an error getting the <code>Range</code>
2740:             * for the <code>Property</code>
2741:             */
2742:            private PropertyInstanceStore getPropertyInstanceStore(Property prop)
2743:                    throws InvalidPropertyInstanceException,
2744:                    DataAccessException {
2745:                PropertyInstanceStore propStore = null;
2746:                String sKey = null;
2747:                String sClassname = null;
2748:
2749:                if (isValidProperty(prop) == false) {
2750:
2751:                    String sPropName = null;
2752:
2753:                    if (prop != null) {
2754:                        sPropName = prop.getName();
2755:                    }
2756:
2757:                    throw new InvalidPropertyInstanceException(
2758:                            "Property not valid on [" + m_profObj + "]:"
2759:                                    + sPropName);
2760:                }
2761:
2762:                if (isPropertyInstanceChildObject(prop) == true) {
2763:                    ChildObjectRange range = (ChildObjectRange) prop.getRange();
2764:                    if (m_profObj instanceof  AbstractChildObject) {
2765:                        sClassname = range
2766:                                .getChildObjectValueClassName((AbstractChildObject) m_profObj);
2767:                    } else {
2768:                        sClassname = prop.getRange().getObject();
2769:                    }
2770:
2771:                    try {
2772:                        sKey = DatabaseInfo.getInstance().getTableName(
2773:                                sClassname);
2774:                    } catch (DataStoreException e) {
2775:                        throw new DataAccessException(
2776:                                "Trouble finding class for " + sKey);
2777:                    }
2778:
2779:                } else if (isPropertyInstanceGeneral(prop) == true) {
2780:                    sKey = GeneralPropertyInstance.class.getName();
2781:
2782:                } else if (isPropertyInstanceProfile(prop) == true) {
2783:                    sKey = Profile.class.getName();
2784:                } else {
2785:                    throw new InvalidPropertyInstanceException(
2786:                            "Property not allowed in profile");
2787:                }
2788:
2789:                propStore = (PropertyInstanceStore) m_propStores.get(sKey);
2790:
2791:                if (propStore == null) {
2792:                    //double checked synchronized block to avoid concurrency problems
2793:                    synchronized (m_propStores) {
2794:                        propStore = (PropertyInstanceStore) m_propStores
2795:                                .get(sKey);
2796:
2797:                        if (propStore == null) {
2798:                            if (sClassname == null) {
2799:                                propStore = new PropertyInstanceStore(sKey);
2800:                            } else {
2801:                                propStore = new PropertyInstanceStore(sKey,
2802:                                        sClassname);
2803:                            }
2804:
2805:                            m_propStores.put(sKey, propStore);
2806:                        }
2807:                    }
2808:
2809:                }
2810:
2811:                return propStore;
2812:            }
2813:
2814:            /**
2815:             * Returns the <code>PropertyInstanceStore</code> assocated with the 
2816:             * <code>Property</code> of the specified name.
2817:             * 
2818:             * @param sPropName the name of the <code>Property</code>
2819:             * @return the <code>PropertyInstanceStore</code> assocated with the 
2820:             * <code>Property</code> of the specified name.
2821:             */
2822:            private PropertyInstanceStore getPropertyInstanceStore(
2823:                    String sPropName) {
2824:                PropertyInstanceStore propStoreResult = null;
2825:
2826:                Iterator iter = m_propStores.keySet().iterator();
2827:
2828:                while (iter.hasNext() == true && propStoreResult == null) {
2829:                    PropertyInstanceStore propStore = (PropertyInstanceStore) m_propStores
2830:                            .get(iter.next());
2831:
2832:                    if (propStore.contains(sPropName) == true) {
2833:                        propStoreResult = propStore;
2834:                    }
2835:                }
2836:
2837:                return propStoreResult;
2838:            }
2839:
2840:            /**
2841:             * Sets the profiled object for this profile.
2842:             *
2843:             * @param obj the profiled object
2844:             */
2845:            public void setProfiledObject(AbstractProfiledObject obj) {
2846:                m_profObj = obj;
2847:            }
2848:
2849:            /* (non-Javadoc)
2850:             * @see java.lang.Object#equals(java.lang.Object)
2851:             */
2852:            public boolean equals(Object obj) {
2853:                boolean bReturn = false;
2854:
2855:                if (obj instanceof  Profile) {
2856:
2857:                    if (this  == obj) {
2858:                        bReturn = true;
2859:                    } else if (obj.getClass().getName().equals(
2860:                            getClass().getName()) == true) {
2861:
2862:                        try {
2863:                            populateFromDatabase();
2864:                        } catch (PopulateException e) {
2865:                            m_logger.log(Level.WARNING,
2866:                                    e.getLocalizedMessage(), e);
2867:                        }
2868:
2869:                        Profile objCompare = (Profile) obj;
2870:
2871:                        try {
2872:                            if ((this .getId() != 0)
2873:                                    && (objCompare.getId() != 0)) {
2874:                                if (m_nId == objCompare.getId()) {
2875:                                    bReturn = true;
2876:                                }
2877:                            }
2878:
2879:                            if (bReturn == true
2880:                                    && m_sName.equals(objCompare.getName())) {
2881:                                bReturn = true;
2882:                            }
2883:
2884:                            if (bReturn == true) {
2885:                                bReturn = match(objCompare);
2886:                            }
2887:
2888:                        } catch (Exception e) {
2889:                            throw new RuntimeException(e.getMessage());
2890:                        }
2891:                    }
2892:
2893:                }
2894:
2895:                return bReturn;
2896:            }
2897:
2898:            /* (non-Javadoc)
2899:             * @see org.openharmonise.rm.resources.AbstractObject#isKeySupported()
2900:             */
2901:            protected boolean isKeySupported() {
2902:                return false;
2903:            }
2904:
2905:            /**
2906:             * Returns <code>true</code> if this profile conforms to the restrictions 
2907:             * determined by the domains on the available properties.
2908:             * 
2909:             * @return  <code>true</code> if this profile conforms to the restrictions 
2910:             * determined by the domains on the available properties.
2911:             * 
2912:             * @throws DataAccessException if any errors occur getting the available
2913:             * properties for this <code>Profile</code>.
2914:             */
2915:            public boolean isValid(AbstractProfiledObject profObj)
2916:                    throws DataAccessException {
2917:                boolean bIsValid = true;
2918:
2919:                List props = Domain.getAvailableProperties(m_dsi, profObj);
2920:
2921:                Iterator iter = props.iterator();
2922:
2923:                while (iter.hasNext() && bIsValid == true) {
2924:                    Property prop = (Property) iter.next();
2925:                    Domain domain = prop.getDomain(profObj);
2926:
2927:                    try {
2928:                        if (hasProperty(prop) == true) {
2929:                            AbstractPropertyInstance propInst = getPropertyInstance(prop);
2930:
2931:                            int nVals = propInst.getValues().size();
2932:
2933:                            if (domain.getMinOccurs() > nVals) {
2934:                                if (m_logger.isLoggable(Level.INFO)) {
2935:                                    m_logger.logp(Level.INFO, this .getClass()
2936:                                            .getName(), "isValid",
2937:                                            "MinOccurs is greater than number of vals for prop "
2938:                                                    + prop.getName()
2939:                                                    + " on object "
2940:                                                    + m_profObj.getClass()
2941:                                                            .getName()
2942:                                                    + " key "
2943:                                                    + m_profObj.getKey());
2944:                                }
2945:                                bIsValid = false;
2946:                            }
2947:
2948:                            if (domain.getMaxOccurs() > 0
2949:                                    && domain.getMaxOccurs() < nVals) {
2950:                                if (m_logger.isLoggable(Level.INFO)) {
2951:                                    m_logger.logp(Level.INFO, this .getClass()
2952:                                            .getName(), "isValid",
2953:                                            "MaxOccurs is less than number of vals for prop "
2954:                                                    + prop.getName()
2955:                                                    + " on object "
2956:                                                    + m_profObj.getClass()
2957:                                                            .getName()
2958:                                                    + " key "
2959:                                                    + m_profObj.getKey());
2960:                                }
2961:                                bIsValid = false;
2962:                            }
2963:                        } else {
2964:                            if (domain.getMinOccurs() > 0) {
2965:                                if (m_logger.isLoggable(Level.INFO)) {
2966:                                    m_logger.logp(Level.INFO, this .getClass()
2967:                                            .getName(), "isValid",
2968:                                            "Mandatory prop inst does not exist for prop "
2969:                                                    + prop.getName()
2970:                                                    + " on object "
2971:                                                    + m_profObj.getClass()
2972:                                                            .getName()
2973:                                                    + " key "
2974:                                                    + m_profObj.getKey());
2975:                                }
2976:                                bIsValid = false;
2977:                            }
2978:                        }
2979:                    } catch (InvalidPropertyInstanceException e) {
2980:                        throw new DataAccessException(e.getLocalizedMessage(),
2981:                                e);
2982:                    }
2983:                }
2984:
2985:                return bIsValid;
2986:            }
2987:
2988:            /**
2989:             * Removes the specified property instance from this <code>Profile</code>.
2990:             * 
2991:             * @param propInst the property instance to remove
2992:             * @throws InvalidPropertyInstanceException if the specified property instance
2993:             * is invalid for this <code>Profile</code>
2994:             * @throws DataAccessException if there is an error getting the 
2995:             * <code>Property</code> associated to the property instance
2996:             */
2997:            private void removePropertyInstance(
2998:                    AbstractPropertyInstance propInst)
2999:                    throws InvalidPropertyInstanceException,
3000:                    DataAccessException {
3001:                PropertyInstanceStore propStore = getPropertyInstanceStore(propInst
3002:                        .getProperty());
3003:
3004:                propStore.removePropertyInstance(propInst);
3005:            }
3006:
3007:            /* (non-Javadoc)
3008:             * @see org.openharmonise.rm.resources.AbstractObject#isHistorical()
3009:             */
3010:            public boolean isHistorical() {
3011:
3012:                boolean bIsHist = super .isHistorical();
3013:
3014:                //check that profile's in line with prof obj
3015:                if (bIsHist == false && m_profObj != null
3016:                        && m_profObj.isHistorical() == true) {
3017:                    bIsHist = true;
3018:                    setHistorical(bIsHist);
3019:                }
3020:
3021:                return bIsHist;
3022:            }
3023:
3024:            /* (non-Javadoc)
3025:             * @see org.openharmonise.rm.resources.AbstractObject#markAsNew()
3026:             */
3027:            public void markAsNew() throws PopulateException {
3028:                m_bNew = true;
3029:                super .markAsNew();
3030:
3031:                markProfilePropertyInstanceValuesAsNew();
3032:            }
3033:
3034:            /**
3035:             * Mark <code>ProfileValue</code> as new
3036:             * 
3037:             * @throws PopulateException
3038:             */
3039:            private void markProfilePropertyInstanceValuesAsNew()
3040:                    throws PopulateException {
3041:                PropertyInstanceStore propStore = (PropertyInstanceStore) m_propStores
3042:                        .get(Profile.class.getName());
3043:
3044:                if (propStore != null) {
3045:                    Collection col = propStore.getValues();
3046:
3047:                    Iterator iter = col.iterator();
3048:
3049:                    while (iter.hasNext()) {
3050:                        ProfilePropertyInstance propInst = (ProfilePropertyInstance) iter
3051:                                .next();
3052:
3053:                        propInst.markValuesAsNew();
3054:                    }
3055:                }
3056:            }
3057:
3058:            /**
3059:             * Returns the base class for the given class which is a concrete
3060:             * implementation of <code>AbstractChildObject</code>.
3061:             * 
3062:             * @param clss <code>Class</code> from which to find the base 
3063:             * <code>AbstractChildObject</code> implementation
3064:             * @return the base class for the given class which is a concrete
3065:             * implementation of <code>AbstractChildObject</code>
3066:             */
3067:            private Class getBaseChildObjectClass(Class clss) {
3068:                Class returnClass = null;
3069:                Class super Class = clss.getSuperclass();
3070:
3071:                if (super Class.equals(AbstractChildObject.class)) {
3072:                    returnClass = clss;
3073:                } else {
3074:                    returnClass = getBaseChildObjectClass(super Class);
3075:                }
3076:
3077:                return returnClass;
3078:            }
3079:
3080:            /**
3081:             * Deletes the property instance held by this <code>Profile</code>
3082:             * associated with the specified <code>Property</code>.
3083:             * 
3084:             * @param prop the <code>Property</code>
3085:             * @throws ProfileException
3086:             * @throws InvalidPropertyInstanceException
3087:             * @throws DataAccessException
3088:             */
3089:            private void deletePropertyInstance(Property prop)
3090:                    throws ProfileException, InvalidPropertyInstanceException,
3091:                    DataAccessException {
3092:
3093:                AbstractPropertyInstance propInst = getPropertyInstance(prop);
3094:
3095:                if (propInst instanceof  ProfilePropertyInstance) {
3096:                    ProfilePropertyInstance profPropInst = (ProfilePropertyInstance) propInst;
3097:
3098:                    profPropInst.delete();
3099:                } else {
3100:                    DeleteStatement delete = new DeleteStatement();
3101:
3102:                    String sDataTable = propInst.getDBTableName();
3103:
3104:                    try {
3105:                        ColumnRef profId_colref = getProfileDataColumn(
3106:                                sDataTable,
3107:                                GeneralPropertyInstance.CLMN_PROFILE_ID);
3108:
3109:                        delete.addWhereCondition(profId_colref, "=", m_nId);
3110:
3111:                        ColumnRef dataPropIdCol = getProfileDataColumn(
3112:                                sDataTable,
3113:                                AbstractPropertyInstance.CLMN_PROPERTY_ID);
3114:
3115:                        delete.addWhereCondition(dataPropIdCol, "=", prop
3116:                                .getId());
3117:
3118:                        m_dsi.execute(delete);
3119:                    } catch (DataStoreException e) {
3120:                        throw new ProfileException(
3121:                                "Error occured deleting property instances", e);
3122:                    }
3123:
3124:                }
3125:
3126:            }
3127:
3128:            private void deletePropertyInstanceData(
3129:                    AbstractPropertyInstance propInst) throws ProfileException,
3130:                    InvalidPropertyInstanceException, DataAccessException {
3131:
3132:                if (propInst instanceof  ProfilePropertyInstance) {
3133:                    ProfilePropertyInstance profPropInst = (ProfilePropertyInstance) propInst;
3134:
3135:                    profPropInst.delete();
3136:                } else {
3137:                    DeleteStatement delete = new DeleteStatement();
3138:
3139:                    String sDataTable = propInst.getDBTableName();
3140:
3141:                    try {
3142:                        ColumnRef profId_colref = getProfileDataColumn(
3143:                                sDataTable,
3144:                                GeneralPropertyInstance.CLMN_PROFILE_ID);
3145:
3146:                        delete.addWhereCondition(profId_colref, "=", m_nId);
3147:
3148:                        ColumnRef colDataId = getProfileDataColumn(sDataTable,
3149:                                AbstractPropertyInstance.CLMN_ID);
3150:
3151:                        delete.addWhereCondition(colDataId, "=", propInst
3152:                                .getId());
3153:
3154:                        m_dsi.execute(delete);
3155:                    } catch (DataStoreException e) {
3156:                        throw new ProfileException(
3157:                                "Error occured deleting property instances", e);
3158:                    }
3159:
3160:                }
3161:
3162:            }
3163:
3164:            /**
3165:             * A class to group concrete implementations of 
3166:             * <code>AbstractPropertyInstance</code> by type.
3167:             * 
3168:             * @author Michael Bell
3169:             * @version $Revision: 1.8.2.1 $
3170:             *
3171:             */
3172:            private class PropertyInstanceStore implements  Cloneable {
3173:                /**
3174:                 * <code>boolean</code> flag to indicate whether this object has been 
3175:                 * changed since it was populated
3176:                 */
3177:                private boolean m_bIsChanged = false;
3178:                /**
3179:                 * <code>boolean</code> flag to indicate whether this object has been
3180:                 * populated
3181:                 */
3182:                private boolean m_bIsPopulated = false;
3183:                /**
3184:                 * <code>Map</code> of <code>Property</code> names to 
3185:                 * <code>AbstractPropertyInsatance</code>s
3186:                 */
3187:                private Map m_propInsts = new Hashtable();
3188:                /**
3189:                 * List of props which have been removed and need to be deleted on update
3190:                 */
3191:                private List m_deadProps = new ArrayList();
3192:                /**
3193:                 * The label assocaited to this <code>PropertyInstanceStore</code>
3194:                 */
3195:                private String m_sLabel = null;
3196:                /**
3197:                 * The class name associated with this <code>PropertyInstanceStore</code>
3198:                 */
3199:                private String m_sClassname = null;
3200:
3201:                /**
3202:                 * Constructs a <code>PropertyInstanceStore</code> with the specified label
3203:                 *
3204:                 */
3205:                PropertyInstanceStore(String sLabel) {
3206:                    m_sLabel = sLabel;
3207:                }
3208:
3209:                /**
3210:                 * Constructs a <code>PropertyInstanceStore</code> with the specified label
3211:                 * and a assocated class name
3212:                 *
3213:                 */
3214:                PropertyInstanceStore(String sLabel, String sClassname) {
3215:                    m_sLabel = sLabel;
3216:                    m_sClassname = sClassname;
3217:                }
3218:
3219:                /**
3220:                 * Constructs a new property instance store which is a copy of the 
3221:                 * passed in property instance store
3222:                 * 
3223:                 * @param other property instance store to replicate
3224:                 */
3225:                PropertyInstanceStore(PropertyInstanceStore other) {
3226:                    m_sLabel = other.m_sLabel;
3227:                    m_sClassname = other.m_sClassname;
3228:                    m_bIsChanged = other.m_bIsChanged;
3229:                    m_bIsPopulated = other.m_bIsPopulated;
3230:
3231:                    Iterator iter = other.m_propInsts.keySet().iterator();
3232:
3233:                    while (iter.hasNext()) {
3234:                        String sKey = (String) iter.next();
3235:                        AbstractPropertyInstance propInst = (AbstractPropertyInstance) other.m_propInsts
3236:                                .get(sKey);
3237:
3238:                        m_propInsts.put(sKey, propInst.clone());
3239:                    }
3240:                }
3241:
3242:                /**
3243:                 * Returns the label associated with this store
3244:                 * 
3245:                 * @return the label associated with this store
3246:                 */
3247:                String getLabel() {
3248:                    return m_sLabel;
3249:                }
3250:
3251:                /**
3252:                 * Returns the associated class name with this store
3253:                 * 
3254:                 * @return the associated class name with this store
3255:                 */
3256:                String getAssociatedClassname() {
3257:                    return m_sClassname;
3258:                }
3259:
3260:                /**
3261:                 * Returns <code>true</code> if any of the property instances in the 
3262:                 * store have changed since being populated from the database
3263:                 * 
3264:                 * @return <code>true</code> if any of the property instances in the 
3265:                 * store have changed
3266:                 */
3267:                boolean isChanged() {
3268:
3269:                    if (m_bIsChanged == false) {
3270:                        Iterator iter = m_propInsts.values().iterator();
3271:
3272:                        while (iter.hasNext() && m_bIsChanged == false) {
3273:                            AbstractPropertyInstance next = (AbstractPropertyInstance) iter
3274:                                    .next();
3275:
3276:                            if (next.isChanged()) {
3277:                                m_bIsChanged = true;
3278:                            }
3279:                        }
3280:                    }
3281:                    return m_bIsChanged;
3282:                }
3283:
3284:                /**
3285:                 * Marks this store as having been changed since being populated from
3286:                 * the database
3287:                 * 
3288:                 * @param bIsChanged <code>true</code> to indicate that this store has 
3289:                 * been changed, otherwise <code>false</code>
3290:                 */
3291:                void setIsChanged(boolean bIsChanged) {
3292:                    m_bIsChanged = bIsChanged;
3293:                }
3294:
3295:                /**
3296:                 * Returns <code>true</code> if this store has been populated
3297:                 * 
3298:                 * @return <code>true</code> if this store has been populated
3299:                 */
3300:                boolean isPopulated() {
3301:                    return m_bIsPopulated;
3302:                }
3303:
3304:                /**
3305:                 * Marks this store as having been populated
3306:                 * 
3307:                 * @param bIsPopulated <code>true</code> to indicate that this 
3308:                 * store has been populated
3309:                 */
3310:                void setIsPopulated(boolean bIsPopulated) {
3311:                    m_bIsPopulated = bIsPopulated;
3312:                }
3313:
3314:                /**
3315:                 * Adds the specified property instance to this store
3316:                 * 
3317:                 * @param propInst the property instance to add
3318:                 * @throws DataAccessException if there is an error getting the name
3319:                 * of the associated <code>Property</code>
3320:                 */
3321:                void addPropertyInstance(AbstractPropertyInstance propInst)
3322:                        throws DataAccessException {
3323:                    if (m_bIsPopulated == true
3324:                            && m_propInsts.containsValue(propInst) == false) {
3325:                        m_bIsChanged = true;
3326:                    }
3327:
3328:                    m_propInsts.put(propInst.getName(), propInst);
3329:                }
3330:
3331:                /**
3332:                 * Removes the specified property instance from the store
3333:                 * 
3334:                 * @param prop the <code>Property</code> whose instances are to be
3335:                 * removed from this store
3336:                 * @throws DataAccessException if an error occurs getting the name of the
3337:                 * given <code>Property</code>
3338:                 */
3339:                void removePropertyInstance(Property prop)
3340:                        throws DataAccessException {
3341:                    String sPropName = prop.getName();
3342:                    if (contains(prop) == true) {
3343:                        m_deadProps.add(m_propInsts.get(sPropName));
3344:                        m_propInsts.remove(sPropName);
3345:                        m_bIsChanged = true;
3346:                    }
3347:                }
3348:
3349:                /**
3350:                 * Returns <code>true</code> if this store contains an 
3351:                 * instance of the given <code>Property</code>.
3352:                 * 
3353:                 * @param prop the <code>Property</code>
3354:                 * @return <code>true</code> if this store contains an 
3355:                 * instance of the given <code>Property</code>
3356:                 * @throws DataAccessException if an error occurs getting the name of the
3357:                 * given <code>Property</code>
3358:                 */
3359:                boolean contains(Property prop) throws DataAccessException {
3360:                    return contains(prop.getName());
3361:                }
3362:
3363:                /**
3364:                 * Returns <code>true</code> if this store contains the specified 
3365:                 * <code>AbstractPropertyInstance</code>.
3366:                 * 
3367:                 * @param propInst the prperty instance whose presence is to be tested
3368:                 * @return <code>true</code> if this store contains the specified 
3369:                 * <code>AbstractPropertyInstance</code>
3370:                 */
3371:                boolean contains(AbstractPropertyInstance propInst) {
3372:                    return m_propInsts.containsValue(propInst);
3373:                }
3374:
3375:                /**
3376:                 * Returns <code>true</code> if this store contains an instance
3377:                 * of the <code>Property</code> of the specified name.
3378:                 * 
3379:                 * @param sPropName the <code>Property</code> name
3380:                 * @return <code>true</code> if this store contains an instance
3381:                 * of the <code>Property</code> of the specified name
3382:                 */
3383:                public boolean contains(String sPropName) {
3384:                    return m_propInsts.containsKey(sPropName);
3385:                }
3386:
3387:                /**
3388:                 * Returns the <code>AbstractPropertyInstance</code>s contained in this store.
3389:                 * 
3390:                 * @return the <code>AbstractPropertyInstance</code>s contained in this store
3391:                 */
3392:                Collection getValues() {
3393:                    return m_propInsts.values();
3394:                }
3395:
3396:                /**
3397:                 * Returns the <code>AbstractPropertyInstance</code> from the store that
3398:                 * matches the given <code>Property</code>.
3399:                 * 
3400:                 * @param prop the <code>Property</code> of the instance to be returned
3401:                 * @return the <code>AbstractPropertyInstance</code> from the store that
3402:                 * matches the given <code>Property</code>
3403:                 * @throws DataAccessException if there is an error getting the name of
3404:                 * the <code>Property</code>
3405:                 */
3406:                AbstractPropertyInstance getPropertyInstance(Property prop)
3407:                        throws DataAccessException {
3408:                    return getPropertyInstance(prop.getName());
3409:                }
3410:
3411:                /**
3412:                 * Returns the <code>AbstractPropertyInstance</code> from the store that
3413:                 * matches the specified <code>Property</code> name.
3414:                 * 
3415:                 * @param sName the name of the <code>Property</code> to return an
3416:                 * instance of
3417:                 * @return the <code>AbstractPropertyInstance</code> from the store that
3418:                 * matches the specified <code>Property</code> name
3419:                 */
3420:                AbstractPropertyInstance getPropertyInstance(String sName) {
3421:                    return (AbstractPropertyInstance) m_propInsts.get(sName);
3422:                }
3423:
3424:                /* (non-Javadoc)
3425:                 * @see java.lang.Object#clone()
3426:                 */
3427:                protected Object clone() throws CloneNotSupportedException {
3428:                    throw new CloneNotSupportedException(
3429:                            "Bad - causes all sorts of problems to clone a nested class");
3430:                }
3431:
3432:                /**
3433:                 * Removes the specified <code>AbstractPropertyInstance</code> from this
3434:                 * store
3435:                 * 
3436:                 * @param propInst the <code>AbstractPropertyInstance</code> to remove
3437:                 * @throws DataAccessException if there is an error getting the name
3438:                 * of the associated <code>Property</code>
3439:                 */
3440:                void removePropertyInstance(AbstractPropertyInstance propInst)
3441:                        throws DataAccessException {
3442:                    if (m_bIsPopulated == true
3443:                            && m_propInsts.containsValue(propInst) == true) {
3444:
3445:                        Object remObj = null;
3446:                        String sPropName = propInst.getName();
3447:
3448:                        if (sPropName != null) {
3449:                            remObj = m_propInsts.remove(sPropName);
3450:                        }
3451:
3452:                        //in case prop insts property no longer exists
3453:                        if (remObj == null
3454:                                && m_propInsts.values().contains(propInst)) {
3455:                            Iterator iter = m_propInsts.keySet().iterator();
3456:                            Object propKey = null;
3457:                            while (iter.hasNext()) {
3458:                                Object key = (Object) iter.next();
3459:
3460:                                if (m_propInsts.get(key).equals(propInst)) {
3461:                                    propKey = key;
3462:                                }
3463:                            }
3464:                            if (propKey != null) {
3465:                                m_propInsts.remove(propKey);
3466:                            }
3467:                        }
3468:                        m_deadProps.add(propInst);
3469:                        m_bIsChanged = true;
3470:                    }
3471:
3472:                }
3473:
3474:                /**
3475:                 * Updates all property instance data in the database for the specified
3476:                 * <code>PropertyInstanceStore</code>
3477:                 * 
3478:                 * @throws PopulateException if there is an error accessing data held in 
3479:                 * the property instances
3480:                 * @throws EditException if there is an error saving the data to the database
3481:                 */
3482:                void update() throws ProfileException, EditException {
3483:                    Iterator iter = getValues().iterator();
3484:
3485:                    while (iter.hasNext()) {
3486:                        AbstractPropertyInstance propInst = (AbstractPropertyInstance) iter
3487:                                .next();
3488:
3489:                        propInst.update(Profile.this );
3490:                    }
3491:
3492:                    for (Iterator propIter = m_deadProps.iterator(); propIter
3493:                            .hasNext();) {
3494:                        AbstractPropertyInstance propInst = (AbstractPropertyInstance) propIter
3495:                                .next();
3496:
3497:                        propInst.update(Profile.this );
3498:                    }
3499:
3500:                    m_deadProps.clear();
3501:
3502:                    setIsChanged(false);
3503:                }
3504:
3505:            }
3506:
3507:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.