001: /*
002: * Copyright 2007 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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.outerj.daisy.frontend.editor;
017:
018: import org.apache.excalibur.source.SourceValidity;
019: import org.apache.avalon.framework.context.Context;
020: import org.apache.cocoon.components.flow.FlowHelper;
021: import org.apache.cocoon.components.ContextHelper;
022: import org.apache.commons.jxpath.JXPathContext;
023: import org.outerj.daisy.repository.schema.DocumentType;
024: import org.outerj.daisy.repository.schema.FieldTypeUse;
025: import org.outerj.daisy.repository.schema.PartTypeUse;
026:
027: import java.util.Map;
028:
029: /**
030: * A source validity which remains valid as long as a document type
031: * and its contained part and field types do not change (the implementation
032: * checks the 'update count' properties of these entities),
033: * and as long as the classes of field editors stay the same.
034: *
035: * <p>It assumes the document type for which it needs to check
036: * the validity is available in a flow attribute called "documentType".
037: * The FieldEditor's should be available as an array in the flow
038: * attribute "fieldEditors".
039: *
040: * <p>To create an instance, use the method {@link #getValidity}.
041: *
042: * <p>This validity is used to cache the CForms form definition
043: * and form template of the dynamically generated fields form
044: * (part of the document editor).
045: *
046: */
047: public class FieldsFormSourceValidity implements SourceValidity {
048: private Context context;
049: private long documentTypeId;
050: private long documentTypeUpdateCount;
051: private long[] fieldTypeUpdateCounts;
052: private long[] partTypeUpdateCounts;
053: private Class[] fieldEditorClasses;
054:
055: private FieldsFormSourceValidity(Context context,
056: long documentTypeId, long documentTypeUpdateCount,
057: long[] fieldTypeUpdateCounts, long[] partTypeUpdateCounts,
058: Class[] fieldEditorClasses) {
059: this .context = context;
060: this .documentTypeId = documentTypeId;
061: this .documentTypeUpdateCount = documentTypeUpdateCount;
062: this .fieldTypeUpdateCounts = fieldTypeUpdateCounts;
063: this .partTypeUpdateCounts = partTypeUpdateCounts;
064: this .fieldEditorClasses = fieldEditorClasses;
065: }
066:
067: public int isValid() {
068: Map objectModel = ContextHelper.getObjectModel(context);
069: Object flowContext = FlowHelper.getContextObject(objectModel);
070: JXPathContext jxpc = JXPathContext.newContext(flowContext);
071: DocumentType documentType = (DocumentType) jxpc
072: .getValue("/documentType");
073: FieldEditor[] fieldEditors = (FieldEditor[]) jxpc
074: .getValue("/fieldEditors");
075: if (documentType == null)
076: throw new RuntimeException(
077: "Error in fields form validity source validity check: no documentType available in flow context.");
078: if (fieldEditors == null)
079: throw new RuntimeException(
080: "Error in fields form validity source validity check: no fieldEditors available in flow context.");
081:
082: if (documentType.getId() != documentTypeId) {
083: return SourceValidity.INVALID;
084: }
085:
086: if (documentType.getUpdateCount() != documentTypeUpdateCount)
087: return SourceValidity.INVALID;
088:
089: // check field types
090: FieldTypeUse[] fieldTypeUses = documentType.getFieldTypeUses();
091:
092: if (fieldTypeUses.length != fieldTypeUpdateCounts.length) // this is an impossible situation since the doctyp was not updated
093: throw new RuntimeException(
094: "Unexpected situation: number of field types do not match.");
095:
096: for (int i = 0; i < fieldTypeUses.length; i++) {
097: if (fieldTypeUses[i].getFieldType().getUpdateCount() != fieldTypeUpdateCounts[i])
098: return SourceValidity.INVALID;
099: }
100:
101: // Check part types
102: PartTypeUse[] partTypeUses = documentType.getPartTypeUses();
103:
104: if (partTypeUses.length != partTypeUpdateCounts.length)
105: throw new RuntimeException(
106: "Unexpected situation: number of part types do not match.");
107:
108: for (int i = 0; i < partTypeUses.length; i++) {
109: if (partTypeUses[i].getPartType().getUpdateCount() != partTypeUpdateCounts[i])
110: return SourceValidity.INVALID;
111: }
112:
113: // Check field editor classes
114: if (fieldEditorClasses.length != fieldEditors.length)
115: throw new RuntimeException(
116: "Unexpected situation: number of field editors do not match.");
117:
118: for (int i = 0; i < fieldEditorClasses.length; i++) {
119: if (!fieldEditorClasses[i].equals(fieldEditors[i]
120: .getClass()))
121: return SourceValidity.INVALID;
122: }
123:
124: return SourceValidity.VALID;
125: }
126:
127: public int isValid(SourceValidity sourceValidity) {
128: throw new RuntimeException(
129: "Unexpected situation: this method should not be called.");
130: }
131:
132: public static FieldsFormSourceValidity getValidity(
133: DocumentType documentType, FieldEditor[] fieldEditors,
134: Context context) {
135: return new FieldsFormSourceValidity(context, documentType
136: .getId(), documentType.getUpdateCount(),
137: getFieldTypeUpdateCounts(documentType),
138: getPartTypeUpdateCounts(documentType),
139: getFieldEditorClasses(fieldEditors));
140:
141: }
142:
143: private static long[] getFieldTypeUpdateCounts(
144: DocumentType documentType) {
145: FieldTypeUse[] fieldTypeUses = documentType.getFieldTypeUses();
146: long[] updateCounts = new long[fieldTypeUses.length];
147: for (int i = 0; i < updateCounts.length; i++) {
148: updateCounts[i] = fieldTypeUses[i].getFieldType()
149: .getUpdateCount();
150: }
151: return updateCounts;
152: }
153:
154: private static long[] getPartTypeUpdateCounts(
155: DocumentType documentType) {
156: PartTypeUse[] partTypeUses = documentType.getPartTypeUses();
157: long[] updateCounts = new long[partTypeUses.length];
158: for (int i = 0; i < updateCounts.length; i++) {
159: updateCounts[i] = partTypeUses[i].getPartType()
160: .getUpdateCount();
161: }
162: return updateCounts;
163: }
164:
165: private static Class[] getFieldEditorClasses(
166: FieldEditor[] fieldEditors) {
167: Class[] classes = new Class[fieldEditors.length];
168: for (int i = 0; i < fieldEditors.length; i++) {
169: classes[i] = fieldEditors[i].getClass();
170: }
171: return classes;
172: }
173: }
|