2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.dialog.scxml;
19  
20  import java.io.Serializable;
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import javax.faces.context.FacesContext;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.commons.scxml.model.SCXML;
29  import org.apache.shale.dialog.Constants;
30  import org.apache.shale.dialog.DialogContext;
31  import org.apache.shale.dialog.DialogContextManager;
32  import org.apache.shale.dialog.base.AbstractDialogContextManager;
33  import org.apache.shale.dialog.scxml.config.DialogMetadata;
34  
35  /***
36   * <p>Implementation of {@link DialogContextManager} for integrating
37   * Commons SCXML into the Shale Dialog Manager.</p>
38   *
39   * @since 1.0.4
40   */
41  public final class SCXMLDialogManager extends AbstractDialogContextManager
42    implements Serializable {
43  
44  
45      // ------------------------------------------------------ SCXMLDialogManager Variables
46  
47  
48      /***
49       * Serial version UID.
50       */
51      private static final long serialVersionUID = -4358734655564376781L;
52  
53  
54      /***
55       * <p><code>Map</code> of {@link SCXML} configurations, keyed
56       * by dialog name.  This value is lazily instantiated.</p>
57       */
58      private Map dialogs = null;
59  
60  
61      /***
62       * <p>Map containing all currently active {@link DialogContext} instances for
63       * the current user.</p>
64       */
65      private final Map map = new HashMap();
66  
67  
68      /***
69       * <p>The <code>Log</code> instance for this class.  This value is lazily
70       * instantiated, and is also transient and may need to be regenerated.</p>
71       */
72      private transient Log log = null;
73  
74  
75      /***
76       * <p>Serial number used to generate dialog instance identifiers.</p>
77       */
78      private int serial = 0;
79  
80  
81      // -------------------------------------------------------- DialogContextManager Methods
82  
83  
84      /*** {@inheritDoc} */
85      public DialogContext create(FacesContext context, String name) {
86  
87          return create(context, name, null);
88  
89      }
90  
91  
92      /*** {@inheritDoc} */
93      public DialogContext create(FacesContext context, String name, DialogContext parent) {
94  
95          // Obtain the dialog metadata for the specified dialog
96          DialogMetadata dialog = (DialogMetadata) dialogs(context).get(name);
97          if (dialog == null) {
98              throw new IllegalArgumentException("No definition for dialog name '"
99                                                 + name + "' can be found");
100         }
101 
102         // Validate the specified parent (if any)
103         String parentDialogId = null;
104         if (parent != null) {
105             parentDialogId = parent.getId();
106             if (parent != get(parentDialogId)) {
107                 throw new IllegalStateException("The specified parent DialogContext '"
108                         + parentDialogId + "' is not managed by this DialogContextManager");
109             }
110         }
111 
112         // Configure a new SCXMLDialogContext instance
113         SCXMLDialogContext instance = new SCXMLDialogContext(this, dialog, generateId(),
114                 parentDialogId);
115         instance.setData(new HashMap());
116         synchronized (map) {
117             map.put(instance.getId(), instance);
118         }
119         context.getExternalContext().getRequestMap().put(Constants.CONTEXT_BEAN, instance);
120         fireOnCreate(instance);
121 
122         if (log().isDebugEnabled()) {
123             log().debug("create(Created DialogContext instance with ID '"
124                 + instance.getId() + "' for dialog with name '" + name + "'");
125         }
126 
127         return instance;
128     }
129 
130 
131     /*** {@inheritDoc} */
132     public DialogContext get(String id) {
133         return (DialogContext) map.get(id);
134     }
135 
136 
137     /*** {@inheritDoc} */
138     public void remove(DialogContext instance) {
139         boolean found = false;
140         // Cache ID in case any of the listeners destroy instance onRemove()
141         String id = instance.getId();
142         synchronized (map) {
143             found = map.remove(id) == instance;
144         }
145         if (found) {
146             ((SCXMLDialogContext) instance).deactivate();
147             fireOnRemove(instance);
148 
149             if (log().isDebugEnabled()) {
150                 log().debug("remove(Removed DialogContext instance with ID '"
151                     + id + "'");
152             }
153 
154         }
155     }
156 
157 
158     // --------------------------------------------------------- Private Methods
159 
160 
161     /***
162      * <p>Return a <code>Map</code> of the configured {@link SCXML} instances,
163      * keyed by logical dialog name.</p>
164      *
165      * @param context FacesContext for the current request
166      * @return Map of {@link SCXML} instances, keyed by logical dialog name
167      */
168     private Map dialogs(FacesContext context) {
169 
170         // Return the cached instance (if any)
171         if (this.dialogs != null) {
172             return this.dialogs;
173         }
174 
175         // Return the previously configured application scope instance (if any)
176         this.dialogs = (Map)
177           context.getExternalContext().getApplicationMap().get(Globals.DIALOGS);
178         return this.dialogs;
179 
180     }
181 
182 
183     /***
184      * <p>Generate and return a new dialog identifier.  FIXME - switch to
185      * something that creates randomized identifiers?</p>
186      *
187      * @return The generated identifier
188      */
189     private String generateId() {
190         return "" + ++serial;
191     }
192 
193 
194     /***
195      * <p>Return the <code>Log</code> instance for this instance.</p>
196      *
197      * @return The log instance
198      */
199     private Log log() {
200         if (this.log == null) {
201             this.log = LogFactory.getLog(SCXMLDialogManager.class);
202         }
203         return this.log;
204     }
205 
206 }
207