Cocoa Tip: Filtering NSArray using NSPredicate

January 13th, 2010 vira Posted in Computer science, cocoa 1 Comment »

Today I had a small task in one of my projects – to get subset of elements from NSArray. I’ve already started writing all this NSEnumerator-s stuff (need to support 10.4) when I remembered about NSPredicator. So, instead of iterating over an array and finding elements that satisfy some condition and adding them to some output array you just need to create predicate and filter your input array with it. Here is the sample code:

1
2
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"storeState == 1"];
NSArray  *outputArray = [inputArray filteredArrayUsingPredicate:predicate];

Predicates language seems to be very powerful and simple. But I can’t tell you anything about performance, need to investigate.

Further reading: Apple Predicates Programming Guide


Using Google AJAX search API in Cocoa

January 8th, 2010 vira Posted in Computer science, mac 2 Comments »

Sometimes it’s needed to allow user to find some information in the Web, without interrupting he/she from working with your application. In this small article I’ll describe simple solution to fulfill this task.
As for today, search = Google and I’m going to implement search using it. I’ve implemented category for Cocoa’s NSArray class for creating array of dictionaries. Each dictionary represents a search results. You can define where to search (web, news, video) etc and how many results to return. This code requires JSON Framework by Stig Brautaset

Here is the code of the main search method. The full project can be downloaded here (XCode 3.2, JSON Framework included)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
+ (NSArray *)arrayWithSearchFor:(NSString *)query type:(NSString *)searchType range:(NSRange)range
{
    if (range.location > 56) {
    	NSLog(@"Error while searching in Google : start must be in range [0;56]");
    	return nil;
    }
 
    NSMutableArray *results = [NSMutableArray array];
    SBJSON *parser = nil;
    NSString *json_string = nil;
    NSUInteger i = range.location;
 
    while (i < range.length + range.location) {
        @try {
    	    NSURL *url = [NSURL URLWithString:[BASE_URL stringByAppendingFormat:@"%@?v=%@&q=%@&start=%i", searchType, @"1.0", query, i]];
            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                        cachePolicy:NSURLRequestReloadIgnoringCacheData
                                        timeoutInterval:120];
            NSError *error = nil;
            NSURLResponse *response = nil;
            NSData *searchResults = [NSURLConnection sendSynchronousRequest:request
                                         returningResponse:&response
                                        error:&error];
            if (!searchResults) {
                        @throw [NSException exceptionWithName:@"Failed to search cuz: %@" reason:[error description] userInfo:nil];
            }
            //parse results
            parser = [[SBJSON alloc] init];
            json_string = [[NSString alloc] initWithData:searchResults encoding:NSUTF8StringEncoding];
 
            //NSLog(@"Raw JSON result %@", json_string);
            NSDictionary *allResult = [parser objectWithString:json_string error:&error];
            if (!allResult || [allResult isKindOfClass:[NSNull class]]) {
                    @throw [NSException exceptionWithName:@"Failed to parse all results JSON" reason:[error description] userInfo:nil];
            }
            if (![[allResult objectForKey:@"responseStatus"] isEqualToNumber:[NSNumber numberWithInt:200]]) {
                @throw [NSException exceptionWithName:[allResult objectForKey:@"responseStatus"] reason:[allResult objectForKey:@"responseDetails"] userInfo:nil];
            }
            allResult = [allResult objectForKey:@"responseData"];
            if (!allResult || [allResult isKindOfClass:[NSNull class]]) {
                @throw [NSException exceptionWithName:@"Failed to parse responseData" reason:[error description] userInfo:nil];
            }
            NSArray *newResults = [allResult objectForKey:@"results"];
            if (!newResults) {
                @throw [NSException exceptionWithName:@"Failed to parse results" reason:[error description] userInfo:nil];
            }		
 
            [results addObjectsFromArray:newResults];
            i += SMALL_RESULT_SET;
        } @catch (NSException * e) {
            NSLog(@"Exception during searching in Google: %@", e);
        } @finally {
            [parser release];
            [json_string release];
        }
    }
    return results;
}
 
+ (NSArray *)arrayWithWebSearchFor:(NSString *)query range:(NSRange)range
{
    return [[self class] arrayWithSearchFor:query type:WEB_URL range:range];
}

And the sample usage:

1
2
3
4
5
NSArray *results = [NSArray arrayWithWebSearchFor:@"apple" range:NSMakeRange(0, 5)];
    NSLog(@"Search finished, found %i", [results count]);
    for (NSDictionary *result in results) {
        NSLog(@"Url = %@",  [result objectForKey:@"url"]);
    }

In this sample code I’ve searched for “apple” and got the following results:

2009-10-13 01:18:40.638 iGoogle[63665:a0f] Url = http://en.wikipedia.org/wiki/Apple_Inc.
2009-10-13 01:18:40.641 iGoogle[63665:a0f] Url = http://www.info.apple.com/
2009-10-13 01:18:40.641 iGoogle[63665:a0f] Url = http://www.crunchbase.com/company/apple
2009-10-13 01:18:40.642 iGoogle[63665:a0f] Url = http://developer.apple.com/
2009-10-13 01:18:40.642 iGoogle[63665:a0f] Url = http://apple.slashdot.org/
2009-10-13 01:18:40.642 iGoogle[63665:a0f] Url = http://finance.yahoo.com/q%3Fs%3DAapl
2009-10-13 01:18:40.644 iGoogle[63665:a0f] Url = http://support.apple.com/batteryprogram/
2009-10-13 01:18:40.644 iGoogle[63665:a0f] Url = http://topics.nytimes.com/topics/news/business/companies/apple_computer_inc/index.html

This code has never been used in production, so use on your own risk ;-)


XCode tips

March 31st, 2009 vira Posted in Computer science, mac No Comments »

Here will be short list of the XCode hotkeys most used by me. I’ll try to update it periodically.

  • Switch to header/source file – Opt+Cmd+Up
  • Show Console – Shift+Cmd+R
  • Move to the next argument in Code Completion – Control+slash
  • Jump to definition – Cmd+doubleClick
  • Code Completion – Esc
  • Open Quickly – Shift+Cmd+D

Cool shortcut’s list for XCode


Magic of svn:keywords

December 11th, 2008 vira Posted in Computer science 3 Comments »

Сегодняшний день не прошел без мини откровений  – узнала о возможности динамически изменять ревизию/дату изменения в исходниках при коммите. Для этого просто необходимо установить свойство svn:keywords (svn propset svn:keywords “Date Author” source.c) с необходимыми ключевыми словами (напр. Revision, Author и т.д.), а в исходнике добавить что-то вроде “$Revision$”. И при коммите вместо ключевого слова будет вставлен номер ревизии с которой он произведен -$Revision: 666$”

Одно из применений этого метода для Java – добавить в каждый класс статический блок

static{ System.out.println(”$Revision$ $Source$ $Date$”);}

При загрузке классов будет выводиться указанная информация, которая может быть крайне полезна при отладке – напр. один из классов устаревший.

Детали в svnbook


Using Google Search API from Java

April 25th, 2008 vira Posted in Computer science 14 Comments »

Recently I’ve discovered ability to search in Google from Java program in a way different from brute “crawling”. And I’ve found out two options:

With this API you can issue search requests to Google’s index of billions of web pages and receive results as structured data, access information in the Google cache, and check the spelling of words. Google SOAP Search API is implemented as a web service and all you need is just get WSDL and call remote methods through SOAP protocol. Usage of this service is limited to 1000 requests per day.

But as you can read on SOAP API site

As of December 5, 2006, we are no longer issuing new API keys for the SOAP Search API. Developers with existing SOAP Search API keys will not be affected.

So you aren’t able to get a new API key (I found the old one in Internet). And Google encourages you to use the AJAX Search API, which is described below.

Example of code that perform search request and show obtained results:

import com.google.soap.search.*;
import java.io.*;
public class SimpleGoogleDemo {
	public static void main(String[] args) {
		// Create a Google Search object, set our authorization key
		GoogleSearch s = new GoogleSearch();
		String clientKey="xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
		s.setKey(clientKey);
		s.setQueryString("vera.org.ua");
		GoogleSearchResult result = null;
		// Depending on user input, do search or cache query, then print out result
		try {
			result = s.doSearch();
		}
		catch (GoogleSearchFault f) {
			System.out.println("The call to the Google Web APIs failed:");
			System.out.println(f.toString());
		}    // if we made it here, the search went through
		System.out.println("Google Search Results:");
		System.out.println("======================");
		if (result!= null)
			System.out.println(result.toString());
	}
}

To run this code you need to have googleapi.jar in your classpath. This jar file contains very useful and easy-to-use class com.google.soap.search.GoogleSearch, which does all search work.

Google AJAX API

Usage of this unlimited and you can make as many request as you want. Despite the fact that Google in this API FAQ say “The Google AJAX Search API is currently available only for websites.” ability to use it exists :-)

Example of code that perform search request and show obtained results.

import java.io.*;
import java.net.*;
 
public class GoogleAJAXSearchAPI {    
 
	private static String endpointURL = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&amp;q=vera";
 
	public static void main(String[] args) throws Exception {
		URLConnection uc = new URL(endpointURL).openConnection();
		HttpURLConnection connection = (HttpURLConnection) uc;
		connection.setDoOutput(true);
		connection.setRequestMethod("GET");
		connection.connect();
		String line;
		InputStream inputStream = null;
		try {
			inputStream = connection.getInputStream();
		} catch (IOException e) {
			inputStream = connection.getErrorStream();
		}
		BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
		while ((line = rd.readLine()) != null) {
			System.out.println(line);
		}
	}
}

To run this code you need to can get API key here.

So, have fun :)

PS Take a look at this too – Java OO wrapper for Google AJAX API.


Mac Tips: Mac OS X+DosBox+TASM=true dos development in assembler environment

October 24th, 2007 vira Posted in Computer science 2 Comments »

Что-то моя “формула счастья” усложняется :-) – после (Mac+Cord=remote Win)

Возникла задача делать лабы по асму для х86-го на моем Маке. Вначале думала найти родную cреду для МакОС, но так сразу не нашлось :( И потом вспомнила про старый-добрый TASM, который можно было бы запустить под эмулятором DOS-a. И вышло )

В качестве эмулятора выбран DosBox – An open source DOS emulator for BeOS, Linux, Mac OS X, OS/2, and Windows. Ну и TASM ) После стандартной установки DosBox-a и его запуска необходимо примонтировать директорию, в которую заранее необходимо скопировать установщик TASM-a. В моем случае команда имела вид: mount c ~/dos

Установка TASM-a правда успешно до конца не дошла ( и пришлось доустановить нужные его части, что сделать довольно таки просто. Например, для установки отладчика просто нужно распаковать tddos.pak командой unpak.exe xl tddos.pak c:\tasm\bin. Правда вполне возможно, что такая проблема возникла только у меня.

Итак, мы сделали все, чтобы работать в полноценной среде, для разработки программ на ассемблере под дос. Править исходные файлы можно в любимом текстовом редакторе под MacOS, а дальше tasm.exe prog.asm, tlink.exe /v prog.obj и наконец td.exe prog.exe

Так выглядит запущенный отладчик:

td_dosbox

Только ресурсов этот эмулятор ест – уджас просто


Семинар от IBM на тему безопасности J2EE приложений

October 22nd, 2007 vira Posted in Computer science No Comments »

Очередной семинар в Киеве – на этот раз от IBM (на их семинарах я еще не была :)

“Решения IBM для построение защищенной ИТ-инфраструктуры”

Когда? 6 ноября 2007, с 10 до 15

Где? Украина, Киев, ул. Богдана Хмельницкого, д. 53, отель “Опера”, зал “Симфония”

Registration and details


Internet works – help to find Steve Fossett

September 10th, 2007 vira Posted in Computer science, internet No Comments »

3-го вересня зник на своєму літаку Стів Фоссет – людина, що встановила багато світових рекордів, при чому у різних видах змагань. Це сумна подія і сподіваюсь, що його знайдуть. Але питання не в цьому. Подібний пост йому не допоможе.Цікавим є метод пошуку. Кожен користувач Інтернету може допомогти знайти Стіва Фоссета аналізуючи супутникові знімки на предмет об’єктів, що схожі на його літак. Цю акцію підтримує Гугл та Амазон. При чому кількість розглянутих знімків стрімко зменшується – швидкість по моїм оцінкам складає приблизно 5 зображень за 1 сек.Якщо це спрацює, то людство матиме цікравий приклад застосування Інтернету для такого важливого завдання як пошук людей. Звичайно ж і раніш таке робилося, але до цього не заохочувались звичайні користувачі Інтернету, які представлють собою величезні за розміром людські ресурси.


Java tips: get last inserted autoincrement fields

September 6th, 2007 vira Posted in Computer science No Comments »

To get last inserted autoincrement fields using JDBC you should write something like this:

ResultSet resultSet = statement.getGeneratedKeys();
int newId=0;
if ( resultSet != null && resultSet.next() )
{
newId = resultSet.getInt(1);
}

And don’t forget to add Statement.RETURN_GENERATED_KEYS parameter when create statement.


Another one )

July 3rd, 2007 vira Posted in Computer science No Comments »

Today I’ve got another one certificate )))