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.resources.metadata.properties;
0020:
0021: import java.sql.*;
0022: import java.util.*;
0023: import java.util.logging.*;
0024:
0025: import org.openharmonise.commons.cache.CacheException;
0026: import org.openharmonise.commons.dsi.*;
0027: import org.openharmonise.commons.dsi.dml.*;
0028: import org.openharmonise.rm.*;
0029: import org.openharmonise.rm.dsi.*;
0030: import org.openharmonise.rm.metadata.ChildObjectPropertyInstance;
0031: import org.openharmonise.rm.publishing.*;
0032: import org.openharmonise.rm.resources.*;
0033: import org.openharmonise.rm.resources.lifecycle.*;
0034: import org.openharmonise.rm.resources.metadata.properties.domains.Domain;
0035: import org.openharmonise.rm.resources.metadata.properties.ranges.*;
0036: import org.w3c.dom.*;
0037:
0038: /**
0039: * Class which represents a metadata property in the Harmonise framework, having
0040: * a <code>Range</code> which determines what values an instance of this
0041: * <code>Property</code> may have and a set of <code>Domain</code>s which
0042: * determine what objects may have an instance of this <code>Property</code>.
0043: *
0044: * @author Michael Bell
0045: * @version $Revision: 1.5 $
0046: *
0047: */
0048: public class Property extends AbstractChildObject implements
0049: Publishable, Editable, DataStoreObject, Cloneable {
0050:
0051: // XML tags for Properties
0052: /**
0053: * The property XML element name
0054: */
0055: public static final String TAG_PROPERTY = "Property";
0056:
0057: /**
0058: * The domain list XML element name
0059: */
0060: public static final String TAG_DOMAIN_LIST = "DomainList";
0061:
0062: /**
0063: * The description XML attribute name
0064: */
0065: public static final String ATTRIB_DESCRIPTION = "description";
0066:
0067: /**
0068: * The operator XML attribute name
0069: */
0070: public static final String ATTRIB_OPERATOR = "operator";
0071:
0072: //DB constants
0073: /**
0074: * The property database table name
0075: */
0076: private static final String TBL_PROPERTY = "property";
0077:
0078: /**
0079: * The range object database column name
0080: */
0081: private static final String CLMN_RANGE_OBJECT = "range_object";
0082:
0083: /**
0084: * The range details column name
0085: */
0086: private static final String CLMN_RANGE_DETAILS = "range_details";
0087:
0088: /**
0089: * The constant value for the type field for <code>Property</code>
0090: */
0091: protected static String TYPE_PROPERTY = Property.class.getName();
0092:
0093: //member fields
0094: /**
0095: * The <code>Range</code> for this <code>Property</code>
0096: */
0097: protected Range m_range = null;
0098:
0099: /**
0100: * The <code>List</code> of <code>Domain</code>s for this <code>Property</code>
0101: */
0102: protected List m_domains = null;
0103:
0104: /**
0105: * The <code>List</code> of <code>Domain</code>s that have to be added
0106: * at the next save operation
0107: */
0108: protected List m_add_domains = null;
0109:
0110: /**
0111: * The <code>List</code> of <code>Domain</code>s that have to be removed
0112: * at the next save operation
0113: */
0114: protected List m_remove_domains = null;
0115:
0116: /**
0117: * <code>boolean</code> flag to indicate whether the <code>List</code> of
0118: * <code>Domain</code>s has been populated
0119: */
0120: protected boolean m_bIsDomainPopulated = false;
0121:
0122: /**
0123: * Logger for this class
0124: */
0125: static private Logger m_logger = Logger
0126: .getLogger(AbstractObject.class.getName());
0127:
0128: //initialiser block
0129: {
0130: m_domains = new Vector();
0131: m_remove_domains = new Vector();
0132: m_add_domains = new Vector();
0133: }
0134:
0135: //static initialiser block
0136: static {
0137: DatabaseInfo.getInstance().registerTableName(
0138: Property.class.getName(), TBL_PROPERTY);
0139: }
0140:
0141: /**
0142: * Constructs a new <code>Property</code>
0143: *
0144: */
0145: public Property() {
0146: super ();
0147: }
0148:
0149: /**
0150: * Constructs a <code>Property</code> with an interface to the data store.
0151: *
0152: * @param dbintrf the data store interface
0153: */
0154: public Property(AbstractDataStoreInterface dbintrf) {
0155: super (dbintrf);
0156:
0157: }
0158:
0159: /**
0160: * Constructs a known existing <code>Property</code> with an interface to the
0161: * data store.
0162: *
0163: * @param dbintrf the data store interface
0164: * @param nId the id of the <code>Property</code>
0165: */
0166: public Property(AbstractDataStoreInterface dbintrf, int nId) {
0167: super (dbintrf, nId);
0168:
0169: }
0170:
0171: /**
0172: * Constructs <code>Property</code> with the specified id and unique key
0173: * which may be historical.
0174: *
0175: * @param dbintrf the data store interface
0176: * @param nId the <code>Property</code> id
0177: * @param nKey the unique key of the <code>Property</code>
0178: * @param bIsHist <code>true</code> if the <code>Property</code> is to be
0179: * a historical version
0180: */
0181: public Property(AbstractDataStoreInterface dbintrf, int nId,
0182: int nKey, boolean bIsHist) {
0183: super (dbintrf, nId, nKey, bIsHist);
0184: }
0185:
0186: /* (non-Javadoc)
0187: * @see java.lang.Object#clone()
0188: */
0189: public Object clone() {
0190: Property other = null;
0191:
0192: try {
0193: fullPopulate();
0194:
0195: other = (Property) super .clone();
0196:
0197: if (m_range != null) {
0198: other.setRange((Range) m_range.clone());
0199: }
0200:
0201: if (m_domains != null) {
0202: Iterator iter = m_domains.iterator();
0203:
0204: other.m_domains = new Vector();
0205:
0206: while (iter.hasNext()) {
0207: Domain domain = (Domain) iter.next();
0208:
0209: other.m_domains.add(domain.clone());
0210: }
0211: }
0212:
0213: } catch (PopulateException e) {
0214: throw new IllegalStateException("Clone failed:"
0215: + e.getLocalizedMessage());
0216: } catch (CloneNotSupportedException e) {
0217: throw new IllegalStateException("Clone failed:"
0218: + e.getLocalizedMessage());
0219: }
0220:
0221: return other;
0222:
0223: }
0224:
0225: /**
0226: * Returns the <code>Range</code> of this <code>Property</code>.
0227: *
0228: * @return the <code>Range</code> of this <code>Property</code>.
0229: */
0230: public Range getRange() throws DataAccessException {
0231: if (isPopulated() == false) {
0232: try {
0233: populateFromDatabase();
0234: } catch (PopulateException e) {
0235: throw new DataAccessException(
0236: "Error occured populating object", e);
0237: }
0238: }
0239:
0240: return m_range;
0241: }
0242:
0243: /**
0244: * Sets the <code>Range</code> for this <code>Property</code>.
0245: *
0246: * @param range the <code>Range</code> for this <code>Property</code>
0247: * @throws PopulateException if an error occurs populating this <code>Property</code>
0248: */
0249: public void setRange(Range range) throws PopulateException {
0250: if (isPopulated() == false) {
0251: populateFromDatabase();
0252: }
0253:
0254: if ((m_range == null && range != null)
0255: || m_range.equals(range) == false) {
0256: m_range = range;
0257: setIsChanged(true);
0258: }
0259: }
0260:
0261: /**
0262: * Returns the list of domain restrictions on this <code>Property</code>.
0263: *
0264: * @return the list of domain restrictions on this <code>Property</code>
0265: * @throws DataAccessException if there is an error populating the domains
0266: * from the database
0267: */
0268: public List getDomains() throws DataAccessException {
0269: if (m_bIsDomainPopulated == false) {
0270: try {
0271: populateDomainFromDatabase();
0272: } catch (PopulateException e) {
0273: throw new DataAccessException(
0274: "Error occured populating domains", e);
0275: }
0276: }
0277:
0278: return m_domains;
0279: }
0280:
0281: /**
0282: * Adds the given <code>Domain</code> to this <code>Property</code>.
0283: *
0284: * @param domain the <code>Domain</code> to add
0285: * @throws PopulateException if there is an error populating the domains
0286: * from the database
0287: */
0288: public void addDomain(Domain domain) throws PopulateException {
0289: if (m_bIsDomainPopulated == false) {
0290: populateDomainFromDatabase();
0291: }
0292:
0293: if (m_domains.contains(domain) == false) {
0294:
0295: if (m_logger.isLoggable(Level.FINE)) {
0296: try {
0297: StringBuffer sbuf = new StringBuffer();
0298:
0299: sbuf.append("Adding domain {class - ").append(
0300: domain.getDomainClass()).append(
0301: ", path restrictions - ").append(
0302: domain.getDetails()).append(
0303: "} to property ").append(getName());
0304:
0305: m_logger.logp(Level.FINE,
0306: this .getClass().getName(), "addDomain",
0307: sbuf.toString());
0308: } catch (DataAccessException e) {
0309: m_logger.log(Level.WARNING,
0310: e.getLocalizedMessage(), e);
0311: }
0312: }
0313:
0314: if (m_range != null && m_range instanceof BooleanRange) {
0315: domain.setMaxOccurs(1);
0316: }
0317:
0318: m_add_domains.add(domain);
0319: try {
0320: if (isChanged() == false) {
0321: setIsChanged(true);
0322: }
0323: } catch (DataAccessException e) {
0324: throw new PopulateException(
0325: "Error occurred populating property: ", e);
0326: }
0327: }
0328: }
0329:
0330: /**
0331: * Removes the given <code>Domain</code> from this <code>Property</code>.
0332: *
0333: * @param domain the <code>Domain</code> to remove
0334: * @throws PopulateException if an error occurs populating the list
0335: * of <code>Domain</code>s
0336: */
0337: public void removeDomain(Domain domain) throws PopulateException {
0338: if (m_bIsDomainPopulated == false) {
0339: populateDomainFromDatabase();
0340: }
0341:
0342: if (m_domains.contains(domain) == true) {
0343: m_remove_domains.add(domain);
0344: try {
0345: if (isChanged() == false) {
0346: setIsChanged(true);
0347: }
0348: } catch (DataAccessException e) {
0349: throw new PopulateException(
0350: "Error occurred populating property", e);
0351: }
0352: }
0353: }
0354:
0355: /**
0356: * Sets the complete list of <code>Domain</code>s for this <code>Property</code>,
0357: * overwriting the current list
0358: *
0359: * @param domains the list of new <code>Domain</code>s
0360: * @throws PopulateException if there is an error populating the list of
0361: * <code>Domain</code>s
0362: */
0363: public void setDomains(List domains) throws PopulateException {
0364: if (m_bIsDomainPopulated == false) {
0365: populateDomainFromDatabase();
0366: }
0367:
0368: if (m_domains.equals(domains) == false) {
0369: setIsChanged(true);
0370: m_add_domains = new Vector(domains);
0371: m_remove_domains.addAll(m_domains);
0372: }
0373:
0374: }
0375:
0376: /**
0377: * Returns <code>true</code> if the specified
0378: * <code>AbstarctProfiledObject</code> can have an instance of this
0379: * <code>Property</code> in its <code>Profile</code>.
0380: *
0381: * @param obj the profiled object
0382: * @return <code>true</code> if this <code>Property</code> can be applied
0383: * to the specified profiled object
0384: * @throws DataAccessException if an error occurs populating the <code>Domain</code>s
0385: * of this <code>Property</code>
0386: */
0387: public boolean isValidProfiledObject(AbstractProfiledObject obj)
0388: throws DataAccessException {
0389: boolean bIsValid = false;
0390:
0391: Iterator iter = getDomains().iterator();
0392:
0393: boolean bFound = false;
0394:
0395: while (iter.hasNext() && bFound == false) {
0396: Domain domain = (Domain) iter.next();
0397:
0398: if (domain.getDomainClass()
0399: .equals(obj.getClass().getName()) == true) {
0400: bIsValid = domain.isValid(obj);
0401: bFound = true;
0402: }
0403: }
0404:
0405: return bIsValid;
0406: }
0407:
0408: /* (non-Javadoc)
0409: * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceJoinConditions(java.lang.String, boolean)
0410: */
0411: public JoinConditions getInstanceJoinConditions(String sObjectTag,
0412: boolean bIsOuter) throws DataStoreException {
0413: return null;
0414: }
0415:
0416: /* (non-Javadoc)
0417: * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceColumnRef(java.lang.String, boolean)
0418: */
0419: public ColumnRef getInstanceColumnRef(String sColumn,
0420: boolean bIsHist) throws DataStoreException {
0421: ColumnRef returnColRef = null;
0422:
0423: String sTable = getDBTableName();
0424:
0425: if (bIsHist == true) {
0426: sTable = getHistoricalDBTableName();
0427: }
0428:
0429: if (sColumn.equals(CLMN_RANGE_OBJECT) == true) {
0430: returnColRef = new ColumnRef(sTable, CLMN_RANGE_OBJECT,
0431: ColumnRef.TEXT);
0432: } else if (sColumn.equals(CLMN_RANGE_DETAILS) == true) {
0433: returnColRef = new ColumnRef(sTable, CLMN_RANGE_DETAILS,
0434: ColumnRef.TEXT);
0435: } else {
0436: returnColRef = super .getInstanceColumnRef(sColumn, bIsHist);
0437: }
0438:
0439: if (returnColRef != null) {
0440: return returnColRef;
0441: } else {
0442: throw new InvalidColumnReferenceException(
0443: "No column of the name [" + sColumn
0444: + "] in Property");
0445: }
0446: }
0447:
0448: /* (non-Javadoc)
0449: * @see org.openharmonise.rm.resources.AbstractObject#markAsNew()
0450: */
0451: public void markAsNew() throws PopulateException {
0452: if (m_domains != null) {
0453: Iterator iter = m_domains.iterator();
0454:
0455: while (iter.hasNext()) {
0456: Domain domain = (Domain) iter.next();
0457: domain.markAsNew();
0458: }
0459: }
0460: super .markAsNew();
0461: }
0462:
0463: /* (non-Javadoc)
0464: * @see org.openharmonise.rm.resources.AbstractEditableObject#delete(boolean)
0465: */
0466: protected void delete(boolean bDeleteHist)
0467: throws DataAccessException, EditException,
0468: PopulateException, DataStoreException {
0469:
0470: List domains = getDomains();
0471:
0472: Iterator iter = domains.iterator();
0473:
0474: while (iter.hasNext()) {
0475: Domain domain = (Domain) iter.next();
0476: domain.delete();
0477: }
0478:
0479: super .delete(bDeleteHist);
0480: }
0481:
0482: /* (non-Javadoc)
0483: * @see org.openharmonise.rm.publishing.Publishable#populate(org.w3c.dom.Element, org.openharmonise.rm.publishing.State)
0484: */
0485: public void populate(Element xmlElement, State state)
0486: throws PopulateException {
0487:
0488: String sTemp = "";
0489: String sTagName = xmlElement.getTagName();
0490:
0491: if (sTagName.equals(TAG_PROPERTY)) {
0492: sTemp = xmlElement.getAttribute(ATTRIB_ID);
0493:
0494: if (!sTemp.equals("")) {
0495: m_nId = Integer.parseInt(sTemp);
0496: }
0497:
0498: sTemp = xmlElement.getAttribute(ATTRIB_NAME);
0499:
0500: if (sTemp.equals("") == false) {
0501: try {
0502: setName(sTemp);
0503: } catch (InvalidNameException e) {
0504: throw new PopulateException(e);
0505: }
0506: }
0507:
0508: sTemp = xmlElement.getAttribute(ATTRIB_DESCRIPTION);
0509:
0510: if (sTemp.equals("") == false) {
0511: setSummary(xmlElement.getAttribute(ATTRIB_DESCRIPTION));
0512: }
0513:
0514: NodeList nodes = xmlElement.getChildNodes();
0515:
0516: for (int i = 0; i < nodes.getLength(); i++) {
0517: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
0518: continue;
0519: }
0520:
0521: Element el = (Element) nodes.item(i);
0522: populate(el, state);
0523: }
0524: } else if (RangeFactory.isRangeTagName(sTagName) == true) {
0525: try {
0526: Range range = RangeFactory.getInstance().getRange(
0527: xmlElement);
0528: ((Publishable) range).populate(xmlElement, state);
0529: setRange(range);
0530: } catch (InvalidRangeObjectException e) {
0531: throw new PopulateException(e);
0532: }
0533: } else if (sTagName.equals(TAG_DOMAIN_LIST)) {
0534: NodeList domEls = xmlElement.getChildNodes();
0535:
0536: for (int i = 0; i < domEls.getLength(); i++) {
0537: if (domEls.item(i).getNodeType() == Node.ELEMENT_NODE) {
0538: Element domEl = (Element) domEls.item(i);
0539:
0540: Domain domain = new Domain(m_dsi);
0541: domain.populate(domEl, state);
0542: m_add_domains.add(domain);
0543: }
0544: }
0545:
0546: } else {
0547: super .populate(xmlElement, state);
0548: }
0549: }
0550:
0551: /* (non-Javadoc)
0552: * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
0553: */
0554: public Element publish(Element topEl, HarmoniseOutput xmlDoc,
0555: State state) throws PublishException {
0556: if (isPopulated() == false) {
0557: try {
0558: populateFromDatabase();
0559: } catch (PopulateException e) {
0560: throw new PublishException(
0561: "Error occured populating object", e);
0562: }
0563: }
0564:
0565: Element docEl = null;
0566: NodeList nodes = null;
0567: Text txt = null;
0568: String sTagName = topEl.getTagName();
0569:
0570: if (sTagName.equals(TAG_PROPERTY)) {
0571: docEl = xmlDoc.createElement(sTagName);
0572:
0573: String sTemp = "";
0574:
0575: try {
0576: sTemp = getName();
0577:
0578: if ((sTemp == null) || sTemp.equalsIgnoreCase("")) {
0579: sTemp = topEl.getAttribute(ATTRIB_NAME);
0580: }
0581:
0582: docEl.setAttribute(ATTRIB_NAME, sTemp);
0583:
0584: sTemp = getSummary();
0585:
0586: if (!sTemp.equalsIgnoreCase("") && (sTemp != null)) {
0587: docEl.setAttribute(ATTRIB_DESCRIPTION, sTemp);
0588: }
0589: } catch (DataAccessException e) {
0590: throw new PublishException(
0591: "Error occured accessing data", e);
0592: }
0593:
0594: sTemp = topEl.getAttribute(ATTRIB_OPERATOR);
0595:
0596: if (sTemp.equalsIgnoreCase("") == false && (sTemp != null)) {
0597: docEl.setAttribute(ATTRIB_OPERATOR, sTemp);
0598: }
0599:
0600: nodes = topEl.getChildNodes();
0601: } else if (sTagName.equals(TAG_DOMAIN_LIST)) {
0602: // deal with domain
0603: docEl = xmlDoc.createElement(sTagName);
0604:
0605: Element domEl = (Element) topEl.getElementsByTagName(
0606: Domain.TAG_DOMAIN).item(0);
0607: if (domEl == null) {
0608: domEl = xmlDoc.createElement(Domain.TAG_DOMAIN);
0609: Element tempEl = xmlDoc
0610: .createElement(Domain.TAG_DOMAIN_DETAILS);
0611: domEl.appendChild(tempEl);
0612: tempEl = xmlDoc.createElement(Domain.TAG_DOMAIN_OBJECT);
0613: domEl.appendChild(tempEl);
0614: }
0615: if (this .m_bIsDomainPopulated == false) {
0616: try {
0617: this .populateDomainFromDatabase();
0618: } catch (PopulateException e) {
0619: throw new PublishException(e);
0620: }
0621: }
0622:
0623: if (m_domains != null) {
0624: for (Iterator iter = m_domains.iterator(); iter
0625: .hasNext();) {
0626: Domain dom = (Domain) iter.next();
0627: docEl
0628: .appendChild(dom.publish(domEl, xmlDoc,
0629: state));
0630: }
0631: }
0632:
0633: } else if (sTagName.equals(AbstractRange.TAG_RANGE)) {
0634: //deal with range
0635: if (m_range != null) {
0636: docEl = ((AbstractRange) m_range).publish(topEl,
0637: xmlDoc, state);
0638: } else {
0639: docEl = xmlDoc.createElement(sTagName);
0640: }
0641:
0642: } else { //add on any other nodes
0643: docEl = super .publish(topEl, xmlDoc, state);
0644: }
0645:
0646: // recurse through the children if there are any
0647: Element formEl;
0648: Element el;
0649:
0650: if (nodes != null) {
0651: for (int i = 0; i < nodes.getLength(); i++) {
0652: if (nodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
0653: continue;
0654: }
0655: formEl = (Element) nodes.item(i);
0656: el = publish(formEl, xmlDoc, state);
0657:
0658: if (el != null) {
0659: docEl.appendChild(el);
0660: }
0661: }
0662: }
0663:
0664: return docEl;
0665: }
0666:
0667: /* (non-Javadoc)
0668: * @see org.openharmonise.rm.dsi.DataStoreObject#getDBTableName()
0669: */
0670: public String getDBTableName() {
0671: return TBL_PROPERTY;
0672: }
0673:
0674: /* (non-Javadoc)
0675: * @see org.openharmonise.rm.publishing.Publishable#getTagName()
0676: */
0677: public String getTagName() {
0678: return TAG_PROPERTY;
0679: }
0680:
0681: /*-----------------------------------------------------------------
0682: protected methods
0683: -----------------------------------------------------------------*/
0684:
0685: /* (non-Javadoc)
0686: * @see org.openharmonise.rm.resources.AbstractObject#fullPopulate()
0687: */
0688: protected void fullPopulate() throws PopulateException {
0689: if (isPopulated() == false) {
0690: populateFromDatabase();
0691: }
0692:
0693: if (m_bIsDomainPopulated == false) {
0694: populateDomainFromDatabase();
0695: }
0696:
0697: super .fullPopulate();
0698: }
0699:
0700: /**
0701: * Populates the list of <code>Domain</code>s from the database for this
0702: * <code>Property</code>.
0703: *
0704: * @throws PopulateException if there is an error populating the data
0705: * from the database
0706: */
0707: protected synchronized void populateDomainFromDatabase()
0708: throws PopulateException {
0709: if (isPopulated() == false) {
0710: populateFromDatabase();
0711: }
0712:
0713: if (m_bIsDomainPopulated == false) {
0714:
0715: if (m_logger.isLoggable(Level.FINE)) {
0716: try {
0717: m_logger.logp(Level.FINE,
0718: this .getClass().getName(),
0719: "populateDomainFromDatabase",
0720: "populating domains for object, key - "
0721: + getKey());
0722: } catch (DataAccessException e) {
0723: m_logger.log(Level.WARNING,
0724: "Problem logging domain population", e);
0725: }
0726: }
0727:
0728: boolean bIsHist = isHistorical();
0729: ResultSet rs = null;
0730:
0731: SelectStatement select = new SelectStatement();
0732:
0733: try {
0734: select.addSelectColumn(getDomainColumnRef(
0735: Domain.CLMN_DOMAIN_OBJECT, bIsHist));
0736: select.addSelectColumn(getDomainColumnRef(
0737: Domain.CLMN_DOMAIN_ID, bIsHist));
0738: select.addSelectColumn(getDomainColumnRef(
0739: Domain.CLMN_MIN_OCCURS, bIsHist));
0740: select.addSelectColumn(getDomainColumnRef(
0741: Domain.CLMN_MAX_OCCURS, bIsHist));
0742: select.addSelectColumn(getDomainColumnRef(
0743: Domain.CLMN_DEPTH, bIsHist));
0744: select.addWhereCondition(getDomainColumnRef(
0745: Domain.CLMN_PROPERTY_KEY, bIsHist), "=",
0746: m_nObjectKey);
0747:
0748: } catch (DataStoreException e) {
0749: throw new PopulateException(
0750: "Error occure building query for domain", e);
0751: }
0752: try {
0753: rs = m_dsi.execute(select);
0754:
0755: while (rs.next()) {
0756: Domain domain = new Domain(m_dsi);
0757:
0758: domain.setDomainClass(rs.getString(1));
0759: domain.setId(rs.getInt(2));
0760: domain.setMinOccurs(rs.getInt(3));
0761: domain.setMaxOccurs(rs.getInt(4));
0762: domain.setDepth(rs.getInt(5));
0763:
0764: m_domains.add(domain);
0765: }
0766:
0767: m_bIsDomainPopulated = true;
0768: } catch (DataStoreException e) {
0769: throw new PopulateException(
0770: "Error occure processing query for domain", e);
0771: } catch (SQLException e) {
0772: throw new PopulateException(
0773: "Error occure processing query for domain", e);
0774: } finally {
0775: if (rs != null) {
0776: try {
0777: rs.close();
0778: } catch (SQLException e) {
0779: throw new PopulateException(
0780: "Error occur closing result set", e);
0781: }
0782: }
0783: }
0784: }
0785: }
0786:
0787: /* (non-Javadoc)
0788: * @see org.openharmonise.rm.resources.AbstractEditableObject#update()
0789: */
0790: protected void update() throws EditException, DataStoreException {
0791:
0792: // remove what's to be removed
0793: if (m_remove_domains.size() > 0) {
0794:
0795: //now save
0796: Iterator iter = m_remove_domains.iterator();
0797: DeleteStatement delete = new DeleteStatement();
0798: boolean bIsHist = isHistorical();
0799:
0800: while (iter.hasNext()) {
0801: Domain domain = (Domain) iter.next();
0802:
0803: domain.delete();
0804:
0805: m_domains.remove(domain);
0806: }
0807:
0808: m_remove_domains.clear();
0809: }
0810:
0811: //add what's to be added
0812: if (m_add_domains.size() > 0) {
0813: //now save
0814: Iterator iter = m_add_domains.iterator();
0815:
0816: while (iter.hasNext()) {
0817: Domain domain = (Domain) iter.next();
0818:
0819: domain.save(this );
0820: m_domains.add(domain);
0821: }
0822: m_add_domains.clear();
0823: }
0824:
0825: //check for current range and domain
0826: for (Iterator iter = m_domains.iterator(); iter.hasNext();) {
0827: Domain domain = (Domain) iter.next();
0828: checkDomainAndRange(domain);
0829: }
0830:
0831: super .update();
0832:
0833: }
0834:
0835: /* (non-Javadoc)
0836: * @see org.openharmonise.rm.resources.AbstractEditableObject#saveNonCoreData()
0837: */
0838: protected void saveNonCoreData() throws EditException {
0839: // nothing to do, no non core data
0840:
0841: }
0842:
0843: /* (non-Javadoc)
0844: * @see org.openharmonise.rm.resources.AbstractChildObject#getParentObjectClassName()
0845: */
0846: public String getParentObjectClassName() {
0847:
0848: return PropertyGroup.class.getName();
0849: }
0850:
0851: /* (non-Javadoc)
0852: * @see org.openharmonise.rm.resources.AbstractObject#addColumnsToPopulateQuery(org.openharmonise.commons.dsi.dml.SelectStatement, boolean)
0853: */
0854: protected void addColumnsToPopulateQuery(SelectStatement select,
0855: boolean bIsHist) throws DataStoreException {
0856:
0857: super .addColumnsToPopulateQuery(select, bIsHist);
0858:
0859: select.addSelectColumn(getInstanceColumnRef(CLMN_RANGE_OBJECT,
0860: bIsHist));
0861: select.addSelectColumn(getInstanceColumnRef(CLMN_RANGE_DETAILS,
0862: bIsHist));
0863: }
0864:
0865: /* (non-Javadoc)
0866: * @see org.openharmonise.rm.resources.AbstractObject#populateFromResultSetRow(java.sql.ResultSet, org.openharmonise.commons.dsi.dml.SelectStatement)
0867: */
0868: protected void populateFromResultSetRow(ResultSet rs,
0869: SelectStatement select) throws PopulateException {
0870:
0871: if (isPopulated() == false) {
0872:
0873: super .populateFromResultSetRow(rs, select);
0874:
0875: List cols = select.getSelectColumns();
0876: ColumnRef colref = null;
0877:
0878: try {
0879: ColumnRefCache cache = ColumnRefCache.getInstance();
0880:
0881: boolean bIsHist = isHistorical();
0882:
0883: colref = cache.getColumnRef(this , CLMN_RANGE_OBJECT,
0884: bIsHist);
0885:
0886: if (select.containsSelectColumn(colref) == true) {
0887: String sRangeObject = rs.getString(select
0888: .getResultSetIndex(colref));
0889:
0890: m_range = RangeFactory.getInstance().getRange(
0891: sRangeObject);
0892:
0893: colref = cache.getColumnRef(this ,
0894: CLMN_RANGE_DETAILS, bIsHist);
0895:
0896: if (select.containsSelectColumn(colref) == true
0897: && m_range != null) {
0898: String sRangeDetails = rs.getString(select
0899: .getResultSetIndex(colref));
0900:
0901: m_range.setDetails(sRangeDetails);
0902: }
0903: }
0904: } catch (SQLException e) {
0905: throw new PopulateException(
0906: "Error occured populating range", e);
0907: } catch (ClassNotFoundException e) {
0908: throw new PopulateException(
0909: "Error occured generating range from factory",
0910: e);
0911: } catch (CacheException e) {
0912: throw new PopulateException("Error occured with cache",
0913: e);
0914: } catch (InvalidRangeObjectException e) {
0915: throw new PopulateException(
0916: "Error occured generating range from factory",
0917: e);
0918: }
0919: }
0920: }
0921:
0922: /* (non-Javadoc)
0923: * @see org.openharmonise.rm.resources.AbstractEditableObject#addDataToSave(org.openharmonise.commons.dsi.dml.InsertStatement)
0924: */
0925: protected void addDataToSave(InsertStatement insert)
0926: throws DataStoreException {
0927: boolean bIsHist = isHistorical();
0928:
0929: super .addDataToSave(insert);
0930:
0931: if (m_range != null) {
0932:
0933: insert.addColumnValue(getInstanceColumnRef(
0934: CLMN_RANGE_OBJECT, bIsHist), m_range.getObject());
0935:
0936: String sRangeDetails = m_range.getDetails();
0937:
0938: if (sRangeDetails != null) {
0939: insert.addColumnValue(getInstanceColumnRef(
0940: CLMN_RANGE_DETAILS, bIsHist), sRangeDetails);
0941:
0942: }
0943:
0944: }
0945: }
0946:
0947: /* (non-Javadoc)
0948: * @see org.openharmonise.rm.resources.AbstractEditableObject#saveCoreData()
0949: */
0950: protected void saveCoreData() throws EditException {
0951:
0952: if (m_bIsDomainPopulated == false) {
0953: try {
0954: populateDomainFromDatabase();
0955: } catch (PopulateException e) {
0956: throw new EditException(e.getLocalizedMessage(), e);
0957: }
0958: }
0959:
0960: //first must work out what domains have to be saved
0961:
0962: m_domains.removeAll(m_remove_domains);
0963:
0964: m_domains.addAll(m_add_domains);
0965:
0966: //now save
0967: Iterator iter = m_domains.iterator();
0968:
0969: while (iter.hasNext()) {
0970: Domain domain = (Domain) iter.next();
0971:
0972: checkDomainAndRange(domain);
0973:
0974: domain.save(this );
0975: }
0976:
0977: m_remove_domains.clear();
0978: m_add_domains.clear();
0979:
0980: super .saveCoreData();
0981: }
0982:
0983: /*-----------------------------------------------------------------
0984: Private methods
0985: -----------------------------------------------------------------*/
0986:
0987: /**
0988: * Returns the appropriate <code>ColumnRef</code> for the specified column
0989: * of the domain database table.
0990: *
0991: * @param sCol the database column name
0992: * @param bIsHist <code>true</code> if the reference to return should be to
0993: * the historical table
0994: * @return the column reference for the specified column name of the
0995: * domain table
0996: */
0997: private ColumnRef getDomainColumnRef(String sCol, boolean bIsHist)
0998: throws DataStoreException {
0999: String sTable = Domain.TBL_NAME;
1000: ColumnRef colref = null;
1001:
1002: if (bIsHist == true) {
1003: sTable = sTable + EXT_HIST;
1004: }
1005:
1006: if (sCol.equals(Domain.CLMN_DOMAIN_OBJECT) == true) {
1007: colref = new ColumnRef(sTable, sCol, ColumnRef.TEXT);
1008: } else if (sCol.equals(Domain.CLMN_PROPERTY_KEY) == true) {
1009: colref = new ColumnRef(sTable, sCol, ColumnRef.NUMBER);
1010: } else if (sCol.equals(Domain.CLMN_MIN_OCCURS) == true) {
1011: colref = new ColumnRef(sTable, sCol, ColumnRef.NUMBER);
1012: } else if (sCol.equals(Domain.CLMN_MAX_OCCURS) == true) {
1013: colref = new ColumnRef(sTable, sCol, ColumnRef.NUMBER);
1014: } else if (sCol.equals(Domain.CLMN_DOMAIN_ID) == true) {
1015: colref = new ColumnRef(sTable, sCol, ColumnRef.NUMBER);
1016: } else if (sCol.equals(Domain.CLMN_DEPTH) == true) {
1017: colref = new ColumnRef(sTable, sCol, ColumnRef.NUMBER);
1018: } else {
1019: throw new InvalidColumnReferenceException();
1020: }
1021:
1022: return colref;
1023: }
1024:
1025: /* (non-Javadoc)
1026: * @see org.openharmonise.rm.resources.AbstractObject#setHistorical(boolean)
1027: */
1028: public void setHistorical(boolean bIsHistorical) {
1029: if (m_bIsDomainPopulated == true) {
1030: Iterator iter = m_domains.iterator();
1031: while (iter.hasNext()) {
1032: Domain domain = (Domain) iter.next();
1033: domain.setHistorical(bIsHistorical);
1034: }
1035: }
1036:
1037: super .setHistorical(bIsHistorical);
1038: }
1039:
1040: /* (non-Javadoc)
1041: * @see org.openharmonise.rm.resources.AbstractObject#isChanged()
1042: */
1043: public boolean isChanged() throws DataAccessException {
1044: boolean bIsChanged = false;
1045:
1046: Iterator domIter = m_domains.iterator();
1047:
1048: while (domIter.hasNext()) {
1049: Domain domain = (Domain) domIter.next();
1050: if (domain.isChanged() == true) {
1051: bIsChanged = true;
1052: setIsChanged(true);
1053: }
1054: }
1055:
1056: if (bIsChanged == false && m_range != null) {
1057: bIsChanged = m_range.isChanged();
1058: }
1059:
1060: if (bIsChanged == false) {
1061: bIsChanged = super .isChanged();
1062: }
1063:
1064: return bIsChanged;
1065: }
1066:
1067: /**
1068: * Returns the <code>Domain</code> of this <code>Property</code> which
1069: * matches the specified <code>AbstractProfiledObject</code>.
1070: *
1071: * @param profObj the profiled object
1072: * @return the <code>Domain</code> which matches the specified
1073: * <code>AbstractProfiledObject</code>
1074: * @throws DataAccessException if an error occurs populating the list
1075: * of <code>Domain</code>s
1076: */
1077: public Domain getDomain(AbstractProfiledObject profObj)
1078: throws DataAccessException {
1079: if (m_bIsDomainPopulated == false) {
1080: try {
1081: populateDomainFromDatabase();
1082: } catch (PopulateException e) {
1083: throw new DataAccessException(e.getLocalizedMessage(),
1084: e);
1085: }
1086: }
1087: Domain result = null;
1088:
1089: Iterator iter = m_domains.iterator();
1090: boolean bFound = false;
1091: while (iter.hasNext()) {
1092: Domain domain = (Domain) iter.next();
1093:
1094: if (domain.isValid(profObj)) {
1095: bFound = true;
1096: result = domain;
1097: }
1098:
1099: }
1100:
1101: return result;
1102: }
1103:
1104: /**
1105: * Checks domain had valid data given the current property range.
1106: *
1107: * @param domain the domain to check
1108: * @throws EditException if an error occurs
1109: */
1110: protected void checkDomainAndRange(Domain domain)
1111: throws EditException {
1112:
1113: if (m_range != null && m_range instanceof BooleanRange) {
1114: domain.setMaxOccurs(1);
1115: } else if (m_range != null
1116: && m_range instanceof AbsoluteChildObjectRange) {
1117: try {
1118: String sDomainClass = domain.getDomainClass();
1119: Class domainClass = Class.forName(sDomainClass);
1120: String sValueClass = ((ChildObjectRange) m_range)
1121: .getChildObjectValueClassName(domainClass);
1122:
1123: String sTableName = ChildObjectPropertyInstance
1124: .getDBTableName(sDomainClass, sValueClass,
1125: isHistorical());
1126:
1127: if (m_dsi.isTableExist(sTableName) == false) {
1128: ChildObjectPropertyInstance.createTable(m_dsi,
1129: sDomainClass, sValueClass, isHistorical());
1130: }
1131:
1132: } catch (ClassNotFoundException e) {
1133: throw new EditException(e);
1134: } catch (DataAccessException e) {
1135: throw new EditException(e);
1136: } catch (DataStoreException e) {
1137: throw new EditException(e);
1138: }
1139:
1140: }
1141: }
1142:
1143: /**
1144: * @param domainObject
1145: * @param domainDetails
1146: * @throws DataAccessException
1147: */
1148: public Domain getDomain(String domainObject, String domainDetails)
1149: throws DataAccessException {
1150: if (m_bIsDomainPopulated == false) {
1151: try {
1152: populateDomainFromDatabase();
1153: } catch (PopulateException e) {
1154: throw new DataAccessException(e.getLocalizedMessage(),
1155: e);
1156: }
1157: }
1158: Domain result = null;
1159:
1160: Iterator iter = m_domains.iterator();
1161: boolean bFound = false;
1162: while (iter.hasNext()) {
1163: Domain domain = (Domain) iter.next();
1164:
1165: if (domainObject.equals(domain.getDomainClass())
1166: && domain.getDetails().contains(domainDetails)) {
1167: bFound = true;
1168: result = domain;
1169: }
1170:
1171: }
1172:
1173: return result;
1174:
1175: }
1176:
1177: /* (non-Javadoc)
1178: * @see org.openharmonise.rm.resources.AbstractObject#setName(java.lang.String)
1179: */
1180: public void setName(String sName) throws InvalidNameException {
1181:
1182: //ensure name is valid
1183: if (isNameUnique(sName) == false) {
1184: throw new InvalidNameException(sName
1185: + " already a property name");
1186: }
1187:
1188: super .setName(sName);
1189: }
1190:
1191: /**
1192: * Returns <code>true</code> if this name is unique.
1193: *
1194: * @param sName the proposed name
1195: * @return <code>true</code> if this name is unique
1196: */
1197: private boolean isNameUnique(String sName) {
1198:
1199: boolean bIsUnique = true;
1200: ResultSet rs = null;
1201:
1202: SelectStatement select = new SelectStatement();
1203:
1204: try {
1205: ColumnRef nameCol = getInstanceColumnRef(TAG_NAME,
1206: isHistorical());
1207:
1208: select.addSelectColumn(nameCol);
1209:
1210: select.addWhereCondition(nameCol, "=", sName);
1211:
1212: if (m_nId > 0) {
1213: select.addWhereCondition(getInstanceColumnRef(
1214: ATTRIB_ID, isHistorical()), "!=", m_nId);
1215:
1216: select.addWhereCondition(getInstanceColumnRef(
1217: TAG_LIVE_VERSION, isHistorical()), "!=", m_nId);
1218: }
1219:
1220: rs = m_dsi.execute(select);
1221:
1222: if (rs.next()) {
1223: bIsUnique = false;
1224: }
1225:
1226: } catch (DataStoreException e) {
1227: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
1228: } catch (SQLException e) {
1229: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
1230: } finally {
1231: if (rs != null) {
1232: try {
1233: rs.close();
1234: } catch (SQLException e) {
1235: m_logger.log(Level.WARNING,
1236: e.getLocalizedMessage(), e);
1237: }
1238: }
1239: }
1240:
1241: return bIsUnique;
1242: }
1243:
1244: }
|