3

Там вдали, за рекой

Это река Казанка, на которой стоит Казань:)






1

HI-TECH

Скоро в продажу поступят новые беспроводные компьютерные мыши, выполненные в стиле ретро. Специально для ностальгируещих по временам I, II и III Pentium.








0

Клиент для Blogger своими руками-4

Привет всем читателям нашего блога! Приношу извинения за мое долгое отсутствие -
как, наверное многие успели заметить, за меня отдувалась моя ненаглядная жена :) Счас я сижу на больничном и имею возможность продолжить мои эксперименты с клиентом для Blogger-а :). Обычно я сначала писал программку, а потом, уже имея какой-то готовый результат, садился писать статью. Сейчас будет все по-другому, поскольку все это время я занимался... Ну скажем так, РАБОТОЙ (на самом деле - пытался совместить работу и "учебу" в автошколе:)))) Поэтому никакого готового кода пока нет, будем его сочинять по ходу дела. Итак, в предыдущем посте я добавил в класс BlogEditor возможность получать содержимое всех постов выбранного блога и выяснил, как получить их html-представление. Но у мене такое чувство, что чего-то не хватает. Пожалуй, было бы неплохо указывать, какие посты мы хотим получить, например - последние 15 штук, или за последний месяц, или за какой-то интервал времени (например, в интервале между пасхой и курбан-байрамом :))).

Пишем сначала тест, то есть программку, в которой будет использоваться наш код (пусть даже еще не написанный :)))

package test.blogeditutil;
import com.google.gdata.client.*;
import com.google.gdata.data.*;
import com.google.gdata.util.*;
import java.io.*;
import javax.swing.*;
import java.util.*;
import blogeditutil.*;
//Распечатка избранных постов
class TestBlogEditorSelective
{
public static void main(String args[]) throws IOException, ServiceException
{
BlogEditor bedit = new BlogEditor();
String blogname = QueryBlogName.getBlogName();
List<Entry> postlist = bedit.getPostEntryList(blogname, 1, 15);
assert(postlist.size() <= 15);
System.out.println("Blog posts of " + blogname + ":");
for(Entry p: postlist)
{
System.out.println("Post caption: " + p.getTitle().getPlainText());
System.out.println("Date and time: " + p.getPublished());
}
}
}
Класс BlogEditor описан мной в предыдущих постах. Класс QueryBlogName содержит всего один метод, который возвращает строку, введенную пользователем. Как видно, нам хочется получить 15 последних постов. Компилируем, и... конечно, ничего не компилируется, поскольку метод getPostEntryList(String, int, int) в классе BlogEditor мной пока не реализован. Сделать его из существующего варианта класса - дело нескольких минут:

public class BlogEditor
{
...

...
public List<Entry> getPostEntryList(String blogname, int start, int nres)
throws IOException, ServiceException
{
String blog_id = getBloggerID("http://"+blogname+BLOGGER_SERVER);
if(blog_id == null)
throw new IOException("Can't get blogID for " + blogname+BLOGGER_SERVER);
//Запрос на получение постов:
Query query = new Query(new URL (BLOGGER_FEED + blog_id + POST_LOCATION));
query.setStartIndex(start);
query.setMaxResults(nres);
return bservice.getFeed(query, Feed.class).getEntries();
}
}

Когда интерфейс класса меняется, это есть весьма нехорошо. Поэтому старый метод getPostEntryList с одним параметром типа String я тоже реализую, но уже иначе:

public class BlogEditor
{
...

...
private final int MAX_RESULTS = 10000000;
public List<Entry> getPostEntryList(String blogname)
throws IOException, ServiceException
{
return getPostEntryList(blogname, 1, MAX_RESULTS);
}
}
После этого все нормально компилится и тест TestBlogEditorSelective тоже запускается без проблем. Еще одна полезная возможность - получить список постов, опубликованных в определенный интервал времени. Заново переписывать тест мне лень, и я просто вставляю еще один вызов в конец метода main класса TestBlogEditorSelective:

class TestBlogEditorSelective
{
public static void main(String args[]) throws IOException, ServiceException
{
...
.
.
//Посты, опубликованные между 1 декабря 2008 и 25 января 2009 года:
postlist = bedit.getPostEntryList(blogname, new GregorianCalendar(2008, 11, 1),
new GregorianCalendar(2009, 0, 25) );
assert(postlist.size() == 8);
}
Сейчас тест естественно, даже не компилируется. Я пока добавлю в класс BlogEditor самую простую реализацию этого метода, дабы убедится в том, что тест будет обнаруживать ошибку:

public class BlogEditor
{
...
.
public List<Entry> getPostEntryList(String blogname, Calendar date1, Calendar date2)
{ return new ArrayList<Entry>(); }
}
После запуска теста, он вылетел на assert, как и ожидалось. Хорошо, теперь можно сварганить нормальную реализацию. Заглянув в документацию по GData API, можно увидеть, что там используются собственная структура данных, описывающая дату - DateTime. К сожалению, объект класса DateTime нельзя напрямую создать из java.util.Calendar, а можно лишь из java.util.Date. И это при том, что большинство удобных конструкторов и методов в классе java.util.Date объявлены как deprecated (нежелательными в изпользовании, устаревшими); Ну, ничего страшного, всего лишь код будет чуть длиннее. Итак, новая реализация, которая уже делает то, что нужно:

public class BlogEditor
{
private final String BLOGGER_FEED = "http://www.blogger.com/feeds/",
POST_LOCATION = "/posts/default",
BLOGGER_SERVER = ".blogspot.com";
private GoogleService bservice;
public BlogEditor()
{ bservice = new GoogleService("blogger", "lotrex-BlogEditor-0.0");}
...
.
.
public List<Entry> getPostEntryList(String blogname, Calendar date1,
Calendar date2)
throws IOException, ServiceException
{
String blog_id = getBloggerID("http://"+blogname+BLOGGER_SERVER);
if(blog_id == null)
throw new IOException("Can't get blogID for " + blogname+BLOGGER_SERVER);
//Запрос на получение постов:
Query query = new Query(new URL (BLOGGER_FEED + blog_id + POST_LOCATION));
query.setPublishedMin(new DateTime(date1.getTime()));
query.setPublishedMax(new DateTime(date2.getTime()));
return bservice.getFeed(query, Feed.class).getEntries();
}
}

Все вроде хорошо, и тест проходит... Теперь надо бы устранить дублирование в двух версиях метода getPostEntryList, которое получилось из-за использования супертехнологии "copy-paste". Понятно, что дублирующийся код надо выделить в отдельный private-метод и как-то этот метод обозвать. В таких ситуациях я частенько трачу больше всего времени именно на то, чтобы придумать методу название. В этом случае я решил его обозвать getPostQuery, что должно (на мой взгляд:)) означать - "получить запрос на получение фида постов":

public class BlogEditor
{
private final String BLOGGER_FEED = "http://www.blogger.com/feeds/",
POST_LOCATION = "/posts/default",
BLOGGER_SERVER = ".blogspot.com";
...
.
private Query getPostQuery(String blogname) throws IOException,
ServiceException
{
String blog_id = getBloggerID("http://"+blogname+BLOGGER_SERVER);
if(blog_id == null)
throw new IOException("Can't get blogID for " + blogname + BLOGGER_SERVER);
//Запрос на получение постов:
return new Query(new URL (BLOGGER_FEED + blog_id + POST_LOCATION));
}
}

Остается заменить дублирующийся код в каждой из версий метода getPostEntryList на вызов getPostQuery(blogname) и проверить срабатывание теста, что я и сделал. Уфф, надеюсь с получением постов я на этом закончу. Потому что пора уж заняться чем-нить посерьезнее и интереснее - например, добавлением постов, комментов и картинок :)). Насчет последнего я пока не уверен, что получится...

2

Дела-заботы и фото

Что-то мы с мужем закрутились, все дела, все заботы...

Мы скоро вернемся.:)
Обязуюсь с опозданием, но проддержать идею BeBeKK@ и рассказать про нашего королевского двортерьера Джима:)))

А пока просто зимние, еще декабрьские фото










2

Ёлки-палки

Поздравляем всех наших читателей с наступившим Новым годом и Рождеством Христовым!!!

А поскольку одним из символов Нового года и Рождества является ёлка, то о ней. точнее о них сегодня и поговорим!:)

А теперь пойдут картинки:)

Вот так Казань готовилась к Новому году:








А вот так мы готовились к Новому году!


Хвастаюсь:))))












С Рождеством!!!





P.S. А как вы готовились к праздникам? Хвалитесь ёлками и украшениями!;)