KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > ui > repo > renderer > NodeDescendantsLinkRenderer


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.web.ui.repo.renderer;
18
19 import java.io.IOException JavaDoc;
20 import java.io.Writer JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import javax.faces.component.NamingContainer;
26 import javax.faces.component.UIComponent;
27 import javax.faces.context.FacesContext;
28 import javax.transaction.UserTransaction JavaDoc;
29
30 import org.alfresco.model.ContentModel;
31 import org.alfresco.service.cmr.dictionary.DictionaryService;
32 import org.alfresco.service.cmr.dictionary.TypeDefinition;
33 import org.alfresco.service.cmr.repository.ChildAssociationRef;
34 import org.alfresco.service.cmr.repository.NodeRef;
35 import org.alfresco.service.cmr.repository.NodeService;
36 import org.alfresco.service.namespace.QName;
37 import org.alfresco.service.namespace.RegexQNamePattern;
38 import org.alfresco.web.bean.repository.Repository;
39 import org.alfresco.web.ui.common.Utils;
40 import org.alfresco.web.ui.common.renderer.BaseRenderer;
41 import org.alfresco.web.ui.repo.component.UINodeDescendants;
42
43 /**
44  * @author Kevin Roast
45  */

46 public class NodeDescendantsLinkRenderer extends BaseRenderer
47 {
48    // ------------------------------------------------------------------------------
49
// Renderer implementation
50

51    /**
52     * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
53     */

54    public void decode(FacesContext context, UIComponent component)
55    {
56       Map JavaDoc requestMap = context.getExternalContext().getRequestParameterMap();
57       String JavaDoc fieldId = getHiddenFieldName(context, component);
58       String JavaDoc value = (String JavaDoc)requestMap.get(fieldId);
59       
60       // we encoded the value to start with our Id
61
if (value != null && value.startsWith(component.getClientId(context) + NamingContainer.SEPARATOR_CHAR))
62       {
63          value = value.substring(component.getClientId(context).length() + 1);
64          
65          // found a new selected value for this component
66
// queue an event to represent the change
67
int separatorIndex = value.indexOf(NamingContainer.SEPARATOR_CHAR);
68          String JavaDoc selectedNodeId = value.substring(0, separatorIndex);
69          boolean isParent = Boolean.parseBoolean(value.substring(separatorIndex + 1));
70          NodeService service = getNodeService(context);
71          NodeRef ref = new NodeRef(Repository.getStoreRef(), selectedNodeId);
72          
73          UINodeDescendants.NodeSelectedEvent event = new UINodeDescendants.NodeSelectedEvent(component, ref, isParent);
74          component.queueEvent(event);
75       }
76    }
77    
78    /**
79     * @see javax.faces.render.Renderer#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
80     */

81    public void encodeEnd(FacesContext context, UIComponent component) throws IOException JavaDoc
82    {
83       // always check for this flag - as per the spec
84
if (component.isRendered() == true)
85       {
86          Writer JavaDoc out = context.getResponseWriter();
87          
88          UINodeDescendants control = (UINodeDescendants)component;
89          
90          // make sure we have a NodeRef from the 'value' property ValueBinding
91
Object JavaDoc val = control.getValue();
92          if (val instanceof NodeRef == false)
93          {
94             throw new IllegalArgumentException JavaDoc("UINodeDescendants component 'value' property must resolve to a NodeRef!");
95          }
96          NodeRef parentRef = (NodeRef)val;
97          
98          // use Spring JSF integration to get the node service bean
99
NodeService service = getNodeService(context);
100          DictionaryService dd = getDictionaryService(context);
101          UserTransaction JavaDoc tx = null;
102          try
103          {
104             tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
105             tx.begin();
106                
107             // TODO: need a comparator to sort node refs (based on childref qname)
108
// as currently the list is returned in a random order per request!
109

110             String JavaDoc separator = (String JavaDoc)component.getAttributes().get("separator");
111             if (separator == null)
112             {
113                separator = DEFAULT_SEPARATOR;
114             }
115             
116             // calculate the number of displayed child refs
117
if (service.exists(parentRef) == true)
118             {
119                List JavaDoc<ChildAssociationRef> childRefs = service.getChildAssocs(parentRef,
120                      ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
121                List JavaDoc<ChildAssociationRef> refs = new ArrayList JavaDoc<ChildAssociationRef>(childRefs.size());
122                for (int index=0; index<childRefs.size(); index++)
123                {
124                   ChildAssociationRef ref = childRefs.get(index);
125                   QName type = service.getType(ref.getChildRef());
126                   TypeDefinition typeDef = dd.getType(type);
127                   if (typeDef != null && dd.isSubClass(type, ContentModel.TYPE_FOLDER) &&
128                       dd.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
129                   {
130                      refs.add(ref);
131                   }
132                }
133                
134                // walk each child ref and output a descendant link control for each item
135
int total = 0;
136                int maximum = refs.size() > control.getMaxChildren() ? control.getMaxChildren() : refs.size();
137                for (int index=0; index<maximum; index++)
138                {
139                   ChildAssociationRef ref = refs.get(index);
140                   QName type = service.getType(ref.getChildRef());
141                   TypeDefinition typeDef = dd.getType(type);
142                   if (typeDef != null && dd.isSubClass(type, ContentModel.TYPE_FOLDER) &&
143                       dd.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
144                   {
145                      // output separator if appropriate
146
if (total > 0)
147                      {
148                         out.write( separator );
149                      }
150                      
151                      out.write(renderDescendant(context, control, ref, false));
152                      total++;
153                   }
154                }
155                
156                // do we need to render ellipses to indicate more items than the maximum
157
if (control.getShowEllipses() == true && refs.size() > maximum)
158                {
159                   out.write( separator );
160                   // TODO: is this the correct way to get the information we need?
161
// e.g. primary parent may not be the correct path? how do we make sure we find
162
// the correct parent and more importantly the correct Display Name value!
163
out.write( renderDescendant(context, control, service.getPrimaryParent(parentRef), true) );
164                }
165             }
166             
167             tx.commit();
168          }
169          catch (Throwable JavaDoc err)
170          {
171             try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
172             throw new RuntimeException JavaDoc(err);
173          }
174       }
175    }
176    
177    /**
178     * Render a descendant as a clickable link
179     *
180     * @param context FacesContext
181     * @param control UINodeDescendants to get attributes from
182     * @param childRef The ChildAssocRef of the child to render an HTML link for
183     * @param ellipses Whether to render the label of this descendant as a ellipses i.e. "..."
184     *
185     * @return HTML for a descendant link
186     */

187    private String JavaDoc renderDescendant(FacesContext context, UINodeDescendants control, ChildAssociationRef childRef, boolean ellipses)
188    {
189       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(256);
190       
191       buf.append("<a HREF='#' onclick=\"");
192       // build an HTML param that contains the client Id of this control, followed by the node Id
193
// followed by whether this is the parent node not a decendant (ellipses clicked)
194
String JavaDoc param = control.getClientId(context) + NamingContainer.SEPARATOR_CHAR +
195                      childRef.getChildRef().getId() + NamingContainer.SEPARATOR_CHAR +
196                      Boolean.toString(ellipses);
197       buf.append(Utils.generateFormSubmit(context, control, getHiddenFieldName(context, control), param));
198       buf.append('"');
199       Map JavaDoc attrs = control.getAttributes();
200       if (attrs.get("style") != null)
201       {
202          buf.append(" style=\"")
203             .append(attrs.get("style"))
204             .append('"');
205       }
206       if (attrs.get("styleClass") != null)
207       {
208          buf.append(" class=")
209             .append(attrs.get("styleClass"));
210       }
211       buf.append('>');
212       
213       if (ellipses == false)
214       {
215          // label is the name of the child node assoc
216
String JavaDoc name = Repository.getNameForNode(getNodeService(context), childRef.getChildRef());
217          buf.append(Utils.encode(name));
218       }
219       else
220       {
221          // TODO: allow the ellipses string to be set as component property?
222
buf.append("...");
223       }
224       
225       buf.append("</a>");
226       
227       return buf.toString();
228    }
229    
230    
231    // ------------------------------------------------------------------------------
232
// Private helpers
233

234    /**
235     * Get the hidden field name for this node descendant component.
236     * Build a shared field name from the parent form name and the string "ndec".
237     *
238     * @return hidden field name shared by all node descendant components within the Form.
239     */

240    private static String JavaDoc getHiddenFieldName(FacesContext context, UIComponent component)
241    {
242       return Utils.getParentForm(context, component).getClientId(context) + NamingContainer.SEPARATOR_CHAR + "ndec";
243    }
244    
245    /**
246     * Use Spring JSF integration to return the Node Service bean instance
247     *
248     * @param context FacesContext
249     *
250     * @return Node Service bean instance or throws exception if not found
251     */

252    private static NodeService getNodeService(FacesContext context)
253    {
254       NodeService service = Repository.getServiceRegistry(context).getNodeService();
255       if (service == null)
256       {
257          throw new IllegalStateException JavaDoc("Unable to obtain NodeService bean reference.");
258       }
259       
260       return service;
261    }
262    
263    /**
264     * Use Spring JSF integration to return the Dictionary Service bean instance
265     *
266     * @param context FacesContext
267     *
268     * @return Dictionary Service bean instance or throws exception if not found
269     */

270    private static DictionaryService getDictionaryService(FacesContext context)
271    {
272       DictionaryService service = Repository.getServiceRegistry(context).getDictionaryService();
273       if (service == null)
274       {
275          throw new IllegalStateException JavaDoc("Unable to obtain DictionaryService bean reference.");
276       }
277       
278       return service;
279    }
280    
281    private static final String JavaDoc DEFAULT_SEPARATOR = " | ";
282 }
283
Popular Tags