Архив рубрики ‘Technology’

BigDecimal

Июль 22, 2009

java-personСеголня я немного был шокрирован, когда результат BigDecimal.equals(BigDecimal) давал false, хотя я на 100 процентов был уверен, что числа одинаковые.

Оказывается, что два BigDecimal’а эквивалентны тогда, когда не только их значения равны, но и scale одинаковый.

В если хочется проверить на равенство не взирая на scale, то нужно использовать compareTo.

Вот так вот, так что читаем JavaDoc.

Java and SFTP

Июль 14, 2009

jscapeНедавно встала задача организовать «забирание» файлов по SFTP. Витя организовал тунель на своей машине, так что с помощью MC уже можно было походить по директориям, присмотреться :).

Осталось только выбрать либу для Java. Мною были найдены:

  • SSHTools. Не подошла по лицензионным соображениям. GPL использовать нельзя.
  • jscape. Платная. Хотя по идее деньги на покупку найти можно.

И тут «вылезает из кустов» Витя и предлагает использовать ganymed-ssh2 библиотеку.

С помощью NetBeans Maven Repository Windov я быстро его нашел и добавил к необходимому проекту.

Перетаскиваемое расписание

Апрель 15, 2009

Так как у детей в ХТТ достаточно мало времени на самостоятельное освоение и написание диплома, то придётся им помогать.

Марина делает систему для поддержки деятельности учебной части. Проще говоря, удобный интерфейс для работы с расписанием. Делаться всё это будет на PHP и MySQL. Это мой тактических ход. Тема сама по себе очень хороша. Ведь доступ к расписанию можно дать многим и у каждого будут свои привилегии. Для того, чтобы потом в будущем можно было развивать  систему в этом направлении я решил, что лучше использовать легкий клиент в виде браузера, а PHP обладает очень низким порогом вхождения. На сервере пусть крутиться MySQL. Не понравиться — тогда поставлю «слоника» (PostgreSQL).

Как всегда, расписание отображается в виде сетки. Вверху будет время, а слева любое другое измерение (преподаватели, аудитории, гпуппа).

Схема расписания занятий

Схема расписания занятий

Для того, чтобы это всё было «юзабельным» лучше всего реализовать возможность перетаскивания занятий по сетке. Причём сетка должна быть «заморожена», т.е. при прокручивании расписания верх и левая сторона не изчезают из поля зрения.

Для реализации перетаскиявания подойдет jQuery, а именно draggable и droppable. Лучше конечно про все эти «плюшки» почитать на официальном сайте. Но, как показала практика быстрое вливание на русском будет в моём случае более продуктивнее. В итоге у меня просто таскаемый прямоугольник :)

Для начала то что надо.

Google AJAX api. Коротко.

Апрель 15, 2009

Google предоставляет довольно обширный список API. Из всего этого многообразия я сегодня решил посмотреть Google AJAX API. Очень сильно порадовало Interactive Code Playground.

jQuery magic

Февраль 19, 2009

logo_jquery_215x53Что такое jQuery скорее всего уже все знают (а если не знают, то бегом читать…). Но некоторые методы данного JS фреймворка для меня казались бесполезными (какой я был наивный :))

Рассмотрим мой конкретный пример. У меня в ячейке таблицы находится линк. При нажатии на этот линк мне необходимо получить ссылку на строку, в которой находиться данный линк.

Я поначалу воспользовался методом

.parents("tr")

Но меня ждал сюрприз. (Дети, внимательно читайте документацию !!!). Оказывается данный метод вернет всех родителей в дереве, которые являются строками таблицы. Т.е. если наша таблица вложена в еще одну таблицу (а такой вариант на 100% вам попадётся) то вы получите и родительскую строку, и прородительскую. А мне такого не надо.

На помощь приходит базовый фильтр eq. Написав

.parents("tr:eq(0)")

я как раз и получил только первую строку таблицы. Кстати, рекомандую заглянуть на страницу справки данного фильтра. Там очень интересные примеры использования.

И напоследок, есть возможность устновить себе на комптютер offline версию хелпа по jQuery, которая выполнена в виде AIR приложения.

Как легко и непринужденно добавить парваметр в JSF url.

Декабрь 1, 2008

Всё до безобразия просто. Начнем с того, что я опишу задачу, которую мне пришлось решить.

Задача: отобразить список сущьностей с кнопочкой view, при нажатии на которой открывалась бы детальная информация о сущьности.

Зарание извиняюсь за ненормативную лексику, но, как мне кажется, без неё нет возможности показать всю гамму эмоций.

Кажется просто. А хуй там. Ни в одном примере нет нормального описания такого просто Use-Case. Единственно что мне предлагали, так это использовать сессионный бин. Но у этого способа есть свои недостатки. Например нет возможности создать репрезентативный урл, пойдя по которому, ты сразу получишь контент. ПРиходилось сначала идти на страницу с таблицей, а затем, выбрав необходимую сущьность, перходить на интересующую нас «детальку».

Вот тебе бля и «мега Технология» JSF. А хочеться всего ничего, просто написать entity.page?id=1234.

Итак. Задача разбивается на две задачи:

  1. Как обработать параметр на «детальке»
  2. Как установить этот параметр в урле.

Обработать параметр очень просто. Необходимо в faces-config у бина установить managed property примерно вот так (нет особого желания прасписывать что да как).

    <managed-bean>
        <managed-bean-name>customer</managed-bean-name>
        <managed-bean-class>com.ebon.pgw.web.beans.Customer</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>customerId</property-name>
            <value>#{param.id}</value>
        </managed-property>
    </managed-bean>

Скажу лишь одно, что param и обозначает параметр передаваемый в запросе.

Вторая задача оказалась по сложнее. Я лишь опишу, как я её решил, сам процесс решения я описывать не буду, дабы не засорять статью табуированной лексикой :).

Помогла мне в решении статья Vladimir Petrukhinа «JSF и ЧПУ (Человеко-понятный урл)«. Именно благодаря ней я узнал, как можно поменять возвращаемый урл. Так как я использовал MyFaces, то мой ViewHandler наследовался от JspViewHandlerImpl. Вот его код.

package test;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
public class GetParamViewHandler extends JspViewHandlerImpl {

    private static final Log log = LogFactory.getLog(GetParamViewHandler.class);

    @Override
    public String getActionURL(FacesContext facesContext, String viewId) {       
        String actionURL = super.getActionURL(facesContext, viewId);
        Map<String, Object> requestParameterMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
        String id = (String) requestParameterMap.get("id");
        if (id!=null) {
            actionURL += "?id=" + id;
            requestParameterMap.remove("id");
        }
        log.info("viewId[%s] actionUrl[%s]", viewId, actionURL);
        return actionURL;
    }
}

Соответсвенно его необходимо прописать в faces-config.xml

<application>
        <view-handler>test.GetParamViewHandler</view-handler>
</application>

Для того, чтобы установить соответсвующий id необходимо использовать f:param примерно так:

<h:commandLink value="view" action="customer" immediate="true">
    <f:setPropertyActionListener value="#{customer.value.merchantId}" target="#{customers.customerId}"/>
    <f:param name="id" value="#{customer.value.merchantId}"/>
</h:commandLink>

Вот наверное и всё. Если у кого есть вопросы и дельные замечания, welcome to comments :)

UPD: Оказалось, что не всё так просто. Во первых, код надо немного переписать (запосчу его позже), во вторых…. А вот про во-вротрых по подробнее.

Описанный выше метод прекрасно работает при простой навигации. А если мне необходимо отредактировать бин. Вот и пришел пиздец. Оказывается, что JSF пытается после нашего клика провести восстановление состояния view (LifeCycle Phase : Restore View), и именно в этот момент у происходит всё заново. А заново не получится, т.к. у нас уже нет в запросе параметра id. Как сделать так, чтобы состояние нормально восстанавливалось я не знаю. Увы :(.

Flash. Как сделать сложный Tween?

Декабрь 10, 2007

Как создавать простой Tween я узнал из livedocs

В этой документации имеется пример, который изменяет только одно свойство.


import fl.transitions.Tween;
import fl.transitions.easing.*;
var myTween:Tween = new Tween(myObject, "x", Elastic.easeOut, 0, 300, 3, true);

А как можно одновременно изменять два свойства?

С этим вопрос я обратился на форум flasher.ru. И как оказываеться, есть специальный класс TweenLite. Про него можно почитать на http://blog.greensock.com/

Всё очень грамотно офрмлено, а в комлекте есть генериловка кода под этого класса. Честное слово, очень порадовало.

За подсказку спасибо fljot.

Java. Как измерить время работы метода.

Ноябрь 14, 2007

На днях меня мой teamlead столкнул с этой задачей. Каково самое простое решение? Очень просто…. Берем исходный код и дописываем всё необходимое для измерения. Например, если был такой код


public class C {

public void m() throws Exception {
// do doSomething
}
}

и мы хотим померять производительность метода m(), то можем поменять его например так:


public class C {

public void m() throws Exception {
long timer = -System.currentTimeMillis();
// do doSomething
timer += System.currentTimeMillis();
System.out.println("C.m() " + timer);
}
}

Потом снимаих результаты с консоли и анализируем. Но вот беда, а если мне надо протестировать две версии проекта. Тогда мне придётся компилировать эти две версии с этими изменениями. Не гуд, скажу я вам. Очень муторно и неудобно. Мне то всего надо чуть чуть дописать, а ради этого перекомпиливать кучу всего.

У вот тут нам поможе ASM. Нет, не пугайтесь это не ассемблер, но очень близко. Это framework для анализа и изменения байт кода Java. Так вот с помощью этого «зверька» можно автоматически дописать в байт код всё что вам вздумаеться.

Давайте рассмотрим как с помощью ASM реализовать нашу идею. Всё очень просто.

  1. Качаем сам framework
  2. Качаем мануал по ASM с официального сайта. И, если вы хорошо знаете английский, читаете его и находите в нём ответ на данный вопрос.

Если вы хотите прочитать весь процесс реализации данного подхода к измерению времени работы метода на русском языке, то отпишите мне в коментах. Тогда я не поленюсь и распишу, что да как.

Flash. Ошибки новичка.

Октябрь 10, 2007

Я, используя loader, загрузил картинку и сразу же её ложил в некоторый MovieClip. Как оказалось, при увеличении этого клипа картинка переставала отображаться. Обход этой ситуации оказался следующий. Загруженную картинку нужно просто было нарисовать на Shape, а потом этот Shape бросить на MovieClip, который мы будем расширять. Этот способ позволил также включить сглаживание при увеличении (последний параметр в beginBitmapFill)


var image:Bitmap = new Bitmap(event.target.loader.content.bitmapData.clone());
var shape:Shape = new Shape();

shape.graphics.beginBitmapFill(image.bitmapData, null, false, true);
shape.graphics.drawRect(0,0,image.width, image.height);
shape.graphics.endFill();

Flash. Refactoring.

Октябрь 2, 2007

Я программирую в основном на Java. Но вот понадобился Flash. Что я могу сказать по этому поводу…. Flash обзавёлся ноым языком снераиев (последний раз я видел флеш когда была только пятая версия). Этот язык похож на Java, всё при неём: ООП, пакеты….Порадовала обработка XML.

Но, честно сказать, очень тяжело (а если точно сказать лень) изучать что-то похожее. Был бы полным ламаком, учил бы с нуля и знал бы самые простые вещи. Вот и приходиться по форумам лазить.

Это было отступление от темы….. :)

Так вот, на моей карте оказалось уже два таскаемых объекта. Это карта и панель масштаба. Когда пришла очередь миникарты, то я понял, что надо что-то менят. Третий объект, в котором опять од-но и тоже. Вот тут нам и поможет наследование.

Реализовал клас, который позволяет создавать объекты, которые можно таскать в переделах экрана.

Всё просто, берешь и рисуешь мувик, который будет у нас фоном. Единственное требовани : верхнний левый угол этого мувика должен быть в координатах 0,0. Называешь его к примеру Background. Наследуешь его от моего класса. Для этого пишешь примерно такой код.


/**
* Фон Ð´Ð»Ñ Ð¿Ð°Ð½ÐµÐ»Ð¸ "
*/

package {

import by.strix.MovedBackground;

public class Background extends MovedBackground {
}
}

После этого ложишь свой BackGround на любой клип на задний план. Вот и всё.

Код моего класса следующий.


/**
* Фон Ð´Ð»Ñ Ð¿Ð°Ð½ÐµÐ»ÐµÐ¹. ÐозволÑÐµÑ Ð¸Ñ Ð´Ð²Ð¸Ð³Ð°ÑÑ Ð² пÑÐµÐ´ÐµÐ»Ð°Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾Ð¹ облаÑÑи
* !!! ÐÐÐÐÐÐÐÐ. ÐÐ»Ñ ÐºÐ¾ÑÑекÑной ÑабоÑÑ Ð½ÐµÐ¾Ð±Ñодимо, ÑÑо Ð±Ñ Ñон наÑиналÑÑ Ñ (0,0)
*/

package by.strix {

import flash.display.MovieClip;
import flash.events.*;
import flash.geom.Rectangle;

public class MovedBackground extends MovieClip {

//private var settings:XML = MovieClip(root).settings.getSettings();

private var _parent:MovieClip = MovieClip(parent);

public function MovedBackground() {

// УÑÑановка обÑабоÑÑиков Ð´Ð»Ñ Ð¿ÐµÑеÑÑгиваниÑ.
addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
stage.addEventListener(Event.MOUSE_LEAVE, handleMouseLeave);

// УÑÑановка обÑбоÑÑиков Ñ ÑодиÑелÑ, Ð´Ð»Ñ ÐºÐ¾ÑоÑого ÑвлемÑÑ Ð·Ð°Ð´Ð½Ð¸Ð¼ Ñоном, Ð´Ð»Ñ Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ð¸Ñ.
_parent.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOver);
_parent.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOut);

// пÑогÑаммно ÑÑÑанавливаем в заÑемненное положение
handleMouseOut(null);
}

function handleMouseDown(event:Event):void {
// ХиÑÑое вÑÑмÑление Rect Ð´Ð»Ñ StartDrag ÑвÑзвно ÑÑем, ÑÑо наÑало клипа не в нÑле.
var dx:Number = width-stage.stageWidth + x;
var dy:Number = height-stage.stageHeight + y;
var dragRect:Rectangle = new Rectangle(-dx,-dy, dx-x,dy-y);
//parent.startDrag(false, dragRect);
//startDrag(false, dragRect);*/
MovieClip(parent).startDrag(false, dragRect);
}

function handleMouseUp(event:Event):void {
//parent.stopDrag();
stopDrag();
}

function handleMouseLeave(event:Event=undefined):void {
/*if (root.panel.dragged_mc){
root.panel.handleMouseUp();
}*/
handleMouseUp(event);
}

// Ðаводи мÑÑкÑ
function handleMouseOver(event:Event=undefined):void {
_parent.alpha = 1;
}

// Уводим мÑÑкÑ
function handleMouseOut(event:Event=undefined):void {
_parent.alpha = 0.25;
}
}
}