#include "WOComponentFault.h"
#include "common.h"
#include <NGExtensions/NGBundleManager.h>
-#include <EOControl/EOControl.h>
+#import <EOControl/EOControl.h>
+#ifdef MULLE_EO_CONTROL
+#import <EOControl/EOKeyValueUnarchiver.h>
+#endif
#include <NGExtensions/NSString+Ext.h>
@interface WOContext(ComponentStackCount)
static BOOL debugOn = NO;
static BOOL debugComponentAwake = NO;
static BOOL debugTemplates = NO;
+static BOOL debugTakeValues = NO;
static BOOL abortOnAwakeComponentInCtxDealloc = NO;
static BOOL abortOnMissingCtx = NO;
static BOOL wakeupPageOnCreation = NO;
ud = [NSUserDefaults standardUserDefaults];
lm = [NGLoggerManager defaultLoggerManager];
-
+
WOComponentClass = [WOComponent class];
NSDateClass = [NSDate class];
perfLogger = [lm loggerForDefaultKey:@"WOProfileElements"];
debugOn = [WOApplication isDebuggingEnabled];
debugComponentAwake = [ud boolForKey:@"WODebugComponentAwake"];
+
+ if ((debugTakeValues = [ud boolForKey:@"WODebugTakeValues"]))
+ NSLog(@"WOComponent: WODebugTakeValues on.");
+
abortOnAwakeComponentInCtxDealloc =
[ud boolForKey:@"WOCoreOnAwakeComponentInCtxDealloc"];
}
- (id)initWithContext:(WOContext *)_ctx {
[self _setContext:_ctx];
if ((self = [self init])) {
- if (self->context)
+ if (self->context != nil)
[self ensureAwakeInContext:self->context];
else {
[self warnWithFormat:
if (debugComponentAwake)
[self debugWithFormat:@"0x%08X ensureAwakeInContext:0x%08X", self, _ctx];
- if (self->context == nil) [self _setContext:_ctx];
+ /* sanity check */
+
+ if (self->componentFlags.isAwake) {
+ if (self->context == _ctx) {
+ if (debugComponentAwake)
+ [self debugWithFormat:@"0x%08X already awake:0x%08X", self, _ctx];
+ return;
+ }
+ }
+
+ /* setup globals */
+
+ if (self->context == nil) [self _setContext:_ctx];
if (self->application == nil) self->application = [_ctx application];
if ((self->session == nil) && [_ctx hasSession])
WOComponent *child;
children = [self->subcomponents objectEnumerator];
- while ((child = [children nextObject]))
+ while ((child = [children nextObject]) != nil)
[child _awakeWithContext:_ctx];
}
return self->wocName;
}
- (NSString *)frameworkName {
- return [[NGBundle bundleForClass:[self class]] bundleName];
+ NSBundle *cbundle;
+
+ cbundle = [NGBundle bundleForClass:[self class]];
+ if (cbundle == [NSBundle mainBundle])
+ return nil;
+
+ return [cbundle bundleName];
}
- (NSString *)path {
NSArray *languages = nil;
#if 0 // the component might not yet be awake !
- languages = [self hasSession]
- ? [[self session] languages]
- : [[[self context] request] browserLanguages];
+ languages = [[self context] resourceLookupLanguages];
#endif
return [[self resourceManager]
return [@"/" stringByAppendingString:[self name]];
}
-- (WOApplication *)application {
+- (id)application {
if (self->application == nil)
return (self->application = [WOApplication application]);
return self->application;
}
- (id)existingSession {
- if (self->session)
+ if (self->session != nil)
return self->session;
if ([[self context] hasSession])
return nil;
}
-- (WOSession *)session {
+- (id)session {
if (self->session == nil) {
if ((self->session = [[self context] session]) == nil) {
[self debugWithFormat:@"could not get session object from context %@",
}
- (void)setCachingEnabled:(BOOL)_flag {
- self->componentFlags.reloadTemplates = _flag ? NO : YES;
+ self->componentFlags.reloadTemplates = _flag ? 0 : 1;
}
- (BOOL)isCachingEnabled {
- return (self->componentFlags.reloadTemplates == NO) ? YES : NO;
+ return (!self->componentFlags.reloadTemplates) ? YES : NO;
}
-- (WOComponent *)pageWithName:(NSString *)_name {
- NSArray *languages = nil;
+- (id)pageWithName:(NSString *)_name {
+ NSArray *languages;
WOResourceManager *rm;
WOComponent *component;
- languages = [self hasSession]
- ? [(WOSession *)[self session] languages]
- : [[[self context] request] browserLanguages];
-
- rm = [self resourceManager];
-
+ languages = [[self context] resourceLookupLanguages];
+ rm = [self resourceManager];
+
/*
Note: this API is somewhat broken since the component expects the
-initWithContext: message for initialization yet we pass no
NSArray *langs;
IS_DEPRECATED;
- langs = [self hasSession]
- ? [(WOSession *)[self session] languages]
- : [[[self context] request] browserLanguages];
+ langs = [[self context] resourceLookupLanguages];
return [[[self application]
resourceManager]
- (void)setParent:(WOComponent *)_parent {
self->parentComponent = _parent;
}
-- (WOComponent *)parent {
+- (id)parent {
return self->parentComponent;
}
}
- (NSString *)pathForResourceNamed:(NSString *)_name ofType:(NSString *)_ext {
- NSFileManager *fm = [NSFileManager defaultManager];
- NSEnumerator *languages = nil;
- NSString *language = nil;
+ NSFileManager *fm;
+ NSEnumerator *languages;
+ NSString *language;
BOOL isDirectory = NO;
- NSString *cpath = [self path];
+ NSString *cpath;
if (_ext) _name = [_name stringByAppendingPathExtension:_ext];
- if (cpath == nil) {
+ if ((cpath = [self path]) == nil) {
[self warnWithFormat:@"no path set in component %@", [self name]];
return nil;
}
+
+ fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:cpath isDirectory:&isDirectory]) {
[self warnWithFormat:@"component directory %@ does not exist !", cpath];
return nil;
[self warnWithFormat:@"component path %@ is not a directory !", cpath];
return nil;
}
+
+ /* check in language projects */
- // check in language projects
-
- languages = [[(WOSession *)[self session] languages] objectEnumerator];
- while ((language = [languages nextObject])) {
- language = [[cpath stringByAppendingPathComponent:
- [language stringByAppendingPathExtension:@"lproj"]]
- stringByAppendingPathExtension:_name];
+ languages = [self hasSession]
+ ? [[(WOSession *)[self session] languages] objectEnumerator]
+ : [[[[self context] request] browserLanguages] objectEnumerator];
+
+ while ((language = [languages nextObject]) != nil) {
+ language = [language stringByAppendingPathExtension:@"lproj"];
+ language = [cpath stringByAppendingPathComponent:language];
+ language = [language stringByAppendingPathExtension:_name];
if ([fm fileExistsAtPath:language])
return language;
}
-
- // check in component
+
+ /* check in component */
cpath = [cpath stringByAppendingPathComponent:_name];
if ([fm fileExistsAtPath:cpath])
return cpath;
/* template */
-- (WOElement *)templateWithHTMLString:(NSString *)_html
++ (WOElement *)templateWithHTMLString:(NSString *)_html
declarationString:(NSString *)_wod
languages:(NSArray *)_languages
{
declarationString:(NSString *)_wod
{
IS_DEPRECATED;
- return [self templateWithHTMLString:_html
- declarationString:_wod
- languages:[(WOSession *)[self session] languages]];
+ return [[self class] templateWithHTMLString:_html
+ declarationString:_wod
+ languages:[(WOSession *)[self session] languages]];
}
- (WOElement *)templateWithName:(NSString *)_name {
return nil;
}
- languages = [self hasSession]
- ? [(WOSession *)[self session] languages]
- : [[[self context] request] browserLanguages];
-
- tmpl = [resourceManager templateWithName:_name languages:languages];
+ languages = [[self context] resourceLookupLanguages];
+ tmpl = [resourceManager templateWithName:_name languages:languages];
+
if (debugTemplates) [self debugWithFormat:@"found template: %@", tmpl];
return tmpl;
}
- (WOElement *)_woComponentTemplate {
WOElement *element;
- if ((element = _getExtraVar(self, @"__wotemplate")))
+ // TODO: move to ivar?
+ if ((element = _getExtraVar(self, @"__wotemplate")) != nil)
return element;
return [self templateWithName:[self name]];
}
- (BOOL)synchronizesVariablesWithBindings {
- return YES;
+ return [self isStateless] ? NO : YES;
}
- (void)setValue:(id)_value forBinding:(NSString *)_name {
/* OWResponder */
-- (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c{
+- (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c {
+ if (debugTakeValues)
+ [self debugWithFormat:@"%s: default says no.", __PRETTY_FUNCTION__];
return NO;
}
- (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
WOElement *template = nil;
+ if (debugTakeValues)
+ [self debugWithFormat:@"take values from rq 0x%08X", _req];
+
NSAssert1(self->componentFlags.isAwake,
@"component %@ is not awake !", self);
[self _setContext:_ctx];
template = [self _woComponentTemplate];
- if (template == nil)
+ if (template == nil) {
+ if (debugTakeValues)
+ [self debugWithFormat:@"cannot take values, component has no template!"];
return;
-
+ }
+
if (template->takeValues) {
template->takeValues(template,
@selector(takeValuesFromRequest:inContext:),
#if DEBUG && 0
[self debugWithFormat:@"KVC: accessed the component variable %@", _key];
#endif
- if ((value = [self objectForKey:_key]))
+ if ((value = [self objectForKey:_key]) != nil)
return value;
return nil;
- (void)setValue:(id)_value forUndefinedKey:(NSString *)_key {
// Note: this is not used on libFoundation, insufficient KVC implementation
+
+#if DEBUG && 0
+ [self logWithFormat:@"KVC: set the component variable %@: %@",_key,_value];
+#endif
if (_value == nil) {
#if 0
@"storing <nil> value in component variable %@", _key];
#endif
- if ([self->wocVariables objectForKey:_key])
+ if ([self->wocVariables objectForKey:_key] != nil)
[self setObject:nil forKey:_key];
return;
}
}
#endif
-
[self setObject:_value forKey:_key];
}
+
- (id)valueForUndefinedKey:(NSString *)_key {
// Note: this is not used on libFoundation, insufficient KVC implementation
#if DEBUG && 0
[self debugWithFormat:@"KVC: accessed the component variable %@", _key];
#endif
+
return [self objectForKey:_key];
}
- (id)unarchiver:(EOKeyValueUnarchiver *)_archiver
objectForReference:(id)_keyPath
{
+ /*
+ This is used when a .woo file is unarchived. Eg datasources contain
+ bindings in the archive:
+
+ editingContext = session.defaultEditingContext;
+
+ The binding will evaluate against the component during loading.
+ */
return [self valueForKeyPath:_keyPath];
}
return str;
}
-@end /* WOComponent */
-
-@implementation WOComponent(Statistics)
+/* Statistics */
- (NSString *)descriptionForResponse:(WOResponse *)_response
inContext:(WOContext *)_context
return [self name];
}
-@end /* WOComponent(Statistics) */
-
-@implementation WOComponent(AdvancedBindingAccessors)
+/* AdvancedBindingAccessors */
- (void)setUnsignedIntValue:(unsigned)_value forBinding:(NSString *)_name {
[self setValue:[NSNumber numberWithUnsignedInt:_value] forBinding:_name];
}
#endif
-@end /* WOComponent(AdvancedBindingAccessors) */
+@end /* WOComponent */