001: /*
002: * Copyright 2006-2007 Luca Garulli (luca.garulli@assetdata.it)
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.romaframework.core.flow;
018:
019: import java.util.HashMap;
020: import java.util.IdentityHashMap;
021: import java.util.List;
022: import java.util.Map;
023: import java.util.WeakHashMap;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027: import org.romaframework.aspect.session.SessionAspect;
028: import org.romaframework.aspect.session.SessionInfo;
029: import org.romaframework.aspect.session.SessionListener;
030: import org.romaframework.aspect.view.ViewAspect;
031: import org.romaframework.aspect.view.ViewException;
032: import org.romaframework.aspect.view.form.ContentComponent;
033: import org.romaframework.aspect.view.form.ContentForm;
034: import org.romaframework.aspect.view.form.FormPool;
035: import org.romaframework.aspect.view.form.FormViewer;
036: import org.romaframework.aspect.view.screen.Screen;
037: import org.romaframework.core.config.ApplicationConfiguration;
038: import org.romaframework.core.config.RomaApplicationContext;
039: import org.romaframework.core.exception.ConfigurationNotFoundException;
040: import org.romaframework.core.exception.UserException;
041: import org.romaframework.core.schema.SchemaClass;
042: import org.romaframework.core.schema.SchemaElement;
043: import org.romaframework.core.schema.SchemaFeaturesChangeListener;
044: import org.romaframework.core.schema.SchemaField;
045: import org.romaframework.core.schema.SchemaManager;
046: import org.romaframework.core.schema.SchemaObject;
047: import org.romaframework.core.util.DynaBean;
048: import org.romaframework.core.validation.ValidationException;
049:
050: /**
051: * Manager of forms, user objects and their relationships. Track all changes in objects. It's used to update changed properties of
052: * objects after user's code execution.
053: *
054: * @author Luca Garulli (luca.garulli@assetdata.it)
055: */
056: public class ObjectContext implements SessionListener {
057:
058: private Map<SessionInfo, IdentityHashMap<Object, ContentComponent>> objectsForms;
059: private SessionAspect sessionManager;
060: private static ThreadLocalContext localContext;
061:
062: private static ObjectContext instance = new ObjectContext();
063: private static Log log = LogFactory.getLog(ObjectContext.class);
064:
065: protected ObjectContext() {
066: localContext = new ThreadLocalContext();
067:
068: sessionManager = RomaApplicationContext.getInstance().getBean(
069: SessionAspect.class);
070: objectsForms = new WeakHashMap<SessionInfo, IdentityHashMap<Object, ContentComponent>>();
071: }
072:
073: public void shutdown() {
074: objectsForms.clear();
075: objectsForms = null;
076: }
077:
078: /**
079: * Get a session context attribute value.
080: *
081: * @param iKey
082: * attribute name
083: * @return Attribute value
084: */
085: public Object getProperty(String iKey) {
086: return sessionManager.getProperty(iKey);
087: }
088:
089: /**
090: * Set a session context attribute giving a name and a value.
091: *
092: * @param iKey
093: * attribute name
094: * @param iValue
095: * attribute value
096: */
097: public void setProperty(String iKey, Object iValue) {
098: sessionManager.setProperty(iKey, iValue);
099: }
100:
101: /**
102: * Get a component configured in the IoC system.
103: *
104: * @param iClass
105: * Interface of component implementation
106: * @return the component if any or null if not found
107: */
108: public <T> T getComponent(Class<T> iClass) {
109: return RomaApplicationContext.getInstance().getBean(iClass);
110: }
111:
112: /**
113: * Get a component configured in the IoC system.
114: *
115: * @param iName
116: * Component name
117: * @return the component if any or null if not found
118: */
119: public <T> T getComponent(String iName) {
120: return (T) RomaApplicationContext.getInstance().getBean(iName);
121: }
122:
123: /**
124: * Check if a component was configured in the IoC system.
125: *
126: * @param iClass
127: * Interface of component implementation
128: * @return true if was configured, otherwise null
129: */
130: public boolean existComponent(Class<? extends Object> iClass) {
131: return existComponent(iClass.getSimpleName());
132: }
133:
134: /**
135: * Check if a component was configured in the IoC system.
136: *
137: * @param iComponentName
138: * Name of component to search
139: * @return true if was configured, otherwise null
140: */
141: public boolean existComponent(String iComponentName) {
142: return RomaApplicationContext.getInstance().existBean(
143: iComponentName);
144: }
145:
146: /**
147: * Create an association between a User Object and a ContentForm. This association is useful to gather custom form information.
148: *
149: * @param iUserObject
150: * @param iArea
151: * @param iForm
152: */
153: public void createObjectFormAssociation(Object iUserObject,
154: String iArea, ContentComponent iForm) {
155: IdentityHashMap<Object, ContentComponent> userForms = objectsForms
156: .get(sessionManager.getActiveSessionInfo());
157: userForms.put(iUserObject, iForm);
158: }
159:
160: public void removeObjectFormAssociation(Object iUserObject) {
161: // REMOVE OBJECT-FORM ASSOCIATION
162: IdentityHashMap<Object, ContentComponent> userForms = objectsForms
163: .get(sessionManager.getActiveSessionInfo());
164: userForms.remove(iUserObject);
165: }
166:
167: /**
168: * Return the form associated to a User Object.
169: *
170: * @param iUserObject
171: * @return ContentComponent instance if any, otherwise null
172: */
173: public ContentComponent getFormByObject(Object iUserObject) {
174: return getFormByObject(null, iUserObject);
175: }
176:
177: /**
178: * Return the form associated to a User Object.
179: *
180: * @param iSession
181: * User session, null to get the current active
182: * @param iUserObject
183: * @return ContentComponent instance if any, otherwise null
184: */
185: public ContentComponent getFormByObject(Object iSession,
186: Object iUserObject) {
187: if (iSession == null)
188: iSession = sessionManager.getActiveSessionInfo();
189:
190: IdentityHashMap<Object, ContentComponent> userForms = objectsForms
191: .get(iSession);
192:
193: if (userForms == null)
194: return null;
195:
196: return userForms.get(iUserObject);
197: }
198:
199: /**
200: * Return the first form of the declaring Class iClassOfObject.
201: *
202: * @param iSession
203: * User session, null to get the current active
204: * @param iClassOfObject
205: * The Class of the object
206: * @return ContentComponent instance if any, otherwise null
207: */
208: public ContentComponent getFormByClass(Object iSession,
209: Class<?> iClassOfObject) {
210: if (iSession == null)
211: iSession = sessionManager.getActiveSessionInfo();
212:
213: IdentityHashMap<Object, ContentComponent> userForms = objectsForms
214: .get(iSession);
215:
216: if (userForms == null)
217: return null;
218:
219: for (Map.Entry<Object, ContentComponent> entry : userForms
220: .entrySet()) {
221: if (entry.getKey().getClass().equals(iClassOfObject))
222: return entry.getValue();
223: }
224: return null;
225: }
226:
227: /**
228: * Return all the forms for all the active session that render POJOs of class iClass.
229: *
230: * @param iClass
231: * Class to search
232: * @return Map<SessionInfo, ContentComponent> with all entries that are handling POJOs of class iClass
233: */
234: public Map<SessionInfo, ContentComponent> getFormsByClass(
235: Class<?> iClass) {
236: Map<SessionInfo, ContentComponent> result = new HashMap<SessionInfo, ContentComponent>();
237:
238: Map<Object, ContentComponent> perSessionObjects;
239:
240: for (Map.Entry<SessionInfo, IdentityHashMap<Object, ContentComponent>> entry : objectsForms
241: .entrySet()) {
242: perSessionObjects = entry.getValue();
243: for (Map.Entry<Object, ContentComponent> formEntry : perSessionObjects
244: .entrySet()) {
245: if (formEntry.getKey() != null
246: && formEntry.getKey().getClass().equals(iClass))
247: result.put(entry.getKey(), formEntry.getValue());
248: }
249: }
250: return result;
251: }
252:
253: /**
254: * Get the instance of user class iEntityClassName. If the instance is in the user session's pool then recycle it, otherwise
255: * create a new one and insert in to the user session's pool.
256: *
257: * @param iEntityClassName
258: * User Class name of requested object
259: * @return instance of class requested
260: */
261: public Object getObject(String iEntityName) {
262: return getObject(iEntityName, null);
263: }
264:
265: /**
266: * Get the instance of user class iEntityClassName. If the instance is in the user session's pool then recycle it, otherwise
267: * create a new one and insert in to the user session's pool.
268: *
269: * @param iEntityClassName
270: * User Class name of requested object
271: * @param iEntityInstance
272: * Entity instance to assign to the object requested if is instance of ComposedEntity
273: * @return instance of class requested
274: */
275: public Object getObject(String iEntityName, Object iEntityInstance) {
276: return Controller.getInstance().getObject(iEntityName,
277: iEntityInstance);
278: }
279:
280: /**
281: * Get the instance of user class iNextClass. If the instance is in the user session's pool then recycle it, otherwise create a
282: * new one and insert in to the user session's pool. Use this method instead of getObject(String) when you know class type at
283: * compile time to benefits of static checks and future refactoring.
284: *
285: * @see #getObject(String)
286: * @param iEntityClass
287: * @return instance of class requested
288: */
289: public <T> T getObject(Class<T> iEntityClass) {
290: return getObject(iEntityClass, null);
291: }
292:
293: /**
294: * Get the instance of user class iNextClass. If the instance is in the user session's pool then recycle it, otherwise create a
295: * new one and insert in to the user session's pool. Use this method instead of getObject(String) when you know class type at
296: * compile time to benefits of static checks and future refactoring.
297: *
298: * @see #getObject(String)
299: * @param iEntityClass
300: * @param iEntityInstance
301: * Entity instance to assign to the object requested if is instance of ComposedEntity
302: * @return instance of class requested
303: */
304: public <T> T getObject(Class<T> iEntityClass, Object iEntityInstance) {
305: return (T) getObject(iEntityClass.getSimpleName(),
306: iEntityInstance);
307: }
308:
309: public void refresh(SessionInfo iSession, ContentComponent iForm) {
310: getComponent(ViewAspect.class).pushRefreshForm(iSession, iForm);
311: }
312:
313: /**
314: * Refresh a property feature and/or value.
315: *
316: * @param iUserObject
317: * The User Object of changed property
318: * @param iPropertyName
319: * The property name
320: */
321: public void refresh(Object iUserObject, String iPropertyName) {
322: refresh(null, iUserObject, iPropertyName);
323: }
324:
325: /**
326: * Refresh a property feature and/or value of iUserSession session.
327: *
328: * @param iUserSession
329: * The User Session
330: * @param iUserObject
331: * The User Object of changed property
332: * @param iPropertyName
333: * The property name
334: */
335: public void refresh(SessionInfo iUserSession, Object iUserObject,
336: String iPropertyName) {
337: List<UserObjectEventListener> listeners = Controller
338: .getInstance().getListeners(
339: UserObjectEventListener.class);
340:
341: synchronized (listeners) {
342: try {
343: SchemaClass clz = getComponent(SchemaManager.class)
344: .getClassInfo(
345: iUserObject.getClass().getSimpleName());
346: if (clz == null)
347: return;
348:
349: SchemaField field = clz.getField(iPropertyName);
350: if (field == null)
351: return;
352:
353: if (iUserSession == null)
354: iUserSession = getComponent(SessionAspect.class)
355: .getActiveSessionInfo();
356:
357: for (UserObjectEventListener listener : listeners) {
358: listener.onFieldRefresh(iUserSession, iUserObject,
359: field);
360: }
361: } catch (UserException e) {
362: log
363: .info("[ObjectContext.refresh] Cannot refresh field '"
364: + iPropertyName
365: + "' in object "
366: + iUserObject
367: + " since it not exists for current view");
368: }
369: }
370: }
371:
372: /**
373: * Return the desktop for the current user.
374: *
375: * @return Desktop instance
376: */
377: public Screen getScreen() {
378: return FormViewer.getInstance().getScreen();
379: }
380:
381: /**
382: * Return the screen for the user.
383: *
384: * @param iUserSession
385: * User session
386: * @return Desktop instance
387: */
388: public Screen getScreen(Object iUserSession) {
389: return FormViewer.getInstance().getScreen(iUserSession);
390: }
391:
392: /**
393: * Set the current screen.
394: *
395: * @param iScreen
396: */
397: public void setScreen(Screen iScreen) {
398: if (iScreen != null)
399: FormViewer.getInstance().setScreen(iScreen);
400: }
401:
402: public void close(Object iUserObject) {
403: ContentComponent form = getFormByObject(iUserObject);
404: if (form != null)
405: form.close();
406: }
407:
408: public void showComponent(Object iComponent, String iArea) {
409: FormViewer.getInstance().display(iArea, iComponent);
410: }
411:
412: /**
413: * Display the form reading information from POJO received in the current desktop, in default position.
414: *
415: * @param iContent
416: * Object instance to display
417: */
418: public void show(Object iContent) throws ViewException {
419: show(iContent, null);
420: }
421:
422: /**
423: * Display the form reading information from POJO received following the layout rules. Display the object on iWhere position in
424: * the current desktop.
425: *
426: * @param iContent
427: * @param iPosition
428: * @throws ViewException
429: */
430: public void show(Object iContent, String iPosition)
431: throws ViewException {
432: show(iContent, iPosition, null, null);
433: }
434:
435: public void show(Object iContent, String iPosition, Screen iScreen,
436: SessionInfo iSession) throws ViewException {
437: SchemaClass cls = RomaApplicationContext.getInstance().getBean(
438: SchemaManager.class).getClassInfo(
439: iContent.getClass().getSimpleName());
440:
441: SchemaObject schema = new SchemaObject(cls, iContent);
442: show(iContent, iPosition, iScreen, iSession, schema);
443: }
444:
445: /**
446: * Display the form reading information from POJO received following the layout rules. Display the object on iWhere position in
447: * the desktop received as the argument iDesktop.
448: *
449: * @param iContent
450: * Object instance to display
451: * @param iPosition
452: * Desktop position where render the object
453: * @param iScreen
454: * Desktop instance to use
455: * @throws Exception
456: */
457: public void show(Object iContent, String iPosition, Screen iScreen,
458: SessionInfo iSession, SchemaObject iSchema)
459: throws ViewException {
460: if (iScreen == null)
461: // GET THE CURRENT ONE
462: iScreen = FormViewer.getInstance().getScreen();
463:
464: if (iContent == null) {
465: if (iPosition == null)
466: // GET CURRENT AREA FOR OBJECT
467: iPosition = Controller.getInstance().getContext()
468: .getActiveArea();
469: FormViewer.getInstance().display(iPosition, iContent,
470: iScreen);
471: return;
472: }
473:
474: // SEARCH THE FORM TO VIEW BY ENTITY
475: ContentForm form = (ContentForm) getFormByObject(iSession,
476: iContent);
477: if (form == null)
478: // CREATE IT
479: form = RomaApplicationContext.getInstance().getBean(
480: FormPool.class).getForm(iSchema, null, iContent);
481:
482: if (iPosition == null)
483: // GET CURRENT AREA FOR OBJECT
484: iPosition = Controller.getInstance().getContext()
485: .getActiveArea();
486:
487: if (iSession == null
488: || iSession.equals(ObjectContext.getInstance()
489: .getComponent(SessionAspect.class)
490: .getActiveSessionInfo())) {
491: // DISPLAY NOW
492: RomaApplicationContext.getInstance().getBean(
493: ViewAspect.class)
494: .showForm(form, iPosition, iScreen);
495: form.renderContent();
496: } else
497: // PUSH CHANGES
498: getComponent(ViewAspect.class).pushShowForm(iSession, form,
499: iPosition);
500: }
501:
502: /**
503: * Validate the POJO applying the validation rules found on it.
504: *
505: * @param iPOJO
506: * The object to validate
507: */
508: public void validate(Object iPOJO) {
509: ContentForm entityForm = (ContentForm) ObjectContext
510: .getInstance().getFormByObject(iPOJO);
511: try {
512: entityForm.validateValues();
513: } catch (ValidationException ve) {
514: entityForm.handleException(ve);
515: }
516: }
517:
518: /**
519: * Get the schema object associated to the current POJO.
520: *
521: * @param iUserObject
522: * User POJO
523: * @return SchemaObject instance
524: * @throws ConfigurationNotFoundException
525: */
526: public SchemaObject getSchemaObject(Object iUserObject)
527: throws ConfigurationNotFoundException {
528: ContentComponent form = getFormByObject(iUserObject);
529: if (form == null)
530: return null;
531:
532: return form.getSchemaInstance();
533: }
534:
535: /**
536: * Return the features of the entity. The first time the features are requested, their are cloned by the original features. This
537: * allow to customize features at a User Object level without consuming memory if not necessary.
538: *
539: * @param iUserObject
540: * User Object
541: * @return DynaBean instance
542: */
543: public DynaBean getClassFeatures(Object iUserObject,
544: String iAspectName) throws ConfigurationNotFoundException {
545: SchemaObject obj = getSchemaObject(iUserObject);
546: if (obj == null)
547: return null;
548: return obj.getFeatures(iAspectName);
549: }
550:
551: public boolean setClassFeature(Object iUserObject,
552: String iAspectName, String iFeatureName,
553: Object iFeatureValue) throws ConfigurationNotFoundException {
554: // GET CURRENT VALUE
555: DynaBean features = getClassFeatures(iUserObject, iAspectName);
556: if (features == null)
557: return false;
558:
559: Object currentValue = features.getAttribute(iFeatureName);
560:
561: if (iFeatureValue == null && currentValue == null)
562: // NO CHANGES
563: return false;
564: if (iFeatureValue != null && currentValue != null)
565: if (iFeatureValue.equals(currentValue))
566: // NO CHANGES
567: return false;
568:
569: features.setAttribute(iFeatureName, iFeatureValue);
570:
571: // BROADCAST CHANGES TO ALL REGISTERED LISTENERS
572: List<SchemaFeaturesChangeListener> listeners = Controller
573: .getInstance().getListeners(
574: SchemaFeaturesChangeListener.class);
575: if (listeners != null)
576: for (SchemaFeaturesChangeListener listener : listeners) {
577: listener.signalChangeClass(iUserObject, iAspectName,
578: iFeatureName, currentValue, iFeatureValue);
579: }
580: return true;
581: }
582:
583: /**
584: * Return the features of the requested field.
585: *
586: * @param iUserObject
587: * User Object
588: * @param iFieldName
589: * The name of the field
590: * @return DynaBean instance
591: */
592: public DynaBean getFieldFeatures(Object iUserObject,
593: String iAspectName, String iFieldName)
594: throws ConfigurationNotFoundException {
595: SchemaObject obj = getSchemaObject(iUserObject);
596: if (obj == null)
597: return null;
598:
599: SchemaField field = obj.getField(iFieldName);
600: if (field != null)
601: return field.getFeatures(iAspectName);
602:
603: return null;
604: }
605:
606: public boolean setFieldFeature(Object iUserObject,
607: String iAspectName, String iFieldName, String iFeatureName,
608: Object iFeatureValue) throws ConfigurationNotFoundException {
609: // GET CURRENT VALUE
610: DynaBean features = getFieldFeatures(iUserObject, iAspectName,
611: iFieldName);
612: if (features == null)
613: return false;
614:
615: Object currentValue = features.getAttribute(iFeatureName);
616:
617: if (iFeatureValue == null && currentValue == null)
618: // NO CHANGES
619: return false;
620: if (iFeatureValue != null && currentValue != null)
621: if (iFeatureValue.equals(currentValue))
622: // NO CHANGES
623: return false;
624:
625: features.setAttribute(iFeatureName, iFeatureValue);
626:
627: // BROADCAST CHANGES TO ALL REGISTERED LISTENERS
628: List<SchemaFeaturesChangeListener> listeners = Controller
629: .getInstance().getListeners(
630: SchemaFeaturesChangeListener.class);
631: if (listeners != null)
632: for (SchemaFeaturesChangeListener listener : listeners) {
633: listener.signalChangeField(iUserObject, iAspectName,
634: iFieldName, iFeatureName, currentValue,
635: iFeatureValue);
636: }
637:
638: return true;
639: }
640:
641: /**
642: * Return the features of the requested action. The first time the features are requested, their are cloned by the original
643: * features. This allow to customize features at a User Object level without consuming memory if not necessary.
644: *
645: * @param iUserObject
646: * User Object
647: * @param iActionName
648: * The name of the action
649: * @return DynaBean instance
650: */
651: public DynaBean getActionFeatures(Object iUserObject,
652: String iAspectName, String iActionName)
653: throws ConfigurationNotFoundException {
654: SchemaObject schema = getSchemaObject(iUserObject);
655: if (schema == null)
656: return null;
657:
658: SchemaElement action = schema.getAction(iActionName);
659: if (action == null)
660: return null;
661:
662: return action.getFeatures(iAspectName);
663: }
664:
665: public boolean setActionFeature(Object iUserObject,
666: String iAspectName, String iActionName,
667: String iFeatureName, Object iFeatureValue)
668: throws ConfigurationNotFoundException {
669: // GET CURRENT VALUE
670: DynaBean features = getActionFeatures(iUserObject, iAspectName,
671: iActionName);
672: if (features == null)
673: return false;
674:
675: Object currentValue = features.getAttribute(iFeatureName);
676:
677: if (iFeatureValue == null && currentValue == null)
678: // NO CHANGES
679: return false;
680: if (iFeatureValue != null && currentValue != null)
681: if (iFeatureValue.equals(currentValue))
682: // NO CHANGES
683: return false;
684:
685: features.setAttribute(iFeatureName, iFeatureValue);
686:
687: // BROADCAST CHANGES TO ALL REGISTERED LISTENERS
688: List<SchemaFeaturesChangeListener> listeners = Controller
689: .getInstance().getListeners(
690: SchemaFeaturesChangeListener.class);
691: if (listeners != null)
692: for (SchemaFeaturesChangeListener listener : listeners) {
693: listener.signalChangeAction(iUserObject, iAspectName,
694: iActionName, iFeatureName, currentValue,
695: iFeatureValue);
696: }
697:
698: return true;
699: }
700:
701: /**
702: * Get the component from the current thread's context.
703: *
704: * @param iClass
705: * Class of the component to get.
706: * @return Component if found, otherwise null
707: */
708: public <T> T getContextComponent(Class<T> iClass) {
709: return (T) getContextComponent(iClass.getSimpleName());
710: }
711:
712: /**
713: * Get the component from the current thread's context.
714: *
715: * @param iComponent
716: * Component name to get.
717: * @return Component if found, otherwise null
718: */
719: public <T> T getContextComponent(String iComponent) {
720: T localComponent = (T) localContext.get().get(iComponent);
721: T component = null;
722:
723: List<ContextLifecycleListener> listeners = Controller
724: .getInstance().getListeners(
725: ContextLifecycleListener.class);
726: if (listeners != null)
727: for (ContextLifecycleListener listener : listeners) {
728: try {
729: component = (T) listener.onContextRead(iComponent,
730: localComponent);
731: if (component != null)
732: return (T) component;
733: } catch (Throwable t) {
734: log.error(
735: "[ObjectContext.getContextComponent] listener: "
736: + listener, t);
737: }
738: }
739:
740: return localComponent;
741: }
742:
743: /**
744: * Set a component in the thread's context.
745: *
746: * @param iClass
747: * Class of the component to set.
748: * @param iValue
749: * Component instance
750: */
751: public void setContextComponent(Class<? extends Object> iClass,
752: Object iValue) {
753: setContextComponent(iClass.getSimpleName(), iValue);
754: }
755:
756: /**
757: * Set a component in the thread's context.
758: *
759: * @param iComponentName
760: * Component name to set.
761: * @param iValue
762: * Component instance
763: */
764: public void setContextComponent(String iComponentName, Object iValue) {
765: if (iValue == null)
766: localContext.get().remove(iComponentName);
767: else
768: localContext.get().put(iComponentName, iValue);
769: }
770:
771: /*
772: * Logout current user session.
773: */
774: public void logout() {
775: // CALL CUSTOM APPLICATION CALLBACK
776: ObjectContext.getInstance().getComponent(
777: ApplicationConfiguration.class).endUserSession();
778: }
779:
780: public void onSessionCreating(SessionInfo iSession) {
781: objectsForms.put(iSession,
782: new IdentityHashMap<Object, ContentComponent>());
783: }
784:
785: public void onSessionDestroying(SessionInfo iSession) {
786: // REMOVE OBJECTS-AREA/COMPONENTS ASSOCIATION FOR CURRENT SESSION
787: IdentityHashMap<Object, ContentComponent> forms = objectsForms
788: .remove(iSession);
789: if (forms != null) {
790: if (log.isDebugEnabled())
791: log
792: .debug("[ObjectContext.onSessionDestroying] Removing components "
793: + forms.values().size());
794:
795: for (ContentComponent c : forms.values()) {
796: c.destroy();
797: }
798:
799: if (log.isDebugEnabled())
800: log
801: .debug("[ObjectContext.onSessionDestroying] Removed "
802: + forms.size()
803: + " forms for session="
804: + iSession);
805: }
806: }
807:
808: /**
809: * Get the singleton instance.
810: *
811: * @return The singleton instance.
812: */
813: public static ObjectContext getInstance() {
814: return instance;
815: }
816: }
|