001
002 /*
003 * Copyright (C) 2011 Archie L. Cobbs. All rights reserved.
004 *
005 * $Id: IdMappingMarshaller.java 292 2012-02-19 21:14:45Z archie.cobbs $
006 */
007
008 package org.dellroad.stuff.jibx;
009
010 import java.io.IOException;
011 import java.util.concurrent.Callable;
012
013 import javax.xml.transform.Result;
014 import javax.xml.transform.Source;
015
016 import org.dellroad.stuff.java.IdGenerator;
017 import org.springframework.beans.factory.InitializingBean;
018 import org.springframework.oxm.Marshaller;
019 import org.springframework.oxm.Unmarshaller;
020 import org.springframework.oxm.jibx.JibxMarshaller;
021
022 /**
023 * Wrapper for Spring's {@link JibxMarshaller} that performs marshalling and unmarshalling operations
024 * within an invocation of {@link IdGenerator#run IdGenerator.run()}. Simply set your
025 * normal {@link JibxMarshaller} to the {@linkplain #setJibxMarshaller jibxMarshaller}
026 * property and use this class in its place.
027 *
028 * <p>
029 * This is required when marshalling with JiBX mappings that utilize {@link IdMapper}.
030 *
031 * @see IdMapper
032 */
033 public class IdMappingMarshaller implements Marshaller, Unmarshaller, InitializingBean {
034
035 private JibxMarshaller jibxMarshaller;
036
037 /**
038 * Configure the nested {@link JibxMarshaller}. Required property.
039 */
040 public void setJibxMarshaller(JibxMarshaller jibxMarshaller) {
041 this.jibxMarshaller = jibxMarshaller;
042 }
043
044 @Override
045 public void afterPropertiesSet() throws Exception {
046 if (this.jibxMarshaller == null)
047 throw new Exception("null jibxMarshaller");
048 }
049
050 /**
051 * Invokdes {@link JibxMarshaller#marshal JibxMarshaller.marshal()} on the configured
052 * {@link JibxMarshaller} within an invocation of {@link IdGenerator#run(Callable) IdGenerator.run()}.
053 */
054 @Override
055 public void marshal(final Object graph, final Result result) throws IOException {
056 try {
057 IdGenerator.run(new Callable<Void>() {
058 @Override
059 public Void call() throws Exception {
060 IdMappingMarshaller.this.jibxMarshaller.marshal(graph, result);
061 return null;
062 }
063 });
064 } catch (Exception e) {
065 this.unwrapException(e);
066 }
067 }
068
069 /**
070 * Invokdes {@link JibxMarshaller#unmarshal JibxMarshaller.unmarshal()} on the configured
071 * {@link JibxMarshaller} within an invocation of {@link IdGenerator#run(Callable) IdGenerator.run()}.
072 */
073 @Override
074 public Object unmarshal(final Source source) throws IOException {
075 try {
076 return IdGenerator.run(new Callable<Object>() {
077 @Override
078 public Object call() throws Exception {
079 return IdMappingMarshaller.this.jibxMarshaller.unmarshal(source);
080 }
081 });
082 } catch (Exception e) {
083 this.unwrapException(e);
084 return null; // never reached
085 }
086 }
087
088 @Override
089 public boolean supports(Class<?> type) {
090 return this.jibxMarshaller.supports(type);
091 }
092
093 private void unwrapException(Exception e) throws IOException {
094 if (e instanceof IOException)
095 throw (IOException)e.getCause();
096 if (e instanceof RuntimeException)
097 throw (RuntimeException)e;
098 throw new RuntimeException(e);
099 }
100 }
101