001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.workflow.attribute;
017:
018: import javax.xml.xpath.XPath;
019: import javax.xml.xpath.XPathConstants;
020: import javax.xml.xpath.XPathExpressionException;
021:
022: import org.kuali.core.service.DocumentTypeService;
023: import org.kuali.kfs.KFSPropertyConstants;
024: import org.kuali.kfs.context.SpringContext;
025: import org.kuali.kfs.document.AccountingDocument;
026: import org.kuali.workflow.KualiWorkflowUtils;
027: import org.w3c.dom.Document;
028: import org.w3c.dom.NodeList;
029:
030: import edu.iu.uis.eden.routetemplate.xmlrouting.XPathHelper;
031:
032: /**
033: * This class determines the classes of the accounting lines of a workflow created XML document.
034: */
035: public class AccountingLineClassDeterminer {
036: private AccountingDocument accountingDocument;
037: private String sourceAccountingLineClassName;
038: private boolean sourceNameIsNull = false;
039: private String targetAccountingLineClassName;
040: private boolean targetNameIsNull = false;
041: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
042: .getLogger(AccountingLineClassDeterminer.class);
043:
044: /**
045: * Constructs a AccountingLineClassDeterminer
046: * @param doc the XML document that represents an accounting document
047: */
048: public AccountingLineClassDeterminer(Document doc) {
049: try {
050: XPath xpath = XPathHelper.newXPath(doc);
051:
052: String documentXPath = KualiWorkflowUtils
053: .xstreamSafeXPath(KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX
054: + KFSPropertyConstants.DOCUMENT
055: + "[@class]");
056: NodeList documentNodes = (NodeList) xpath.evaluate(
057: documentXPath, doc, XPathConstants.NODESET);
058: if (documentNodes.getLength() > 0) {
059: String documentClassName = documentNodes.item(0)
060: .getAttributes().getNamedItem("class")
061: .getTextContent();
062: Class documentClass = Class.forName(documentClassName);
063: accountingDocument = getAccountingDocumentFromClass(documentClass);
064: }
065: } catch (XPathExpressionException e) {
066: LOG.error("Could not parse XPath expression: " + e);
067: throw new RuntimeException(e);
068: } catch (ClassNotFoundException e) {
069: LOG.error("Could not find class " + e);
070: throw new RuntimeException(e);
071: } catch (InstantiationException e) {
072: LOG
073: .error("Could not instantiate a class of the given document class: "
074: + e);
075: throw new RuntimeException(e);
076: } catch (IllegalAccessException e) {
077: LOG
078: .error("Illegal Access Exception while instantiating instance of document class: "
079: + e);
080: throw new RuntimeException(e);
081: }
082: }
083:
084: /**
085: * Constructs a AccountingLineClassDeterminer, using the document type name to determine the class name
086: * @param documentTypeName the name of a workflow document type
087: */
088: public AccountingLineClassDeterminer(String documentTypeName) {
089: try {
090: Class c = SpringContext.getBean(DocumentTypeService.class)
091: .getClassByName(documentTypeName);
092: accountingDocument = getAccountingDocumentFromClass(c);
093: } catch (InstantiationException e) {
094: LOG
095: .error("Could not instantiate a class of the given document class: "
096: + e);
097: throw new RuntimeException(e);
098: } catch (IllegalAccessException e) {
099: LOG
100: .error("Illegal Access Exception while instantiating instance of document class: "
101: + e);
102: throw new RuntimeException(e);
103: }
104: }
105:
106: /**
107: * This method returns an instantation of a blank instance of that document type, based on the class sent in
108: * @param documentClass the child class of AccountingDocument to instantiate
109: * @return a blank instance of the accounting document type
110: * @throws InstantiationException if exceptions are caused by the instantiation of an instance of the document
111: * @throws IllegalAccessException if the class of the document cannot be accessed
112: */
113: private AccountingDocument getAccountingDocumentFromClass(
114: Class documentClass) throws InstantiationException,
115: IllegalAccessException {
116:
117: if (!AccountingDocument.class.isAssignableFrom(documentClass)) {
118: throw new IllegalArgumentException(
119: "getSourceAccountingLineClassName method of KualiWorkflowUtils requires a documentTypeName String that corresponds to a class that implments AccountingDocument");
120: }
121:
122: String docTypeName = SpringContext.getBean(
123: DocumentTypeService.class).getDocumentTypeCodeByClass(
124: documentClass);
125: return (AccountingDocument) documentClass.newInstance();
126: }
127:
128: /**
129: * Returns the full name of the class of the source accounting lines in the document, or null if that class cannot be determined
130: * @return the name of the source accounting line class for the document, or null
131: */
132: public String getSourceAccountingLineClassName() {
133: if (sourceAccountingLineClassName == null && !sourceNameIsNull) {
134: if (accountingDocument != null) {
135: if (accountingDocument.getSourceAccountingLineClass() != null) {
136: sourceAccountingLineClassName = accountingDocument
137: .getSourceAccountingLineClass().getName();
138: } else {
139: sourceNameIsNull = true;
140: }
141: } else {
142: sourceNameIsNull = true;
143: }
144: }
145: return sourceAccountingLineClassName;
146: }
147:
148: /**
149: * Returns the full name of the class of the target accounting lines in the document, or null if that class cannot be determined
150: * @return the name of the target accounting line class for the document, or null
151: */
152: public String getTargetAccountingLineClassName() {
153: if (targetAccountingLineClassName == null && !targetNameIsNull) {
154: if (accountingDocument != null) {
155: if (accountingDocument.getTargetAccountingLineClass() != null) {
156: targetAccountingLineClassName = accountingDocument
157: .getTargetAccountingLineClass().getName();
158: } else {
159: targetNameIsNull = true;
160: }
161: } else {
162: targetNameIsNull = true;
163: }
164: }
165: return targetAccountingLineClassName;
166: }
167: }
|