001 /**
002 * Copyright 2010 The Kuali Foundation Licensed under the
003 * Educational Community License, Version 2.0 (the "License"); you may
004 * not use this file except in compliance with the License. You may
005 * obtain a copy of the License at
006 *
007 * http://www.osedu.org/licenses/ECL-2.0
008 *
009 * Unless required by applicable law or agreed to in writing,
010 * software distributed under the License is distributed on an "AS IS"
011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
012 * or implied. See the License for the specific language governing
013 * permissions and limitations under the License.
014 */
015
016 package org.kuali.student.common.ui.client.application;
017
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.HashSet;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Map;
024 import java.util.Map.Entry;
025
026 import org.kuali.student.common.messages.dto.Message;
027 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
028 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
029 import org.kuali.student.common.ui.client.security.SecurityContext;
030 import org.kuali.student.common.ui.client.service.ServerPropertiesRpcService;
031 import org.kuali.student.common.ui.client.service.ServerPropertiesRpcServiceAsync;
032
033 import com.google.gwt.core.client.GWT;
034 import com.google.gwt.user.client.rpc.AsyncCallback;
035
036 /**
037 * The application contains information about who is currently logged in, the security context, and access
038 * to messages loaded from the message service in the app. It provides and a static way to obtain this
039 * information across the entire app.
040 *
041 * @author Kuali Student
042 *
043 */
044 public class ApplicationContext {
045 private ServerPropertiesRpcServiceAsync serverPropertiesRpcService = GWT.create(ServerPropertiesRpcService.class);
046
047 private boolean loggedIn = true;
048 private String userId = "testuser";
049 private String version = "KS";
050 private List<String> roles = new ArrayList<String>();
051
052 private Map<String, Map<String, String>> messages = new HashMap<String, Map<String,String>>();
053 private Map<String, String> flatMessages = new HashMap<String, String>();
054 private List<Message> messagesList = new ArrayList<Message>();
055
056 private SecurityContext securityContext;
057 private String applicationContextUrl;
058
059 //These maps are used to store query paths to their corresponding fieldDefinitions, and also whcih fields have cross constraints
060 private String parentPath = "";
061 private HashMap<String,HashMap<String,FieldDescriptor>> pathToFieldMapping = new HashMap<String,HashMap<String,FieldDescriptor>>();
062 private HashMap<String,HashMap<String,HashSet<HasCrossConstraints>>> crossConstraints = new HashMap<String,HashMap<String,HashSet<HasCrossConstraints>>>();
063 // private HashMap<String,HashMap<FieldDescriptor, String>> defaultValueMapping = new HashMap<String,HashMap<FieldDescriptor, String>>();
064 /**
065 * This constructor should only be visible to the common application package. If ApplicationContext is
066 * required outside this package do Application.getApplicationContext();
067 */
068 protected ApplicationContext() {
069 roles.add("role1");
070 roles.add("role2");
071
072 serverPropertiesRpcService.getContextPath(new AsyncCallback<String>(){
073
074 @Override
075 public void onFailure(Throwable caught) {
076 throw new RuntimeException("Fatal - Unable to initialze application context");
077 }
078
079 @Override
080 public void onSuccess(String result) {
081 applicationContextUrl = result;
082 }
083 });
084 }
085
086 public void setLoggedIn(boolean loggedIn) {
087 this.loggedIn = loggedIn;
088 }
089
090 public void setUserId(String userId) {
091 this.userId = userId;
092 }
093
094 public void setRoles(List<String> roles) {
095 this.roles = roles;
096 }
097
098 public boolean isLoggedIn() {
099 return loggedIn;
100 }
101
102 public String getUserId() {
103 return userId;
104 }
105
106 public List<String> getRoles() {
107 return roles;
108 }
109
110 /**
111 * Adds the messages in the list of messages to the map of the messages
112 * @param messages
113 */
114 public void addMessages(List<Message> messages) {
115 messagesList.addAll(messages);
116 for (Message m : messages) {
117 String groupName = m.getGroupName();
118 Map<String, String> group = this.messages.get(groupName);
119 if (group == null) {
120 group = new HashMap<String, String>();
121 this.messages.put(groupName, group);
122 }
123 group.put(m.getId(), m.getValue());
124 flatMessages.put(m.getId(), m.getValue());
125 }
126 }
127
128 /**
129 * Get a message by a unique id
130 */
131 public String getMessage(String messageId) {
132 return flatMessages.get(messageId);
133 }
134
135 /**
136 * Returns all the messages in the ApplicationContext
137 */
138 public List<Message> getMessages() {
139 return messagesList;
140 }
141
142
143 /**
144 * Get message by the group it is in and its unique id within that group
145 */
146 public String getMessage(String groupName, String messageId) {
147
148 String result = null;
149
150 Map<String, String> group = this.messages.get(groupName);
151 if (group != null) {
152 result = group.get(messageId);
153 }
154
155 return result;
156 }
157
158 /**
159 *
160 * This method looks up a UI Label in the messages cache.
161 * First looks for a label specific to the type and state of the field.
162 * If none found try for a generalized label.
163 * Otherwise return the supplied fieldId
164 * Groups provide namespace for same label ids within different LUs
165 *
166 * @param groupName - for example 'course' or 'program'
167 * @param type
168 * @param state
169 * @param fieldId
170 * @return
171 */
172 public String getUILabel(String groupName, String type, String state, String fieldId) {
173
174 String label = getMessage(groupName, type + ":" + state + ":" + fieldId);
175
176 if (label == null)
177 label = getMessage(groupName, fieldId);
178
179 if (label == null)
180 label = fieldId;
181
182 return label;
183
184 }
185
186 /**
187 * Same as getUILabel(String groupName, String type, String state, String fieldId) with no
188 * type and state needed
189 */
190 public String getUILabel(String groupName, String fieldId) {
191
192 String label = getMessage(groupName, fieldId);
193
194 if (label == null)
195 label = fieldId;
196
197 return label;
198
199 }
200
201 /**
202 * Get the security context for the app
203 * @return SecurityContext
204 */
205 public SecurityContext getSecurityContext() {
206 return securityContext;
207 }
208
209 public void setSecurityContext(SecurityContext securityContext) {
210 this.securityContext = securityContext;
211 }
212
213 /**
214 * Application URL based on the serverPropertiesRPC service result
215 */
216 public String getApplicationContextUrl() {
217 return applicationContextUrl;
218 }
219
220 public void setVersion(String version) {
221 this.version = version;
222 }
223
224 public String getVersion() {
225 return version;
226 }
227
228 /**
229 * Adds a mapping from path to a list of field descriptors for a given namespace
230 * namespace defaults to _default if null
231 * @param path
232 * @param fd
233 */
234 public void putCrossConstraint(String namespace, String path, HasCrossConstraints fd){
235 if(namespace==null){
236 namespace="_default";
237 }
238
239 HashMap<String,HashSet<HasCrossConstraints>> crossConstraintMap = crossConstraints.get(namespace);
240 if(crossConstraintMap==null){
241 crossConstraintMap = new HashMap<String,HashSet<HasCrossConstraints>>();
242 crossConstraints.put(namespace, crossConstraintMap);
243 }
244 HashSet<HasCrossConstraints> fieldDescriptors = crossConstraintMap.get(path);
245 if(fieldDescriptors == null){
246 fieldDescriptors = new HashSet<HasCrossConstraints>();
247 crossConstraintMap.put(path, fieldDescriptors);
248 }
249 fieldDescriptors.add(fd);
250 }
251
252
253
254 public HashSet<HasCrossConstraints> getCrossConstraint(String namespace, String path){
255 if(namespace==null){
256 namespace="_default";
257 }
258 HashMap<String,HashSet<HasCrossConstraints>> crossConstraintMap = crossConstraints.get(namespace);
259 if(crossConstraintMap!=null){
260 return crossConstraintMap.get(path);
261 }
262 return null;
263 }
264 public void clearCrossConstraintMap(String namespace){
265 if(namespace==null){
266 namespace="_default";
267 }
268 crossConstraints.remove(namespace);
269 }
270 public void putPathToFieldMapping(String namespace, String path, FieldDescriptor fd){
271 if(namespace==null){
272 namespace="_default";
273 }
274
275 HashMap<String,FieldDescriptor> pathToField = pathToFieldMapping.get(namespace);
276 if(pathToField==null){
277 pathToField = new HashMap<String,FieldDescriptor>();
278 pathToFieldMapping.put(namespace, pathToField);
279 }
280 pathToField.put(path, fd);
281 }
282
283 public FieldDescriptor getPathToFieldMapping(String namespace, String path){
284 if(namespace==null){
285 namespace="_default";
286 }
287
288 HashMap<String,FieldDescriptor> pathToField = pathToFieldMapping.get(namespace);
289 if(pathToField!=null){
290 return pathToField.get(path);
291 }
292 return null;
293 }
294 public void clearPathToFieldMapping(String namespace){
295 if(namespace==null){
296 namespace="_default";
297 }
298 pathToFieldMapping.remove(namespace);
299 }
300
301 /**
302 * Removes the bidirectional mapping for all paths that start with the path prefix
303 * This means if Field A had a dependency on Field B, and you cleared A, first all mappings with
304 * dependencies to A would be removed, then all mappings with dependencies to A would be removed.
305 * @param namespace
306 * @param pathPrefix
307 */
308 public void clearCrossConstraintsWithStartingPath(String namespace, String pathPrefix){
309 if(namespace==null){
310 namespace="_default";
311 }
312 //First delete any cross constraint mappings based on this field
313 HashMap<String,HashSet<HasCrossConstraints>> crossConstraintMap = crossConstraints.get(namespace);
314 if(crossConstraintMap!=null){
315 Iterator<Map.Entry<String,HashSet<HasCrossConstraints>>> constraintMapIter = crossConstraintMap.entrySet().iterator();
316 while(constraintMapIter.hasNext()){
317 Map.Entry<String,HashSet<HasCrossConstraints>> entry = constraintMapIter.next();
318 if(entry.getKey().startsWith(pathPrefix)){
319 constraintMapIter.remove();
320 }
321 }
322
323 //Find all the fieldDescriptors that start with the prefix and remove the cross constraint mapping to them
324 HashMap<String,FieldDescriptor> pathToField = pathToFieldMapping.get(namespace);
325 if(pathToField!=null){
326 Iterator<Entry<String, FieldDescriptor>> pathMapIter = pathToField.entrySet().iterator();
327 while(pathMapIter.hasNext()){
328 Entry<String, FieldDescriptor> entry = pathMapIter.next();
329 if(entry.getKey().startsWith(pathPrefix)){
330 FieldDescriptor fd = entry.getValue();
331 if(fd.getFieldWidget()!=null && fd.getFieldWidget() instanceof HasCrossConstraints && ((HasCrossConstraints)fd.getFieldWidget()).getCrossConstraints()!=null){
332 //Loop through the constraint paths and remove any mapping to the existing field descriptor
333 for(String path:((HasCrossConstraints)fd.getFieldWidget()).getCrossConstraints()){
334 HashSet<HasCrossConstraints> set = crossConstraintMap.get(path);
335 if(set!=null){
336 set.remove(fd.getFieldWidget());
337 }
338 }
339 }
340 }
341 }
342 }
343 }
344 }
345
346
347 public HashSet<HasCrossConstraints> getCrossConstraints(String namespace) {
348 if(namespace==null){
349 namespace="_default";
350 }
351 HashSet<HasCrossConstraints> results = new HashSet<HasCrossConstraints>();
352 HashMap<String,HashSet<HasCrossConstraints>> crossConstraintMap = crossConstraints.get(namespace);
353 if(crossConstraintMap!=null){
354 for(HashSet<HasCrossConstraints> fds: crossConstraintMap.values()){
355 results.addAll(fds);
356 }
357 }
358 return results;
359 }
360
361 public String getParentPath() {
362 return parentPath;
363 }
364
365 public void setParentPath(String parentPath) {
366 this.parentPath = parentPath;
367 }
368
369 // public void putDefaultValueMapping(String namespace,
370 // FieldDescriptor fieldDescriptor, String defaultValuePath) {
371 // if(namespace==null){
372 // namespace="_default";
373 // }
374 // HashMap<FieldDescriptor, String> defaultValueMap = defaultValueMapping.get(namespace);
375 // if(defaultValueMap==null){
376 // defaultValueMap = new HashMap<FieldDescriptor, String>();
377 // defaultValueMapping.put(namespace, defaultValueMap);
378 // }
379 // defaultValueMap.put(fieldDescriptor, defaultValuePath);
380 // }
381 //
382 // public HashMap<FieldDescriptor, String> getDefaultValueMapping(String namespace) {
383 // if(namespace==null){
384 // namespace="_default";
385 // }
386 // HashMap<FieldDescriptor, String> result = defaultValueMapping.get(namespace);
387 // if(result==null){
388 // result = new HashMap<FieldDescriptor, String>();
389 // }
390 // return result;
391 // }
392 // public void clearDefaultValueMapping(String namespace){
393 // if(namespace==null){
394 // namespace="_default";
395 // }
396 // defaultValueMapping.remove(namespace);
397 // }
398
399 }