2008년 2월 1일 금요일

RIFE 시작하기(4) - Number Guess 어플리케이션 (3/3)

http://rifers.org 에서 발췌한 내용을 번역 하였습니다.
번역: 이원찬(wonchan.lee@gmail.com)
-------------------------------------------------------

- Reading data from a form

이제 우리는 사용자로부터 웹페이지 폼으로 입력을 받아야 한다. 이것은 Guess요소의 submission태그에 정의 되어 있다.
------------------------------------------------------------------
Guess요소에 submission 추가
------------------------------------------------------------------
<element implementation="tutorial.numberguess.Guess">
<input name="gameid"/>

<submission name="performGuess">
<param name="guess">
<default>-1</default>
</param>
</submission>

<exit name="start"/>
<exit name="success"/>

<output name="gameid"/>
</element>
------------------------------------------------------------------

하나의 submission파라미터가 정의되어 있다. 이름처럼 사용자가 추측한 숫자를 의미한다. submission은 항상 이전의 원본요소를 참조한다. 하나의 요소안에 모든 submission의 핸들링을 집중하는것은 폼을 보여주기 위한 페이지와 서브밋된 데이터를 다루는 두개의 페이지를 대신한다.

폼출력과 데이터 처리가 같은 요소에서 처리되므로 어떤 데이터가 누락되거나 잘못되었을때 이전페이지로 돌아가지 않고 폼을 다시 출력하기가 쉽다.

템플릿에도 submission을 위해 다음의 코드를 추가해야 한다.
------------------------------------------------------------------
폼 템플릿
------------------------------------------------------------------
<form action="[!V 'SUBMISSION:FORM:performGuess'/]" method="post">
<!--V 'SUBMISSION:PARAMS:performGuess'/-->
<input type="text" name="guess" value="[!V 'PARAM:guess'][!/V]" /><br />
<input type="submit" value="Guess" /><br />
</form>
------------------------------------------------------------------

action이 특별한 값으로 설정되었다: SUBMISSION:FORM:performGuess. RIFE는 이 값을 정확한 URL로 대채시킨다. 이 경우 대응되는 URL은 GUESS요소가 된다. 이 특별한 값의 마지막 부분은 일찍이 요소정의파일에 선언한 submission의 이름을 참조한다.

input HTML태그의 값은 PARAM:guess 로 설정되었다. 이것은 다시 submission정의에서 guess파라미터와 대응된다. 이 값은 자동으로 파라미터의 마지막값으로 변환되며 사용자에게 항상 마지막 숫자를 볼수 있도록 허락한다. 우리가 여기에서 더긴 value태그를 사용했음을 주목하라. 이것에 대해서는 뒤에 자세히 설명할 것이다. 여기에서 짚고 넘어갈 부분은 guess파라ㅣ터가 없을 경우 값은 빈문자열이 될것이며 사용자에게는 비어있는 필드를 보여줄 것이라는 것이다.

*주의사항*
항상 SUBMISSION:FORM:name 태그와 함께 SUBMISSION:PARAMS:name태그를 사용하라. 그렇지 않으면 RIFE는 경고를 보여줄 것이다. 이것은 미리 알아 두는것이 좋다.

SUBMISSION:과 같은 접두어를 동반한 값은 RIFE에서 특별히 취급된다. 예를들어, 폼액션과 파라미터가 세팅되었다. 여기에 우리가 곧 보게될 EXIT:와 CONFIG:와 같은 다른 접두어가 있다. 이 태그들은 filtered value태그라 부른다. RIFE는 자동으로 이것들을 걸러 특별한 컨텐츠로 치환한다.

페이지에 들어가면 요소는 submission이 존재하는지 확인하고 그렇다면 그것을 처리한다. 처리는 hasSubmission메소드를 통해 이루어 지며 값들은 getParameter와 같은 메소드들로 가져온다. 정수값을 가져오기 위해서는 getParameterInt가 사용된다. 다른 API들에 대한 정보는 javadoc의 com.ueyn.rife.engine.Element클래스를 보면 알 수 있다.

------------------------------------------------------------------
Guess요소를 위한 자바코드
------------------------------------------------------------------
package tutorial.numberguess;

import com.uwyn.rife.engine.Element;
import com.uwyn.rife.template.Template;
import tutorial.numberguess.backend.Contest;
import tutorial.numberguess.backend.Game;

public class Guess extends Element
{
private Template mTemplate = null;

private void handleGuess(Game game)
{
int guess = getParameterInt("guess", -1);
if (guess < 0 || guess > 100)
{
mTemplate.setBlock("warning", "invalid");
return;
}

game.increaseGuesses();

if (game.getAnswer() < guess)
{
mTemplate.setBlock("indication", "lower");
}
else if (game.getAnswer() > guess)
{
mTemplate.setBlock("indication", "higher");
}
else
{
setOutput("gameid", getInput("gameid"));
exit("success");
}
}

public void processElement()
{
Game game = Contest.getGame(getInput("gameid"));
if (null == game)
{
exit("start");
}

mTemplate = getHtmlTemplate("guess");

if (hasSubmission("performGuess"))
{
handleGuess(game);
}

print(mTemplate);
}
}
------------------------------------------------------------------

위의 자바코드에서 우리는 몇가지 흥미로운 점을 볼수 있다. 먼저 processElement메소드 내부의 exit호출을 보자. 이 명령은 start출구와 연결된 Flow link를 활성화 한다. 요소안에서 더이상의 처리를 하지않고, 즉시 종료하여 로직이 Flow link가 가리키는 요소로 넘어간다. 이 예저를 통해, 게임ID를 발견하지 못했을 경우 시작페이지를 보여줌을 알 수 있다.

만약, 게임이 성공적으로 검색되었다면, 다음에는 현재요청이 "perform_guess"라는 submission을 포함하고 있는지 확인하게 된다. 그렇다면, handleGuess가 호출되고 출구명이 "success"로 설정되면 요소는 해당 출구로 빠져나와 결과를 출력 할것이다.

submission을 찾지 못한다면 기본 템플릿 페이지가 보여지며 사용자에게 숫자를 입력하라고 요청할 것이다.

- Specifying the starting point
사용자들이 처음부터 http://localhost:8080/03_numberguess/start/ 으로 들어온다면 대행이지만 대부분 http://localhost:8080/03_numberguess/ 까지만 입력할 것이다.

이경우 사이트(site)를 위한 arrival요소를 기술하여 해결할 수 있다. arrival 요소는 arrival태그로 어플리케이션의 루트를 설정하는데 사용된다. 마지막으로 이것을 추가하면 사이트파일은 아래와 같이 될것이다.

------------------------------------------------------------------
최종 사이트 파일
------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE site SYSTEM "/dtd/site.dtd">

<site>
<arrival destid="Start"/>

<element id="Start" file="start.xml" url="/start">
<flowlink srcexit="started" destid="Guess"/>
<datalink srcoutput="gameid" destid="Guess" destinput="gameid"/>
</element>

<element id="Guess" file="guess.xml" url="/guess">
<flowlink srcexit="start" destid="Start"/>
<datalink srcoutput="gameid" destid="Start" destinput="gameid"/>

<flowlink srcexit="success" destid="Success"/>
<datalink srcoutput="gameid" destid="Success" destinput="gameid"/>
</element>

<element id="Success" file="success.xml">
<flowlink srcexit="start" destid="Start"/>
</element>
</site>
------------------------------------------------------------------

- Wrapping it Up

지금까지 간단한 웹게임을 작성해 보았다. 이것이 RIFE의 프로세스를 배우는데 많은 도움이 되었기를 바란다. 우리는 흐름(flow)과 데이터(data)의 연결(link)를 정의하고 웹페이지 생성을 위해 템플릿(template)을 사용했다. 그리고, 폼을 통한 사용자 입력을 처리했다. 이제 복잡한 템플릿 작성(writing complex templates)과 같은 더 발전된 주제를 위해 옮겨갈 준비가 되었다.

댓글 없음: