KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > forms > binding > MultiValueJXPathBinding


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.forms.binding;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.LinkedList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Locale JavaDoc;
24
25 import org.apache.avalon.framework.logger.Logger;
26 import org.apache.cocoon.forms.datatype.convertor.Convertor;
27 import org.apache.cocoon.forms.datatype.convertor.ConversionResult;
28 import org.apache.cocoon.forms.formmodel.Widget;
29 import org.apache.commons.jxpath.JXPathContext;
30 import org.apache.commons.jxpath.Pointer;
31
32 /**
33  * Simple binding for multi fields: on save, first deletes the target data
34  * before recreating it from scratch.
35  *
36  * @version $Id: MultiValueJXPathBinding.java 289538 2005-09-16 13:46:22Z sylvain $
37  */

38 public class MultiValueJXPathBinding extends JXPathBindingBase {
39
40     private final String JavaDoc multiValueId;
41     private final String JavaDoc multiValuePath;
42     private final String JavaDoc rowPath;
43     private final JXPathBindingBase updateBinding;
44     private final Convertor convertor;
45     private final Locale JavaDoc convertorLocale;
46
47     public MultiValueJXPathBinding(
48         JXPathBindingBuilderBase.CommonAttributes commonAtts, String JavaDoc multiValueId,
49         String JavaDoc multiValuePath, String JavaDoc rowPath,
50         JXPathBindingBase[] updateBindings, Convertor convertor, Locale JavaDoc convertorLocale) {
51         super(commonAtts);
52         this.multiValueId = multiValueId;
53         this.multiValuePath = multiValuePath;
54         this.rowPath = rowPath;
55         this.updateBinding = new ComposedJXPathBindingBase(JXPathBindingBuilderBase.CommonAttributes.DEFAULT, updateBindings);
56         this.convertor = convertor;
57         this.convertorLocale = convertorLocale;
58     }
59     
60     public String JavaDoc getId() { return multiValueId; }
61     public String JavaDoc getMultiValuePath() { return multiValuePath; }
62     public String JavaDoc getRowPath() { return rowPath; }
63     public ComposedJXPathBindingBase getUpdateBinding() { return (ComposedJXPathBindingBase)updateBinding; }
64     public Convertor getConvertor() { return convertor; }
65     public Locale JavaDoc getLocale() { return convertorLocale; }
66
67     public void doLoad(Widget frmModel, JXPathContext jctx) throws BindingException {
68         Widget widget = selectWidget(frmModel,this.multiValueId);
69         if (widget == null) {
70             throw new BindingException("The widget with the ID [" + this.multiValueId
71                     + "] referenced in the binding does not exist in the form definition.");
72         }
73
74         // Move to multi value context
75
Pointer ptr = jctx.getPointer(this.multiValuePath);
76         if (ptr.getNode() != null) {
77             // There are some nodes to load from
78

79             JXPathContext multiValueContext = jctx.getRelativeContext(ptr);
80             // build a jxpath iterator for pointers
81
Iterator JavaDoc rowPointers = multiValueContext.iterate(this.rowPath);
82
83             LinkedList JavaDoc list = new LinkedList JavaDoc();
84
85             while (rowPointers.hasNext()) {
86                 Object JavaDoc value = rowPointers.next();
87
88                 if (value != null && convertor != null) {
89                     if (value instanceof String JavaDoc) {
90                         ConversionResult conversionResult = convertor.convertFromString((String JavaDoc)value, convertorLocale, null);
91                         if (conversionResult.isSuccessful())
92                             value = conversionResult.getResult();
93                         else
94                             value = null;
95                     } else {
96                         getLogger().warn("Convertor ignored on backend-value which isn't of type String.");
97                     }
98                 }
99
100                 list.add(value);
101             }
102
103             widget.setValue(list.toArray());
104         }
105
106         if (getLogger().isDebugEnabled())
107             getLogger().debug("done loading values " + toString());
108     }
109
110     public void doSave(Widget frmModel, JXPathContext jctx) throws BindingException {
111         Widget widget = selectWidget(frmModel,this.multiValueId);
112         Object JavaDoc[] values = (Object JavaDoc[])widget.getValue();
113
114         JXPathContext multiValueContext = jctx.getRelativeContext(jctx.createPath(this.multiValuePath));
115
116         // Delete all that is already present
117

118         // Unfortunately the following statement doesn't work (it doesn't removes all elements from the
119
// list because of a bug in JXPath) so I had to work out another immediate solution
120
//multiValueContext.removeAll(this.rowPath);
121

122         Iterator JavaDoc rowPointers = multiValueContext.iteratePointers(this.rowPath);
123         List JavaDoc l = new ArrayList JavaDoc();
124         while( rowPointers.hasNext() )
125         {
126             Pointer p = (Pointer)rowPointers.next();
127             l.add(p.asPath());
128         }
129         Collections.sort(l);
130         for( int i = l.size()-1; i >= 0; i-- )
131         {
132             multiValueContext.removePath((String JavaDoc)l.get(i));
133         }
134
135         boolean update = false;
136
137         if (values != null) {
138             // first update the values
139
for (int i = 0; i < values.length; i++) {
140                 String JavaDoc path = this.rowPath + '[' + (i+1) + ']';
141                 Pointer rowPtr = multiValueContext.createPath(path);
142
143                 Object JavaDoc value = values[i];
144                 if (value != null && convertor != null) {
145                     value = convertor.convertToString(value, convertorLocale, null);
146                 }
147
148                 rowPtr.setValue(value);
149             }
150
151             // now perform any other bindings that need to be performed when the value is updated
152
this.updateBinding.saveFormToModel(frmModel, multiValueContext);
153
154             update = true;
155         }
156
157
158         if (getLogger().isDebugEnabled()) {
159             getLogger().debug("done saving " + toString() + " -- on-update == " + update);
160         }
161
162
163
164     }
165
166     public String JavaDoc toString() {
167         return "MultiValueJXPathBinding [widget=" + this.multiValueId + ", xpath=" + this.multiValuePath + "]";
168     }
169
170     public void enableLogging(Logger logger) {
171         super.enableLogging(logger);
172         this.updateBinding.enableLogging(logger);
173     }
174 }
175
Popular Tags