 |
|
개별 구성 요소 사용자 정의
지금까지는 전체 스키마 세트나 개별 스키마에 적용되는 사용자 정의 예제만을 살펴보았다. 또한
스키마 정의 내에서 전역 정의 및 전역 정의에 포함된 항목을 포함한 특정 구성 요소에 대한
CodeGen의 처리를 사용자 정의할 수 있다. 데이터 모델에서 구성 요소를 제거하고, 구성 요소에
사용된 클래스 또는 값 이름을 변경하고, 구성 요소의 스키마 유형을 변경하는 등의 사용자 정의를
사용할 수 있다.
스키마를 제어할 경우에는 사용자 정의를 통해 데이터 모델에서 구성 요소를 제거하는 방법보다는
항상 스키마를 직접 변경하는 방법이 훨씬 간단하다. 그러나 엔터프라이즈 데이터 교환 스키마에는 이들
스키마를 사용하는 특정 애플리케이션에 적합하지 않을 수 있는 특수 구성 요소가 있을 수
있다. 일반적으로 사용자는 이러한 스키마를 제어할 수 없다. 이 경우 사용자 정의를 사용하면
제공된 스키마를 변경하지 않고도 데이터 모델을 단순화할 수 있다.
구성 요소 사용자 정의
스키마 구성 요소에 대한 사용자 정의는 사용자 정의 요소와 구성 요소를 나타내는 스키마
정의 요소를 연관시켜서 작동한다. 사용자 정의와 스키마 요소를 연관시킬 경우에는 여러 가지
방법 중에서 해당 상황에 가장 적합한 방법을 선택해서 사용하면 된다. 연관의 한쪽은 고정된다.
그러나 사용자 정의 요소의 이름은 항상 스키마 구성 요소 이름과 일치해야 한다. 예를 들어,
스키마에서 <xs:element> 정의를 사용자 정의하려면 <element
사용자 정의 요소(네임스페이스 없음)를 사용해야 한다.
Listing 15에서는 TimeCard에서 참조하는 스키마 중 한 스키마의
정의를 보여 준다. 이 예제는 개별 구성 요소의 사용자 정의를 잘 보여 준다. PersonNameType은
여러 개의 단순 xs:string 요소와 복합 구조를 갖는 여타 요소로 구성되어
있다. 공교롭게도 튜토리얼 코드에 사용된 테스트 문서에는 이 유형의 Affix
또는 AlternateScript 요소가 포함되어 있지 않으므로 이러한 요소를 제거하여
생성된 데이터 모델을 단순화할 수 있다.
Listing 15. PersonName 스키마
<xsd:complexType name="PersonNameType">
<xsd:sequence>
<xsd:element name="FormattedName" type="xsd:string" minOccurs="0"/>
<xsd:element name="LegalName" type="xsd:string" minOccurs="0"/>
<xsd:element name="GivenName" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="PreferredGivenName" type="xsd:string" minOccurs="0"/>
<xsd:element name="MiddleName" type="xsd:string" minOccurs="0"/>
<xsd:element name="FamilyName" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
...
</xsd:complexType>
</xsd:element>
<xsd:element name="Affix" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
...
</xsd:complexType>
</xsd:element>
<xsd:element name="AlternateScript" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
...
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="script" type="xsd:string"/>
</xsd:complexType> |
Listing 16에서는 데이터 모델에서 Affix 및 AlternateScript
요소를 제거하기 위해 사용자 정의를 정의하는 한 가지 방법을 보여 준다. 이 예제에서는 스키마 정의
구조를 탐색하는 동안 XPath 형태의 지침 세트인 경로 스펙을 사용한다. 경로 단계는 슬래시(/)로 구분되며,
스키마 정의의 이름지정된 구성 요소(전역 유형, 그룹, attributeGroup
정의 또는 전역이나 로컬의 요소 또는 속성 정의)와 일치하는 단계는 [@name=...] 조건부를
사용하여 구성 요소 유형의 특정 인스턴스를 지정할 수 있다.
Listing 16. 불필요한 구성 요소에 대한 직접 사용자 정의
<schema-set ...>
<schema name="PersonName.xsd">
<element path="complexType[@name=PersonNameType]/sequence/element[@name=Affix]"
ignore="true"/>
<element path=
"complexType[@name=PersonNameType]/sequence/element[@name=AlternateScript]"
ignore="true"/>
</schema>
</schema-set> |
Listing 16에서 각 경로는 스키마 레벨부터 시작하는 전체 경로로
표시된다. 경로에 와일드카드 문자를 사용할 수도 있다. 경로 단계에 사용되는 *
와일드카드는 스키마 정의에 있는 임의의 단일 요소와 일치하며, **
와일드카드는 스키마 정의에 있는 임의 개수의 중첩된 요소와 일치한다. 따라서 complexType[@name=PersonNameType]/sequence/element[@name=Affix]
경로 대신 complexType[@name=PersonNameType]/*/element[@name=Affix] 또는
complexType[@name=PersonNameType]/**/element[@name=Affix] 경로를
사용할 수 있다. 그러나 **/element[@name=Affix]는 사용할 수 없다.
왜냐하면 CodeGen에서는 사용자 정의가 잘못 적용되는 경우를 방지하기 위해 사용자 정의와 관련된
전역 정의 구성 요소를 명시적으로 식별해야 하기 때문이다.
구성 요소 사용자 정의는 중첩이 스키마 정의 구조와 일치하는 한 계속해서 중첩될 수 있다. 이
경우에는 각 사용자 정의가 포함하는 사용자 정의에 상대적인 대상을 지정하기만 하면 된다. 경로의
최종 단계에 있는 [@name=...] 조건부 대신 사용자 정의의 name="..."
속성을 사용할 수 있으며 최종 단계의 요소 이름은 사용자 정의 요소의 이름과 항상 같아야 하므로
생략할 수 있다. 이름 속성과 결합된 중첩을 사용하면 경로를 전혀 사용하지 않을 수도 있다. Listing
17에서는 Listing 16의 사용자 정의를 지금 설명한 대체 방법을 사용하여
다시 구조화한 사용자 정의를 보여 준다.
Listing 17. 불필요한 구성 요소에 대한 중첩된 사용자 정의
<schema-set ...>
<schema name="PersonName.xsd">
<complexType name="PersonNameType">
<sequence>
<element name="Affix" ignore="true"/>
<element name="AlternateScript" ignore="true"/>
</sequence>
</complexType>
</schema>
</schema-set> |
데이터 모델 단순화
이전 서브섹션에서 예제로 사용한 PersonName 구성 요소 외에도
TimeCard 스키마에는 이 튜토리얼에 포함된 샘플 문서로 사용되지
않은 수많은 복합 구성 요소가 있다. 사용자 정의를 사용하여 사용되지 않는 구성 요소를 제거하면
생성된 데이터 모델을 상당히 단순화할 수 있다. CodeGen에서 사용하는 Java 값 이름이 올바르게
작동하지 않는 경우도 있다. 특히, 같은 요소 이름이 반복적으로 사용되는 경우에는 값 이름이 숫자
접미어로만 구별되면서 값의 올바른 사용 방법을 파악하기가 어려워질 수 있다. 예를 들어,
Listing 10을 보면 duration 및 duration1이라는
필드 쌍이 생성된 코드에 포함되어 있다. 이 경우 사용자 정의를 사용하여 이들 이름 중 하나를
의미 있는 이름으로 변경할 수 있다.
Listing 18에서는 코드의 hrxml 디렉토리에 있는 custom3.xml 파일을
보여 준다. 여기에는 이러한 사용자 정의가 모두 있다. 이 파일에서는 의도적으로 이전 서브섹션에서
설명한 중첩, 경로 및 이름과 혼합된 경로 등의 다양한 구성 요소 식별 방법을 사용한다. 맨 아래에
있는 값 이름 사용자 정의는 value-name="simpleDuration" 속성을 사용하여
두 번째 기간에 대한 이름을 좀 더 자세한 형태로 바꾼다.
Listing 18. TimeCard 데이터 모델 단순화 및 분류
<schema-set xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://ns.hr-xml.org/2007-04-15" package="org.hrxml.timecard"
type-substitutions="xs:integer xs:int" generate-all="false">
<name-converter strip-suffixes="Type"/>
<class-decorator class="org.jibx.schema.codegen.extend.CollectionMethodsDecorator"/>
<schema name="UserArea.xsd" excludes="UserArea UserAreaType"/>
<schema name="PersonName.xsd">
<complexType name="PersonNameType">
<sequence>
<element name="Affix" ignore="true"/>
<element name="AlternateScript" ignore="true"/>
</sequence>
</complexType>
</schema>
<schema name="TimeCard.xsd" includes="TimeCard">
<complexType name="TimeCardType">
<element path="**/element[@name=Allowance]" ignore="true"/>
<element path="**/element[@name=PieceWork]" ignore="true"/>
<element path="**/element[@name=TimeEvent]/**/" name="RateOrAmount" ignore="true"/>
<element path="**/choice/[@name=Duration]" value-name="simpleDuration"/>
</complexType>
</schema>
</schema-set> |
CodeGen에서 custgen3 Ant 대상을 사용하여 이 사용자 정의를 실행하거나
custom3 대상을 사용하여 생성, 컴파일, 바인딩 및 테스트를 차례대로
실행할 수 있다. 사용자 정의의 결과로 생성된 클래스는 9개의 최상위 레벨 클래스와 10개의 내부 클래스를
합해서 19개가 된다. 이 수는 사용자 정의를 사용하지 않고 생성된 원래 데이터 모델의 클래스 수와
비교해서 정확히 절반이다.
|