// // P4Server.m // MBMenuExtra // // Created by Michael Bishop on 12/3/09. // Copyright 2009 Perforce Software. All rights reserved. // #import "NGAUtilities.h" #import "NGAAutoObserver.h" #import "NGAConditionalExecutor.h" #import "P4ServerEntry.h" #import "P4Connection.h" #import "P4Port.h" #import "P4ErrorCodes.h" #import "P4Encodings.h" #import "P4ClientApi.h" #import "P4Keychain.h" #import "P4Response.h" #import "P4ConnectionPool.h" #import "P4SpecManager.h" #import "P4User.h" #import "P4Client.h" @interface P4ServerEntry () @property (nonatomic, readwrite, copy) NSArray * users; @property (nonatomic, readwrite, retain) P4User * user; @property (nonatomic, readwrite, retain) NSError * connectionError; -(void)valueDidChangeForPortString; -(void)valueDidChangeForUsername; -(void)valueDidChangeForUsers; @end NSString * nameFromP4Port( NSString * p4port ); NSString * nameFromP4Port( NSString * p4port ) { NSRange prefix = [p4port rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]; if ( prefix.location == NSNotFound ) return nil; prefix.length = prefix.location; prefix.location = 0; return [p4port substringWithRange:prefix]; } @implementation P4ServerEntry @synthesize users = _users , connectionError = _connectionError , encoding = _encoding , username = _username , portString = _portString , user = _user ; #pragma mark -- INIT/DEALLOC -- -(id)init { if ((self = [super init]) == nil) return nil; self.portString = [P4RawConnection defaultP4Port]; self.username = [P4RawConnection defaultUsername]; [self registerAllAutoObservationMethods]; return self; } -(id)initWithCoder:(NSCoder*)coder { // if ((self = [super initWithCoder:coder]) == nil) if ((self = [super init]) == nil) return nil; self.portString = [coder decodeObjectForKey:@"p4port"]; self.username = [coder decodeObjectForKey:@"user"]; self.encoding = [coder decodeObjectForKey:@"username"]; [self registerAllAutoObservationMethods]; return self; } -(void)encodeWithCoder:(NSCoder*)coder { // [super encodeWithCoder:coder]; [coder encodeObject:self.portString forKey:@"p4port"]; [coder encodeObject:self.username forKey:@"user"]; [coder encodeObject:_encoding forKey:@"encoding"]; } -(void)dealloc { [self unregisterAllAutoObservationMethods]; [_encoding release]; [_username release]; [_portString release]; [_connectionError release]; [_users release]; [super dealloc]; } -(NSString*)description { return [NSString stringWithFormat:@"Port: %@, User: %@, Encoding: %@, Error: %@", self.portString, self.username, self.encoding, _connectionError]; } #pragma mark -- PRIVATE -- #pragma mark -- PUBLIC -- +(NSSet*)keyPathsForValuesAffectingConnection { return [NSSet setWithObjects:@"portString", @"username", nil]; } -(P4Connection*)connection { P4Connection * c = [P4Connection connectionWithPortString:self.portString user:self.username]; return c; } +(NSSet*)keyPathsForValuesAffectingSpecManager { return [NSSet setWithObjects:@"portString", @"username", nil]; } -(P4SpecManager*)specManager { return [P4SpecManager managerWithPortString:self.portString username:self.username]; } -(void)checkIfUserHasChanged { P4User * user = (P4User*)[self.specManager specOfType:@"user" identifier:self.username createIfNotFound:NO]; if ( self.user == user ) return; self.user = user; } -(void)valueDidChangeForPortString { self.users = nil; [self checkIfUserHasChanged]; [self refreshAll:self]; } -(void)valueDidChangeForUsername { [self checkIfUserHasChanged]; [self refreshAll:self]; } -(void)valueDidChangeForUsers { [self checkIfUserHasChanged]; } +(NSSet*)keyPathsForValuesAffectingPassword { return [NSSet setWithObjects:@"portString", @"username", nil]; } - (void)setPassword:(NSString*)password { [[P4Keychain sharedKeychain] setPassword:password forUser:self.username port:self.portString]; [self refreshAll:self]; } - (NSString*)password { return [[P4Keychain sharedKeychain] passwordForUser:self.username port:self.portString]; } + (NSArray*)encodings { return P4Encodings(); } - (NSArray*)encodings { return [[self class] encodings]; } + (NSSet *)keyPathsForValuesAffectingIsUnicodeEnabled { return [NSSet setWithObjects:@"connection.p4port.info", nil]; } - (BOOL)isUnicodeEnabled { return [self.connection.p4port.info objectForKey:@"unicode"] != nil; } + (NSSet *)keyPathsForValuesAffectingStatus { return [NSSet setWithObjects:@"connection.needsNewPassword", @"connection.p4port.reachable", @"connection.p4port.lastError", @"connection.p4port.refreshing", @"connectionError", nil]; } - (P4ServerStatus)status { if ( !self.connection.p4port.reachable ) return P4ServerStatusOffline; if ( self.connection.p4port.refreshing ) return P4ServerStatusConnecting; if ( self.connection.needsNewPassword ) return P4ServerStatusError; if ( self.connection.p4port.lastError ) return P4ServerStatusError; if ( self.connectionError ) return P4ServerStatusError; return P4ServerStatusOnline; } + (NSSet *)keyPathsForValuesAffectingAddressIsValid { return [NSSet setWithObjects:@"connectionError", nil]; } - (BOOL)addressIsValid { return [_connectionError code] != kP4ErrorCannotConnect; } +(NSSet*)keyPathsForValuesAffectingUserIsValid { return [NSSet setWithObjects:@"user", nil]; } - (BOOL)userIsValid { return self.user != nil; } + (NSSet *)keyPathsForValuesAffectingPasswordIsValid { return [NSSet setWithObjects:@"userIsValid", @"connectionError", nil]; } - (BOOL)passwordIsValid { return [self userIsValid] && [_connectionError code] != kP4ErrorInvalidPassword; } +(NSArray*)signatureKeys { return [NSArray arrayWithObjects:@"portString", @"username", nil]; } -(IBAction)refreshAll:(id)sender { DECLARE_UNRETAINED_SELF(P4ServerEntry*); NGAConditionalExecutor * executor = [NGAConditionalExecutor executorWithConditionalKeyPaths:[P4ServerEntry signatureKeys] object:self]; [self.connection.p4port refreshWithCompletion:^(NSError *error) { [executor conditionallyExecuteBlock:^{ if ( error ) return; unretainedSelf.users = [self.specManager specListOfType:@"user" completion:^(NSArray * speclist, NSError *error) { if ( error ) return; [executor conditionallyExecuteBlock:^{ unretainedSelf.users = speclist; for (P4Client * client in unretainedSelf.user.clients) [client refreshWithCompletion:^(NSError * error) { if ( error ) return; }]; }]; }]; for (P4Client * client in unretainedSelf.user.clients) [client refreshWithCompletion:^(NSError * error) { if ( error ) return; }]; }]; }]; } @end