001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.clientapp;
018:
019: import java.lang.reflect.Field;
020:
021: import org.apache.commons.lang.StringUtils;
022: import org.junit.Test;
023: import org.kuali.workflow.test.WorkflowTestCase;
024:
025: import edu.iu.uis.eden.EdenConstants;
026: import edu.iu.uis.eden.KEWServiceLocator;
027: import edu.iu.uis.eden.clientapp.vo.DocumentContentVO;
028: import edu.iu.uis.eden.clientapp.vo.NetworkIdVO;
029: import edu.iu.uis.eden.clientapp.vo.WorkflowAttributeDefinitionVO;
030: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValue;
031: import edu.iu.uis.eden.routetemplate.TestRuleAttribute;
032:
033: /**
034: * Tests that client interaction with document content behaves approriately.
035: *
036: * @author Eric Westfall
037: */
038: public class DocumentContentTest extends WorkflowTestCase {
039:
040: private static final String DOCUMENT_CONTENT = EdenConstants.DOCUMENT_CONTENT_ELEMENT;
041: private static final String ATTRIBUTE_CONTENT = EdenConstants.ATTRIBUTE_CONTENT_ELEMENT;
042: private static final String SEARCHABLE_CONTENT = EdenConstants.SEARCHABLE_CONTENT_ELEMENT;
043: private static final String APPLICATION_CONTENT = EdenConstants.APPLICATION_CONTENT_ELEMENT;
044:
045: @Test
046: public void testDocumentContent() throws Exception {
047: String startContent = "<" + DOCUMENT_CONTENT + ">";
048: String endContent = "</" + DOCUMENT_CONTENT + ">";
049: String emptyContent1 = startContent + endContent;
050: String emptyContent2 = "<" + DOCUMENT_CONTENT + "/>";
051:
052: WorkflowDocument document = new WorkflowDocument(
053: new NetworkIdVO("ewestfal"), "TestDocumentType");
054:
055: // test no content prior to server creation
056: assertEquals("Content should be empty.", "", document
057: .getApplicationContent());
058: assertEquals("Content should be empty.", "", document
059: .getAttributeContent());
060: assertEquals("Content should be empty.", "", document
061: .getDocumentContent().getSearchableContent());
062: String fullContent = document.getDocumentContent()
063: .getFullContent();
064: assertTrue("Invalid content conversion.", fullContent
065: .equals(emptyContent1)
066: || fullContent.equals(emptyContent2));
067:
068: // test content after server creation
069: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
070: "TestDocumentType");
071: // this will create the document on the server
072: document.saveRoutingData();
073: assertNotNull(document.getRouteHeaderId());
074: // the route header id on the document content should be there now
075: assertEquals("Incorrect document id.", document
076: .getRouteHeaderId(), document.getDocumentContent()
077: .getRouteHeaderId());
078: assertEquals("Content should be empty.", "", document
079: .getApplicationContent());
080: assertEquals("Content should be empty.", "", document
081: .getAttributeContent());
082: assertEquals("Content should be empty.", "", document
083: .getDocumentContent().getSearchableContent());
084: fullContent = document.getDocumentContent().getFullContent();
085: assertTrue("Invalid content conversion.", fullContent
086: .equals(emptyContent1)
087: || fullContent.equals(emptyContent2));
088: // verify the content on the actual document stored in the database
089: DocumentRouteHeaderValue routeHeader = KEWServiceLocator
090: .getRouteHeaderService().getRouteHeader(
091: document.getRouteHeaderId());
092: assertTrue("Invalid initial content.", routeHeader
093: .getDocContent().equals(emptyContent1)
094: || routeHeader.getDocContent().equals(emptyContent2));
095:
096: // test simple case, no attributes
097: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
098: "TestDocumentType");
099: String attributeContent = "<attribute1><id value=\"3\"/></attribute1>";
100: String searchableContent = "<searchable1><data>hello</data></searchable1>";
101: DocumentContentVO contentVO = document.getDocumentContent();
102: contentVO.setAttributeContent(constructContent(
103: ATTRIBUTE_CONTENT, attributeContent));
104: contentVO.setSearchableContent(constructContent(
105: SEARCHABLE_CONTENT, searchableContent));
106: document.saveRoutingData();
107: // now reload the document
108: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
109: document.getRouteHeaderId());
110: String expectedContent = startContent
111: + constructContent(ATTRIBUTE_CONTENT, attributeContent)
112: + constructContent(SEARCHABLE_CONTENT,
113: searchableContent) + endContent;
114: fullContent = document.getDocumentContent().getFullContent();
115: assertEquals("Invalid content conversion.", StringUtils
116: .deleteWhitespace(expectedContent), StringUtils
117: .deleteWhitespace(fullContent));
118:
119: // now, add an attribute and then clear it, document content should remain the same
120: String testAttributeContent = new TestRuleAttribute()
121: .getDocContent();
122: WorkflowAttributeDefinitionVO attributeDefinition = new WorkflowAttributeDefinitionVO(
123: TestRuleAttribute.class.getName());
124: document.addAttributeDefinition(attributeDefinition);
125: document.clearAttributeDefinitions();
126: document.saveRoutingData();
127: fullContent = document.getDocumentContent().getFullContent();
128: assertEquals("Invalid content conversion.", StringUtils
129: .deleteWhitespace(expectedContent), StringUtils
130: .deleteWhitespace(fullContent));
131:
132: // now really add an attribute and save the content
133: document.addAttributeDefinition(attributeDefinition);
134: document.saveRoutingData();
135: fullContent = document.getDocumentContent().getFullContent();
136: expectedContent = startContent
137: + constructContent(ATTRIBUTE_CONTENT, attributeContent
138: + testAttributeContent)
139: + constructContent(SEARCHABLE_CONTENT,
140: searchableContent) + endContent;
141: assertEquals("Invalid content conversion.", StringUtils
142: .deleteWhitespace(expectedContent), StringUtils
143: .deleteWhitespace(fullContent));
144:
145: // let's reload the document and try appending a couple of attributes for good measure, this will test appending to existing content on non-materialized document content
146: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
147: document.getRouteHeaderId());
148: document.addAttributeDefinition(attributeDefinition);
149: document.addAttributeDefinition(attributeDefinition);
150: document.saveRoutingData();
151: fullContent = document.getDocumentContent().getFullContent();
152: expectedContent = startContent
153: + constructContent(ATTRIBUTE_CONTENT, attributeContent
154: + testAttributeContent + testAttributeContent
155: + testAttributeContent)
156: + constructContent(SEARCHABLE_CONTENT,
157: searchableContent) + endContent;
158: assertEquals("Invalid content conversion.", StringUtils
159: .deleteWhitespace(expectedContent), StringUtils
160: .deleteWhitespace(fullContent));
161:
162: // now let's try clearing the attribute content
163: document.clearAttributeContent();
164: expectedContent = startContent
165: + constructContent(SEARCHABLE_CONTENT,
166: searchableContent) + endContent;
167: fullContent = document.getDocumentContent().getFullContent();
168: assertEquals("Invalid content conversion.", StringUtils
169: .deleteWhitespace(expectedContent), StringUtils
170: .deleteWhitespace(fullContent));
171: // now save it and make sure it comes back from the server the same way
172: document.saveRoutingData();
173: fullContent = document.getDocumentContent().getFullContent();
174: assertEquals("Invalid content conversion.", StringUtils
175: .deleteWhitespace(expectedContent), StringUtils
176: .deleteWhitespace(fullContent));
177:
178: // Test backward compatibility with old-school document content, this document content could look something
179: // like <myRadContent>abcd</myRadContent>, when converted to the new form, it should come out like
180: // <documentContent><applicationContent><myRadContent>abcd</myRadContent></applicationContent></documentContent>
181: String myRadContent = "<myRadContent>abcd</myRadContent>";
182: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
183: "TestDocumentType");
184: DocumentRouteHeaderValue documentValue = KEWServiceLocator
185: .getRouteHeaderService().getRouteHeader(
186: document.getRouteHeaderId());
187: documentValue.setDocContent(myRadContent);
188: KEWServiceLocator.getRouteHeaderService().saveRouteHeader(
189: documentValue);
190: // reload the client document and check that the XML has been auto-magically converted
191: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
192: document.getRouteHeaderId());
193: String expected = startContent
194: + constructContent(APPLICATION_CONTENT, myRadContent)
195: + endContent;
196: fullContent = document.getDocumentContent().getFullContent();
197: assertEquals("Backward compatibility failure.", StringUtils
198: .deleteWhitespace(expected), StringUtils
199: .deleteWhitespace(fullContent));
200: }
201:
202: private String constructContent(String type, String content) {
203: if (content == null) {
204: return "";
205: }
206: return "<" + type + ">" + content + "</" + type + ">";
207: }
208:
209: /**
210: * Tests that the lazy loading of document content is functioning properly.
211: */
212: @Test
213: public void testLazyContentLoading() throws Exception {
214: WorkflowDocument document = new WorkflowDocument(
215: new NetworkIdVO("ewestfal"), "TestDocumentType");
216: assertFalse("Content should not be loaded yet.",
217: isContentLoaded(document));
218:
219: // save the document, the content should still not be loaded
220: document.setTitle("Test Title");
221: document.saveRoutingData();
222: assertFalse("Content should not be loaded yet.",
223: isContentLoaded(document));
224:
225: // now get the document content, this should result in the content being loaded
226: DocumentContentVO content = document.getDocumentContent();
227: assertNotNull("Content should be non-null.", content);
228: assertTrue("Content should now be loaded.",
229: isContentLoaded(document));
230:
231: // create a new document, try saving it, and make sure the content has not been loaded
232: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
233: "TestDocumentType");
234: document.saveDocument("");
235: assertFalse("Content should not be loaded yet.",
236: isContentLoaded(document));
237:
238: // set some content on the document
239: String applicationContent = "<myTestContent/>";
240: document.setApplicationContent(applicationContent);
241: assertTrue("Content should now be loaded.",
242: isContentLoaded(document));
243: document.saveRoutingData();
244:
245: // reload the document
246: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
247: document.getRouteHeaderId());
248: assertFalse("Content should not be loaded yet.",
249: isContentLoaded(document));
250: assertEquals("Invalid application content", applicationContent,
251: document.getApplicationContent());
252: assertTrue("Content should now be loaded.",
253: isContentLoaded(document));
254:
255: }
256:
257: private boolean isContentLoaded(WorkflowDocument document)
258: throws Exception {
259: Field contentField = document.getClass().getDeclaredField(
260: "documentContent");
261: contentField.setAccessible(true);
262: return contentField.get(document) != null;
263: }
264:
265: /**
266: * Tests that document content is reloaded from the database after every call (such as Approve, etc.)
267: * so as to verify that the document content stored on the WorkflowDocument will not go stale in between
268: * calls.
269: */
270: @Test
271: public void testDocumentContentConsistency() throws Exception {
272: WorkflowDocument document = new WorkflowDocument(
273: new NetworkIdVO("ewestfal"), "TestDocumentType");
274: String appContent = "<app>content</app>";
275: document.setApplicationContent(appContent);
276: document.saveRoutingData();
277: assertEquals(appContent, document.getApplicationContent());
278:
279: // load the document and modify the content
280: WorkflowDocument document2 = new WorkflowDocument(
281: new NetworkIdVO("ewestfal"), document
282: .getRouteHeaderId());
283: assertEquals(appContent, document2.getApplicationContent());
284: String appContent2 = "<app>content2</app>";
285: document2.setApplicationContent(appContent2);
286: assertEquals(appContent2, document2.getApplicationContent());
287: document2.saveRoutingData();
288:
289: // the original document should not notice these changes yet
290: assertEquals(appContent, document.getApplicationContent());
291: // but if we saveRoutingData, we should see the new value
292: document.saveRoutingData();
293: assertEquals(appContent2, document.getApplicationContent());
294:
295: // also verify that just setting the content, but not saving it, doesn't get persisted
296: document2.setApplicationContent("<bad>content</bad>");
297: document2 = new WorkflowDocument(new NetworkIdVO("ewestfal"),
298: document2.getRouteHeaderId());
299: assertEquals(appContent2, document.getApplicationContent());
300: }
301:
302: /**
303: * Tests modification of the DocumentContentVO object directly.
304: */
305: @Test
306: public void testManualDocumentContentModification()
307: throws Exception {
308: WorkflowDocument document = new WorkflowDocument(
309: new NetworkIdVO("ewestfal"), "TestDocumentType");
310: document.saveRoutingData();
311:
312: // fetch it from WorkflowInfo
313: DocumentContentVO content = new WorkflowInfo()
314: .getDocumentContent(document.getRouteHeaderId());
315: assertTrue("Should contain default content, was "
316: + content.getFullContent(),
317: EdenConstants.DEFAULT_DOCUMENT_CONTENT.equals(content
318: .getFullContent())
319: || EdenConstants.DEFAULT_DOCUMENT_CONTENT2
320: .equals(content.getFullContent()));
321:
322: String appContent = "<abcdefg>hijklm n o p</abcdefg>";
323: content.setApplicationContent(appContent);
324: assertFalse(isContentLoaded(document));
325: document.saveDocumentContent(content);
326: assertTrue(isContentLoaded(document));
327:
328: // test that the content on the document is the same as the content we just set
329: assertEquals(appContent, document.getApplicationContent());
330:
331: // fetch the document fresh and make sure the content is correct
332: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
333: document.getRouteHeaderId());
334: assertEquals(appContent, document.getApplicationContent());
335:
336: }
337: }
|