How to find entries?

Tags ( )

I have a couple questions about how to best find entries so that a plugin can use or process them.

1. How can I find (get a pointer to) an entry if I have it's path? e.g. root/mGTD/Archive/archiveFile

2. How can I find all entries with any value for "dueDate"

3. all entries with the "customData" column containing the string @"test".

thanks,
Jeff

EDIT: just to clarify: in the first example I would indeed be looking for an entry, but in the second two, I assume that it would instead be entryData objects that would be returned.

1. How can I find (get a

1. How can I find (get a pointer to) an entry if I have it's path? e.g. root/mGTD/Archive/archiveFile

What are you going to use this for? If you are trying to store a reference to an entry it's better to use entry ID's. Anyway to get the entry for a path you'll need to do a manual search. Start with the root entry and iterator over its children looking for a child that matches the first path element name, and continue that process for the found child until you have processed all path elements.

2. How can I find all entries with any value for "dueDate"

You'll need to use CoreData. Here's how to setup a fetch and get the results. If you want to display a live fetchRequest in the entries view you'll also need to look at MIEntryLiveFetchRequestProtocol, but I don't think that's what you are asking. I haven't run this code, but assuming I copied everything correctly that is what you need to get all Entries that have a dueDate set.


NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entryData.dueDate != nil"];
NSManagedObjectContext *managedObjectContext = [moriDocument managedObjectContext];
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
NSError *fetchError = nil;
NSArray *fetchResults = nil;

@try {
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Entry" inManagedObjectContext:managedObjectContext]];
[fetchRequest setPredicate:predicate];
fetchResults = [managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
} @catch (NSException *e) {
logErrorWithException(@"failed executeFetchRequest", e);
}

3. all entries with the "customData" column containing the string @"test".

You'll also need to use CoreData for this. Use the above code, but change the predicate to:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entryData.customData contains %@", @"test"];

or

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entryData.customData like %@", @"*test*"];

I'm not entirely sure about difference is between the like and contains predicates in this case. I have the impression that contains is faster, but it also doens't seem to work in some cases. Like always seems to work.

entry paths

Thanks for the code sample; I'm sure it saved me untold searching and frustration.

1. How can I find (get a pointer to) an entry if I have it's path? e.g. root/mGTD/Archive/archiveFile
What are you going to use this for?

For note-chan I was going to let the user set a path to which entry they wanted to use as an inbox, and for mGTD I wanted to find the entries that I would use for storing .reminders, calendars, and archived entries. Of course I'd like to use entry ID's but if the user cuts and pastes the mGTD folder into a new doc, I wont know what those new entry IDs are, so I was going to search for the files on open.

on an unrelated note: if I create an NSDate and store it in a column, does the entry or Mori retain the object, so that I can autorelease it in the method that creates and stores it?

Thanks,
Jeff

why are these set up to

why are these set up to return entries? Since the string is part of the entryData wouldn't it be more natural to fetch the entryData objects?

Would it be as simple as taking the "entryData" out of the key path in the predicate, and changing "Entry" to "EntryData" in the fetch?

Yes. That seems to work.

Yes. That seems to work.

should "predicate" above

should "predicate" above also be autoreleased? or at least released at the end of the method?

No. The method

No. The method predicateWithFormat: already autoreleases it. In general the only time you need to worry about releasing (or autoreleasing) an object is when your either create it with alloc or retain it.

Ok. It should be simple but

Ok. It should be simple but I have the hardest time keeping track of the retains and releases.

Thanks,
Jeff

Could I be causing problems

Could I be causing problems by running a fetch before the notebook has a chance to load it's entries.
When I init by controller object I wanted to fetch references to certain entries that I'll need so I run searches similar to the ones you outlined above, but it seems to cause my entryDelegateExtension to become re-initialized. It seems to keep sending init messages until there is no longer a data returned from the fetch.
Is there a way that I could find out that the document data has fully loaded and would be ready for a fetch request?

Thanks
Jeff

This is the console output

2006-04-27 02:20:09.560 Mori[13371] received message to init MGEntryDelegateExtension
2006-04-27 02:20:09.561 Mori[13371] initing MGEntryDelegateExtension
2006-04-27 02:20:09.561 Mori[13371] initing gtdController
2006-04-27 02:20:09.589 Mori[13371] Admin Entries: (
(entity: EntryData; id: 0x14821c0 ; data: ),
(entity: EntryData; id: 0x1482010 ; data: )
)
2006-04-27 02:20:09.589 Mori[13371] test
2006-04-27 02:20:09.589 Mori[13371] test2
2006-04-27 02:20:09.590 Mori[13371] received message to init MGEntryDelegateExtension
2006-04-27 02:20:09.590 Mori[13371] initing MGEntryDelegateExtension
2006-04-27 02:20:09.590 Mori[13371] initing gtdController
2006-04-27 02:20:09.600 Mori[13371] Admin Entries: (
(entity: EntryData; id: 0x14821c0 ; data: {
GTD = admin;
attachmentCount = nil;
characterCount = 22;
checkbox = 0;
comment = nil;
context = nil;
creationDate = 2006-02-09 00:05:02 -0800;
dateDue = nil;
dateLastCompleted = nil;
descendantCount = nil;
dueDate = nil;
encrypted = nil;
entryDataID = 86;
flagged = nil;
hasNoteText = 1;
isFetchRequest = 0;
joinedEntries = "";
kind = "com.apple.rtfd";
label = nil;
lead = nil;
locked = 0;
modificationDate = 2006-02-11 22:54:04 -0800;
note = 0x1489b40 ;
onComplete = nil;
paragraphCount = 1;
read = 1;
recur = nil;
starRating = 0;
tags = "";
title = Calendar;
userInfo = nil;
wordCount = 4;
}),
(entity: EntryData; id: 0x1482010 ; data: )
)

Could I be causing problems

Could I be causing problems by running a fetch before the notebook has a chance to load it's entries.

I'm not sure, I think it would be best if you send me the code to look at.

Also what do people think about a public subversion repository hosted on the hogbaysoftware site. That would make it easier to share code? If it sounds like a good idea I'll set one up.

Jesse

Thanks I sent it. I had been

Thanks I sent it.

I had been thinking about asking you to set up a user section under the subversion repository. It might make it easier for users to collaborate on plugins or revive abandoned ones.

enumerators


Anyway to get the entry for a path you'll need to do a manual search. Start with the root entry and iterator over its children looking for a child that matches the first path element name, and continue that process for the found child until you have processed all path elements.

I assume that the easiest way to do this is with the "depthFirstEnumerator" or the "breadthFirstEumerator."

You only care about an

You only care about an entries direct children when processing each element in the path. So I think instead of using the "depthFirstEnumerator" or "breadthFirstEumerator" you really only need to use the "childEnumerator". The algorithm would look something like this:


- (MIEntry *)entryForPath:(NSString *)path container:(MIEntry)container {
if (path pathComponents == 0) return container;

NSString *childName = [path firstPathComponent];

for each child in the container
if child title == childName
return [self entryForPath:[path stringByDeletingFirstPathComponent]] container:child];
end
end

return nil; // didn't find match
}

Not I've made up some method names and typed pseudo code here, but hopefully you can follow the logic.

Thanks for the example, I'll

Thanks for the example, I'll used it to find entries for the path. This time I was trying to find all descendents of an entry that possessed a certain tag.

Can you see any problems with this code, (it seems to work):

NSPredicate *adminPredicate = [NSPredicate predicateWithFormat:@"entryData.GTD like %@", adminString];
NSEnumerator *enumerator = [mGTDEntry breadthFirstEnumerator:adminPredicate];
id nextEntry;
NSMutableDictionary *tempDict = [NSMutableDictionary dictionaryWithCapacity:10]; while ( nextEntry = [enumerator nextObject]){
NSLog(@"adding an admin entry to dict");
[tempDict setObject:nextEntry forKey:[[nextEntry entryData] title]]; }

Always, thanks for your help,
Jeff

[PS shouldn't the enumerators be "descendentsBreadthFirstEnumerator" and "descendentsDepthFirstEnumerator"]

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.