MultiDoc
MultiDoc
하나의 Print Job에 둘 이상의 인쇄 데이터(print data)를 공급하는 객체가 구현하는 인터페이스예요. "Doc"은 "조각의 인쇄 데이터"를 뜻하는 짧고 발음하기 쉬운 용어이고, "multidoc"은 여러 doc의 묶음이에요.
본문
javax.print 패키지에 속하는 인터페이스로, 클라이언트는 MultiDoc 인터페이스를 구현한 객체를 Print Job에 넘기고, Print Job은 그 객체의 메서드를 호출해서 인쇄 데이터를 얻어요.
MultiDoc 인터페이스는 문서들의 "연결 리스트(linked list)"와 비슷한 추상화를 제공해요. multidoc 객체는 연결 리스트의 한 노드와 같아서, 리스트의 현재 doc과 다음 노드(multidoc)를 가리키는 포인터를 담고 있어요. Print Job은 multidoc의 getDoc() 메서드를 호출해서 현재 doc을 얻고, 다음 doc으로 이동할 준비가 되면 next() 메서드를 호출해 다음 doc을 담은 다음 multidoc을 얻어요.
void processMultiDoc(MultiDoc theMultiDoc) {
MultiDoc current = theMultiDoc;
while (current != null) {
processDoc (current.getDoc());
current = current.next();
}
}
물론 MultiDoc 인터페이스는 계약만 지키면 어떤 방식으로든 구현할 수 있어요. 반드시 연결 리스트를 구현에 사용해야 하는 건 아니에요.
multidoc 인쇄 작업의 모든 인쇄 데이터를 얻기 위해 Print Service 프록시는 두 가지 패턴 중 하나를 사용할 수 있어요.
- 인터리브(interleaved) 패턴: 현재 multidoc에서 doc을 얻고, 현재 doc에서 인쇄 데이터 표현 객체를 얻고, 그 표현 객체에서 모든 인쇄 데이터를 얻은 뒤, 현재 multidoc에서 다음 multidoc을 얻어서 더 이상 없을 때까지 반복해요. (위 코드 예제가 인터리브 패턴을 사용해요.)
- 한 번에(all-at-once) 패턴: 현재 multidoc에서 doc을 얻어 리스트에 저장하고, 현재 multidoc에서 다음 multidoc을 얻어 더 이상 없을 때까지 반복한 다음, 저장된 doc 리스트를 순회하면서 인쇄 데이터를 얻어요.
인쇄 데이터를 그때그때 생성하는 클라이언트가 있고, 한 번에 하나의 인쇄 데이터만 저장할 수 있는 자원이 없다고 가정해 봐요. Print service 프록시가 all-at-once 패턴을 사용한다면 이런 클라이언트는 문제를 겪게 돼요. 클라이언트는 프록시가 다시 와서 요청할 때까지 모든 doc의 인쇄 데이터를 보관해야 하는데 그럴 능력이 없거든요. 그래서 프록시는 이런 클라이언트와 함께 동작하려면 인터리브 패턴을 사용해야 해요.
이 문제를 해결하고 여러 doc을 Print Job에 제공하는 클라이언트의 설계를 단순화하기 위해, multidoc 인쇄 작업을 지원하는 모든 Print Service 프록시는 MultiDoc 객체에 인터리브 패턴으로 접근해야 해요. 즉 어떤 MultiDoc 객체가 주어지면 프록시는 getDoc()을 성공적으로 현재 Doc 객체를 얻을 때까지 한 번 이상 호출하고, 현재 doc의 인쇄 데이터를 모두 얻거나 복구 불가능한 오류가 발생할 때까지 진행하지 않아요. 계속할 수 있다면 프록시는 next()를 다음 MultiDoc 객체를 얻거나 더 이상 없다는 표시를 받을 때까지 한 번 이상 호출해요. MultiDoc 구현은 프록시가 이 인터리브 패턴을 따른다고 가정할 수 있고, 다른 사용 패턴에서는 구현의 동작이 정해져 있지 않아요(unspecified).
같은 multidoc에 동시에 접근할 수 있는 클라이언트 스레드 수에는 제한이 없어요. 따라서 모든 MultiDoc 구현은 여러 스레드에 안전(multiple thread safe)하도록 설계돼야 해요. 실제로 클라이언트 스레드가 (개념적) 리스트의 끝에 doc을 추가하는 동안 Print Job 스레드가 리스트의 시작에서 doc을 동시에 얻을 수 있어요. multidoc 객체가 스레드를 적절히 동기화한다면 두 스레드는 서로 간섭하지 않아요.
getDoc
Doc getDoc() throws IOException
현재 doc 객체를 얻어요.
- 반환값: 현재 doc 객체
- 예외
IOException: 문서를 읽는 중 오류가 발생한 경우
next
MultiDoc next() throws IOException
doc 객체들의 시퀀스에서 다음 doc 객체를 담은 multidoc 객체로 이동해요.
- 반환값: 다음 doc 객체를 담은 multidoc 객체. 더 이상 doc 객체가 없으면
null - 예외
IOException: 다음 문서를 찾는 중 오류가 발생한 경우