View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.trinidad.change;
20  
21  import javax.faces.component.UIComponent;
22  import javax.faces.context.FacesContext;
23  
24  import org.apache.myfaces.trinidad.component.UIXIterator;
25  import org.apache.myfaces.trinidad.context.RequestContext;
26  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
27  
28  import org.w3c.dom.Document;
29  
30  
31  /**
32   * Base ChangeManager implementation that manages the bookkeeping for
33   * supporting both ComponentChanges and DocumentChanges.
34   * subclasses must implement addComponentChangeImpl() to implement
35   * the ComponentChange support.  To support DocumentChanges,
36   * <code>getDocument</code> must be implemented.
37   *
38   * @version $Name:  $ ($Revision: adfrt/faces/adf-faces-impl/src/main/java/oracle/adfinternal/view/faces/change/BaseChangeManager.java#1 $) $Date: 11-nov-2005.14:59:41 $
39   */
40  abstract class BaseChangeManager extends ChangeManager
41  {
42    /**
43     * {@inheritDoc}
44     */
45    @Override
46    public void addComponentChange(
47      FacesContext facesContext,
48      UIComponent uiComponent,
49      ComponentChange change)
50    {
51      // if our component is a stamped component by UIXIterator, we 
52      // don't want to persist the changes 
53      UIComponent parent = uiComponent.getParent();
54      UIComponent root = facesContext.getViewRoot();
55      while (parent != null && parent != root)
56      {
57        if (parent.getClass() == UIXIterator.class) 
58        {
59          _LOG.info("DONT_PERSIST_STAMPED_COMPONENT_INSIDE_ITERATOR");      
60          return;
61        }
62        parent = parent.getParent();      
63      }
64          
65      if (facesContext == null || uiComponent == null || change == null)
66        throw new IllegalArgumentException(_LOG.getMessage(
67          "CANNOT_ADD_CHANGE_WITH_FACECONTEXT_OR_UICOMPONENT_OR_NULL"));
68  
69      // add the change to the component
70      addComponentChangeImpl(facesContext, uiComponent, change);
71  
72      // add a corresponding DocumentChange if possible
73      _addEquivalentDocumentChange(facesContext, uiComponent, change);
74    }
75    
76    /**
77     * A no-op implementation of adding a ComponentChange. Sub-classers should
78     * override and provide an implementation if they support component changes.
79     * @param facesContext The FacesContext for this request.
80     * @param targetComponent The target component against which this change needs 
81     * to be registered and applied later on.
82     * @param componentChange The ComponentChange to add
83     */
84     protected void addComponentChangeImpl(
85      FacesContext facesContext,
86      UIComponent targetComponent,
87      ComponentChange componentChange)
88    {
89      //no-op
90    }
91  
92    // =-= bts Testing hack hook
93    protected void persistDocumentChanges(
94      FacesContext facesContext)
95    {
96      // noop
97    }
98  
99    /**
100    * Override to return the Document to modify as part of document-based
101    * persistence.
102    * Subclassers adding Document-based Persistence
103    * must override this method and should override
104    * <code>supportsDocumentPersistence</code>
105    * in order to enable  Document-based Persistence
106    */
107   protected abstract Document getDocument(FacesContext context);
108   
109   /**
110    *  Returns true if we can support Document-based Persistence
111    *  in this ChangeManager.  Subclassers adding Document-based Persistence
112    *  should override this method and must override <code>getDocument</code>
113    *  in order to enable  Document-based Persistence.
114    * @param context
115    * @return true if we can support Document-based Persistence
116    */
117   protected boolean supportsDocumentPersistence(FacesContext context)
118   {
119     // correct, but potentially slow implementation
120     return getDocument(context) != null;
121   }
122 
123   /*
124    * Create and add a DocumentChange corresponding to the supplied ComponentChange
125    */
126   private void _addEquivalentDocumentChange(
127     FacesContext facesContext,
128     UIComponent uiComponent,
129     ComponentChange compChange)
130   {
131     if (supportsDocumentPersistence(facesContext))
132     {
133       // try to get equivalent DocumentChange from ComponentChange
134       DocumentChange docChange = createDocumentChange(compChange);
135 
136       if (docChange != null)
137       {
138         //  We ("this" object) could be just a delegate of the top level change manager (i.e. the 
139         //  changemanager registered with the webapp). Automatically adding a document change (or 
140         //  deciding whether to add one) should be done by the top level changemanager 
141         ChangeManager topChangeManager = RequestContext.getCurrentInstance().getChangeManager();
142         
143         if ( ChangeOutcome.CHANGE_APPLIED ==
144               topChangeManager.addDocumentChangeWithOutcome(facesContext, uiComponent, docChange) )
145         {
146           // notify the registered change manager that we applied the document change 
147           topChangeManager.documentChangeApplied(facesContext, uiComponent, compChange);
148         }
149       }
150     }    
151   }
152   
153   private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
154     BaseChangeManager.class);
155 }