皆さん、
オブジェクトのマーシャリングとアンマーシャリングに JAXB を使用する世界は初めてです。
マップのリストのリストであると最もよく言えるオブジェクトをマーシャリングしようとしています。
私が達成しようとしている最終的な結果は、以下のとおりです。
<parametricSearchResult>
<allFilters>
<name>custom_year</name>
<name>abcd</name>
</allFilters>
<allFields>
<field>
<name>custom_year</name>
<value count="10">2012</value>
<value count="8">2011</value>
</field>
<field>
<name>abcd</name>
<value count="8">2011</value>
</field>
</allFields>
</parametricSearchResult>
私が書いたコードでは、これを出力として取得します
<parametricSearchResult>
<allFilters>
<name>custom_year</name>
<name>abcd</name>
</allFilters>
<allFields>
<allFilters>
<mName>test</mName>
<field>
<value count="10">
<mValue>2012</mValue>
</value>
<value count="8">
<mValue>2011</mValue>
</value>
</field>
<name>test</name>
</allFilters>
<allFilters>
<mName>test</mName>
<field>
<value count="4">
<mValue>2011</mValue>
</value>
</field>
<name>test</name>
</allFilters>
</allFields>
</parametricSearchResult>
私が持っているコードを以下に示します
ParametricSearchResult
@XmlRootElement(name = "parametricSearchResult")
public class ParametricSearchResult {
private final List<String> mFilterFields = new ArrayList<String>();
private final List<Map<String, Integer>> mFiltersToCountsMap = new ArrayList<Map<String, Integer>>();
public void setFilterFields(List<String> fields) {
mFilterFields.addAll(fields);
}
@XmlElementWrapper(name = "allFilters")
@XmlElement(name = "name")
public List<String> getFilterFields() {
return mFilterFields;
}
@XmlElement(name = "allFields")
@XmlJavaTypeAdapter(JAXBParametricSearchResultSerializer.class)
public List<Map<String, Integer>> getValuesAndCounts() {
return mFiltersToCountsMap;
}
public void addFilterFieldsAndCounts(final String field, final String filterValue, final Integer count) {
final int index = mFilterFields.indexOf(field.toLowerCase());
if (index == -1) {
mFilterFields.add(field.toLowerCase());
HashMap<String, Integer> mapValuesToCounts = new HashMap<String, Integer>();
mapValuesToCounts.put(filterValue.toLowerCase(), Integer.valueOf(count));
mFiltersToCountsMap.add(mapValuesToCounts);
} else {
Map<String, Integer> mapValuesToCounts = mFiltersToCountsMap.get(index);
mapValuesToCounts.put(filterValue.toLowerCase(), Integer.valueOf(count));
}
}
public Map<String, Integer> getFilterValueToCountMap(String filterName) {
final int index = mFilterFields.indexOf(filterName.toLowerCase());
if (index == -1) {
return new HashMap<String, Integer>();
} else {
return mFiltersToCountsMap.get(index);
}
}
}
ParametricSearchResultType
public class ParametricSearchResultType {
private final List<ParametricFilterType> allFilters = new ArrayList<ParametricFilterType>();
@XmlElement
public List<ParametricFilterType> getFilters() {
return allFilters;
}
public void setFilter(final ParametricFilterType data) {
allFilters.add(data);
}
}
ParametricFilterType
public class ParametricFilterType {
private String mName = "";
private final List<ParametricMapEntryType> mFilterAllEntries = new ArrayList<ParametricMapEntryType>();
@XmlElement(name = "name")
public String getName() {
return mName;
}
public void setName(final String data) {
mName = data;
}
public void setAllFilters(final ParametricMapEntryType data) {
mFilterAllEntries.add(data);
}
@XmlElementWrapper(name = "field")
@XmlElement(name = "value")
public final List<ParametricMapEntryType> getAllFilterEntries() {
return mFilterAllEntries;
}
}
ParametricMapEntryType
public class ParametricMapEntryType {
@XmlValue
public String mValue;
@XmlAttribute(name = "count")
public Integer mCount;
}
JAXBParametricSearchResultSerializer
public class JAXBParametricSearchResultSerializer extends XmlAdapter<ParametricSearchResultType, List<Map<String, Integer>>> {
@Override
public ParametricSearchResultType marshal(final List<Map<String, Integer>> data) throws Exception {
ParametricSearchResultType result = new ParametricSearchResultType();
for (Map<String, Integer> aMap : data) {
ParametricFilterType filters = new ParametricFilterType();
filters.mName = "test";
for (Map.Entry<String, Integer> anEntry : aMap.entrySet()) {
ParametricMapEntryType entry = new ParametricMapEntryType();
entry.mValue = anEntry.getKey();
entry.mCount = anEntry.getValue();
filters.mFilterAllEntries.add(entry);
}
result.allFilters.add(filters);
}
return result;
}
@Override
public List<Map<String, Integer>> unmarshal(final ParametricSearchResultType data) throws Exception {
return null;
}
}
ParametricSearchResultTester
public class ParametricSearchResultTester {
ParametricSearchResult mResult;
@Before
public void setUp() throws Throwable {
mResult = new ParametricSearchResult();
mResult.addFilterFieldsAndCounts("CUSTOM_YEAR", "2012", 10);
mResult.addFilterFieldsAndCounts("CUSTOM_YEAR", "2011", 8);
mResult.addFilterFieldsAndCounts("ABCD", "2011", 4);
}
@After
public void tearDown() throws Throwable {
mResult = null;
}
@Test
public void testThatMarshallingWorks() throws Throwable {
JAXBContext context = JAXBContext.newInstance(ParametricSearchResult.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(mResult, System.out);
}
}
より多くのドキュメントを読んだ後、コードにいくつかの変更を加え、それらの変更を行った後、出力としてこれになりました
<parametricSearchResult>
<allFilters>
<name>custom_year</name>
<name>abcd</name>
</allFilters>
<allFields>
<filters>
<field>
<value count="10">2012</value>
<value count="8">2011</value>
</field>
<name>test</name>
</filters>
<filters>
<field>
<value count="4">2011</value>
</field>
<name>test</name>
</filters>
</allFields>
</parametricSearchResult>
ほぼ完了ですが、要素のクリーンアップと再配置が必要です。ここで他に何をすべきかわからない。