ftp.nice.ch/pub/next/developer/resources/classes/misckit/MiscKit.1.10.0.s.gnutar.gz#/MiscKit/Documentation/Classes/MiscFile.rtf

This is MiscFile.rtf in view mode; [Download] [Up]

Release 0.7  Copyright ©1994, 1995 by Todd Thomas  All Rights Reserved.





MiscFile






Inherits From:	MiscGraphNode

Declared In:	misckit/MiscFile.h





Class Description

This class builds upon a MiscGraphNode so we can represent a file or hierarchy of files in the filesystem.  You can create an instance of MiscFile using initWithPath: or initWithName:inDirectory:. Additionally, only one instance is allowed for a given pathname. Therefore if you already have a MiscFile instance representing "/LocalApps" and you ask for another, initWithPath: will free the receiver and return the first instance. Reference counting was added to keep track of duplicate instances so you don't have to worry about freeing the shared instances before you are done with all of them.  As an example,  you can do the following:

localApps = [ [MiscFile alloc] initWithPath: "/LocalApps"];
localApps2 = [ [MiscFile alloc] initWithPath: "/LocalApps"];
// Both localApps and localApps2 point to the same instance, but reference count = 2.
localApps = [localApps free];
// The instance is not really freed. reference count = 1.
localApps2 = [localApps2 free];
// The instance is freed since the reference count drops to 0.

This will be taken out for MiscKit 2.x.y, which will be built upon the NeXT Foundation Kit, which has its own reference counting scheme. 

You also have considerable freedom in deciding what class your children (if you represent a directory) will be created from. First you can use setDefaultClass: classId to create all MiscFile's children as classId. You can set the class for individual subclasses of MiscFile using setDefaultClass:classId forClass:miscFileClass. This will use classId for creating children of a node that is a miscFileClass class. You can also choose your children's class based on it's filename extension. Therefore you can have *.app files instantiated from MiscAppWrapperFile, while *.bundle files being instantiated from MiscBundleFile, etc. To do this you have to register the extension with the class method registerFileClass:forExtension: You will also have to explicitly set that you would like to use the registered extensions via setCreateChildrenUsingExtensions: YES.  These methods allow great flexibility for creating a tree of nodes that have specific methods for specific kinds of files.

This looks quite complex, so an example is in order. One may want a tree of MiscFiles to represent a work directory containing NEXTSTEP projects. The work directory could be a MiscFile with sub directories of a class called called Project, the default class for Project could be set to ProjectFile to represent most files, with *.lproj represented by Localization classes, *.subproj by Project classes, *.tiff by TIFFfile classes that know how to work with images, *.[cmh] with CSourceFile classes etc. By careful registration of default classes with MiscFile, all of this can happen automatically. This is a very powerful method for creating an object that not only represents the directory tree, but knows how to do 'stuff' with each kind of file.

Here's some example code that will acheive this assuming that the classes above have been defined.

// We need to do this somewhere, -appDidInit  some -awakeFromNib or +initialize is good
- appDidInit:sender
	{
	....
	// We want the top level (work directory) to have children of class Project
	[MiscFile setDefaultClass:[Project class] forClass:[MiscFile class]];
	
	// We want all project files to be of class ProjectFile unless they have a known extension
	[MiscFile setDefaultClass:[ProjectFile class] forClass:[Project class]];
	
	// *.subproj are SubProject class
	[MiscFile registerFileClass:[Project class] forExtension:"subproj"];
	
	// *.lproj are Localization class
	[MiscFile registerFileClass:[Localization class] forExtension:"subproj"];
	
	// *.tiff are TIFFfile class
	[MiscFile registerFileClass:[TIFFfile class] forExtension:"tiff"];
	...
	}
	
Once this is done, doing something like

theWorkDirectory = [[MiscFile alloc] initWithPath:aWorkDir];

will create the appropriate classes for each file in the directory tree without further work whenever children are loaded.

Oh, and thanks very much to all the people who contributed ideas for this class and it's categories.... Bill Bumgarner, Thomas Engel, Daniel Green, David Hunt, Frederic Stark, Alastair Thomson, Georg Tuparev, Don Yacktman, and Stephan Wacker.  If I've missed anyone, I apologize.  Enjoy the classes and if you find a bug or have a suggestion, please let me know.

Be sure to also read the documentation for the various MiscFile categories (Creation, Info, Modification, Searching, and UNIX).







Instance Variables

char *path;
struct stat *st;
short errorCode;
short refCount;
struct __mfFlags
{
	unsigned int childrenLoaded:1;
	unsigned int useExtensions:1;
	unsigned int displayAsLeaf:1;
	unsigned int childrenInherit:1;
	unsigned int visited:1;
	unsigned int enableCaching:1;
	unsigned int lastStat:1;
 }



path	The pathname that the MiscFile represents.

st	Stat information for the file.

errorCode	A global error code for file information errors (something like errno).

refCount	Keep track of our instances.

mfFlags.childrenLoaded	Have our children been loaded yet.

mfFlags.useExtensions	Whether the children's filename extensions should determine their class.

mfFlags.displayAsLeaf	Give non-leaf nodes the choice to look like they are leaf nodes.

mfFlags.childrenInherit	Allows children to inherit attributes from their parents upon creation.

mfFlags.visited	Stops circular references when searching through MiscFile hierarchies.

mfFlags.enableCaching	Should stat the file every time or just use information we already have?

mfFlags.lastStat	Which function, lstat or stat represents the information in the ivar st?






Method Types

Setting a child's class	+ lookupClassForFilename:
	+ registerFileClass:forExtension:
	+ setDefaultFileClass:
	+ setDefaultFileClass:forClass:

Creating files that really exist	+ isPathValid:

Class delegate	+ classDelegate
	+ setClassDelegate

Initialization	- initWithName:inDirectory:
	- initWithPath:
	± free

Querying 	- fullPath
	- filename
	- extension

Attributes 	- setLeaf:
	- displayAsLeaf
	- setDisplayAsLeaf:

Children inheriting attributes 	-childrenInherit
	- setChildrenInherit
	- passOnTraits

Dealing with children	- children
	± updateChildren
	± loadChildrenFromFilesystem
	- childrenLoaded
	- _childrensClassGivenFilename:
	- createChildrenUsingExtensions
	- setCreateChildrenUsingExtensions:





Class Methods

classDelegate
+ classDelegate

Returns the class delegate.  I needed something like this for the searching category and thought that there could be other uses for a single delegate for all the MiscFiles.

See also:  + setClassDelegate:




isPathValid:
+ (BOOL)isPathValid: (const char *)fullPath

Stats (stat(2)) the given fullPath to make sure that it does indeed exist in the filesystem. This is used because you are not allowed to create any instances for which fullPath is not a valid system filename. Returns YES if the fullPath does exist, else NO. On the other hand if you wanted a subclass (or this class via a category) to circumvent this behavior, you could just override this method to return YES no matter what pathname is given to it.




lookupClassForFilename:
+ lookupClassForFilename:(char *)filenameOrPath

Returns the class that is associated with the extension of the filename or full pathname. This would have had to been set earlier with +registerFileClass:forExtension:. If the parameter's extension is not registered, nil is returned.  

See also:  + registerFileClass:forExtension:




registerFileClass:forExtension:
+ registerFileClass: classId
forExtension:(const char *)extension

Allows you to specify the class a child is instantiated from depending upon it's filename extension. You can then use lookupClassForFilename: to return the class that matches the given extension. If you wish to use extensions to determine a new child's class for a given instance, you must also call setCreateChildrenUsingExtensions: YES, because the default is NO.

See also:   + lookupClassForFilename:




setClassDelegate:
+ setClassDelegate: aDelegate

Sets the delegate for all MiscFile classes. This is really here for future expansion. If anyone makes up any categories that need to consult some object (like my file searching categories) or send notification messages different from the announcer in MiscGraphNode, this may just do the trick.

See also:   + classDelegate




setDefaultFileClass:
+ setDefaultFileClass: classId

Another way besides registering extensions to create children of different classes, is to set a default class that the children will be instantiated from. Therefore the parent can be a MiscFile and all the children can be instantiated from MiscBehavingFiles. If you wish to use the same class as the parent, which is the default, call this method and pass it nil. 

See also:   + setDefaultFileClass:forClass:,  + registerFileClass:forExtension:

setDefaultFileClass:forClass:
+ setDefaultFileClass: classId
forClass: miscFileClass


If you want different subclasses of MiscFile to use different default classes for their children, use this method. The classId is stored in a global hash table with miscFileClass as the key. If there is no entry in the table for a particular class, then the class used by setDefaultFileClass:  is used if it has been set, otherwise the objects own class is used. 
 
See also:   + setDefaultFileClass:,  + registerFileClass:forExtension:



Instance Methods

children
-  children

Overridden from MiscGraphNode to load the node's children from the filesystem when asked. Returns the list of children. Children are loaded only upon demand. When children are newly loaded, an announcement of either didAddChild: or didAddChildren: will be sent to all the node's users and listeners via MiscGraphNode's announcer object. Also when the filesystem is updated by using updateChildren, announcements will be made if to reflect any changes (new files or less files). See MiscGraphNode for the types of announcements.

See also:  ± loadChildrenFromFilesystem




childrenInherit
-  (BOOL)childrenInherit

Returns whether newly created children will inherit some of their parent's attributes.

See also:  ± setChildrenInherit:,  ± passOnTraits:




childrenLoaded
-  (BOOL)childrenLoaded

Returns YES if the node's children have already been loaded. This method is needed because the children are loaded lazily.

See also:  - children




_childrensClassGivenFilename:
-  _childrensClassGivenFilename:(const char *)filenameOrPath

An internally used method. Returns the class that the node's child, with the given filename or pathname, should be instantiated from. It checks if we should use it's extension to determine it's class. If not, or an extension match is not found, then the default class is returned if it is not nil. Otherwise the class of the parent is returned.

See also:   +setDefaultFileClass:,  +registerFileClass:forExtension:




createChildrenUsingExtensions
-  (BOOL)createChildrenUsingExtensions

Returns YES if this instance should attempt to use the child's filename extension when determining what class the child should be instantiated from. The default is NO.

See also:  +registerFileClass:forExtension:,  + lookupClassForFilename:




displayAsLeaf
-  (BOOL)displayAsLeaf

This method allows non-leaf nodes to show up in a browser as leaf nodes. This of course if useful for app, bundles and nib file wrappers.  This method returns YES if the node is a leaf node. If the node is a non-leaf, then it will return whether it would like to look like a leaf. The default is NO. 

See also:  ± setDisplayAsLeaf:




extension
-  (const char *)extension

Returns the extension, which is stripped off the instance variable path. NULL is returned if the pathname has no extension.

See also:  ± fullPath,  ± filename




free
- free

If decrementing the instance's reference count does not bring it to zero, then nothing is freed and nil is returned. Otherwise all resources are freed and nil is returned.



filename
-  (const char *)filename

Returns the filename that the object represents. The filename is derived from the instance variable path. 

See also:  ± extension,  ± fullPath




fullPath
-  (const char *)fullPath

Returns the full pathname of the file that the MiscFile represents.

See also:  ± extension,  ± filename




initWithName:inDirectory:
-  initWithName:(const char *)filename
inDirectory:(const char *)directory

Just concatenates directory and filename to create the full pathname and calls the designated initializer initWithPath:.

See also:  ± initWithPath




initWithPath:
-  initWithPath:(const char *)fullPath

The designated initializer. For each pathname in the filesystem there can only exist one instance of this class. Therefore if an instance of "/LocalApps" already exists and you ask for another, you will get a pointer to the first instead of two separate instances.  Also if fullPath does not exist,  the instance is freed and nil is returned. Otherwise self is returned. If you subclass MiscFile and initWithPath:, make sure that [super initWithPath:] returns a valid value (not nil) before continuing with your initialization.

See also:  ± initWithName:inDirectory:




loadChildrenFromFilesystem
- loadChildrenFromFilesystem

Loads and instantiates all the node's children. This is here just in case you would like to load the children differently or more efficiently than I did. If you do override this method make sure that you take into account which class the newly read-in children should be instantiated from. Returns self.

See also:  ± children




passOnTraits:
- passOnTraits: parent

If childrenInherit returns YES, then some attributes of the parent will be passed onto the children when they are created. Currently the only attribute that is passed on is createChildrenUsingExtensions, so that the children will continue to use filename extensions to determine their children's class if their parents did. If you add more traits (in a subclass) that would be useful to pass onto your children, this would be the method to override and pass them on. Returns self.

See also:  ± childrenInherit,  ± setChildrenInherit:




setChildrenInherit:
- setChildrenInherit: (BOOL)inherit

Sets whether children will inherit attributes (via passOnTraits) from their parent when they are created. The default is YES. Returns self.

See also:  ± childrenInherit,  ± passOnTraits:




setCreateChildrenUsingExtensions:
-  setCreateChildrenUsingExtensions:(BOOL)useExts

Set to YES if you would like the class of any new children to be determined by the child's filename extension. It is NO by default.

See also:  ± createChildrenUsingExtensions




setDisplayAsLeaf:
-  setDisplayAsLeaf:(BOOL)asLeaf

Set to YES if you would like a non-leaf node to appear to be a leaf node. The default is NO. Returns self.

See also:  ± displayAsLeaf




setLeaf:
-  setLeaf:(BOOL)isALeaf

Overridden from MiscGraphNode since it doesn't make sense to allow an instance of MiscFile to alternate between a leaf and non-leaf. It is either a directory or it isn't. Returns self (and does nothing else).

See also:  ± isLeaf  (MiscGraphNode)










These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.