View Javadoc

1   /*
2    * jcurl java curling software framework http://www.jcurl.org
3    * Copyright (C) 2005-2009 M. Rohrmoser
4    * 
5    * This program is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License as published by the
7    * Free Software Foundation; either version 2 of the License, or (at your
8    * option) any later version.
9    * 
10   * This program is distributed in the hope that it will be useful, but
11   * WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13   * Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License along
16   * with this program; if not, write to the Free Software Foundation, Inc.,
17   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18   */
19  package org.jcurl.core.xsio;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.io.Reader;
25  import java.io.Writer;
26  import java.util.regex.Matcher;
27  import java.util.regex.Pattern;
28  
29  import org.jcurl.core.api.Measure;
30  import org.jcurl.core.api.Rock;
31  import org.jcurl.core.api.RockDouble;
32  import org.jcurl.core.impl.BisectionCollissionDetector;
33  import org.jcurl.core.impl.CollissionSpin;
34  import org.jcurl.core.impl.CurlerNoCurl;
35  import org.jcurl.core.impl.CurveManager;
36  import org.jcurl.core.impl.CurveStill;
37  import org.jcurl.core.impl.CurveStoreImpl;
38  import org.jcurl.core.impl.CurveTransformed;
39  import org.jcurl.core.impl.NewtonCollissionDetector;
40  import org.jcurl.core.impl.NewtonStopDetector;
41  import org.jcurl.core.impl.StoredTrajectorySet;
42  import org.jcurl.core.io.IONode;
43  import org.jcurl.core.io.IOTrajectories;
44  import org.jcurl.core.io.JCurlSerializer.Engine;
45  import org.jcurl.math.CurveCombined;
46  import org.jcurl.math.PolynomeCurve;
47  import org.jcurl.math.CurveCombined.Part;
48  
49  import com.thoughtworks.xstream.XStream;
50  import com.thoughtworks.xstream.converters.Converter;
51  import com.thoughtworks.xstream.converters.SingleValueConverter;
52  
53  /**
54   * Uses the great {@link XStream} for serialization.
55   * <p>
56   * To be extensible the configuration ({@link XStream#registerConverter(Converter)}
57   * and {@link XStream#alias(String, Class)}) should be applied by
58   * implementations of an interface and the service provider plugin mechanism.
59   * </p>
60   * 
61   * @author <a href="mailto:m@jcurl.org">M. Rohrmoser </a>
62   * @version $Id:XStreamSerializer.java 752 2007-12-09 22:49:16Z mrohrmoser $
63   */
64  public class XStreamSerializer implements Engine {
65  
66  	private static class DoubleArrayConverter implements SingleValueConverter {
67  
68  		@SuppressWarnings("unchecked")
69  		public boolean canConvert(final Class arg0) {
70  			return double[].class.isAssignableFrom(arg0);
71  		}
72  
73  		public Object fromString(final String s) {
74  			final String[] p = s.split(" ");
75  			final double[] d = new double[p.length];
76  			for (int i = 0; i < d.length; i++)
77  				d[i] = Double.parseDouble(p[i]);
78  			return d;
79  		}
80  
81  		public String toString(final Object obj) {
82  			final double[] d = (double[]) obj;
83  			final StringBuilder s = new StringBuilder();
84  			for (final double element : d)
85  				s.append(element).append(' ');
86  			return s.toString().trim();
87  		}
88  	}
89  
90  	static class MeasureConverter implements SingleValueConverter {
91  
92  		@SuppressWarnings("unchecked")
93  		public boolean canConvert(final Class arg0) {
94  			return Measure.class.isAssignableFrom(arg0);
95  		}
96  
97  		public Object fromString(final String s) {
98  			return Measure.parse(s);
99  		}
100 
101 		public String toString(final Object obj) {
102 			final Measure d = (Measure) obj;
103 			final StringBuilder s = new StringBuilder();
104 			s.append(d.value).append(" ").append(d.unit);
105 			return s.toString();
106 		}
107 	}
108 
109 	static class RockConverter implements SingleValueConverter {
110 		static final String num = "-?[0-9]+(?:[.][0-9]+)?(?:e-?[0-9]+)?";
111 
112 		static final Pattern p = Pattern.compile("(" + num + ") (" + num
113 				+ ") (" + num + ")");
114 
115 		@SuppressWarnings("unchecked")
116 		public boolean canConvert(final Class arg0) {
117 			return Rock.class.isAssignableFrom(arg0);
118 		}
119 
120 		public Object fromString(final String s) {
121 			final Matcher m = p.matcher(s);
122 			if (!m.matches())
123 				throw new IllegalStateException();
124 			return new RockDouble(Double.parseDouble(m.group(1)), Double
125 					.parseDouble(m.group(2)), Double.parseDouble(m.group(3)));
126 		}
127 
128 		public String toString(final Object obj) {
129 			final Rock d = (Rock) obj;
130 			final StringBuilder s = new StringBuilder();
131 			s.append(d.getX()).append(" ");
132 			s.append(d.getY()).append(" ");
133 			s.append(d.getA());
134 			return s.toString();
135 		}
136 	}
137 
138 	private final XStream xs;
139 
140 	public XStreamSerializer() {
141 		xs = new XStream();
142 		registerConverter(xs);
143 		registerAliases(xs);
144 	}
145 
146 	public IONode read(final InputStream src) throws IOException {
147 		return (IONode) xs.fromXML(src);
148 	}
149 
150 	public IONode read(final InputStream src, final IONode dst) {
151 		return (IONode) xs.fromXML(src, dst);
152 	};
153 
154 	public IONode read(final InputStream src, final String name,
155 			final IONode dst) throws IOException {
156 		return read(src, dst);
157 	}
158 
159 	public IONode read(final Reader src, final IONode dst) {
160 		return (IONode) xs.fromXML(src, dst);
161 	}
162 
163 	public IONode read(final String s) {
164 		return (IONode) xs.fromXML(s);
165 	}
166 
167 	/**
168 	 * Map all basic concepts to be a little bit robust against refactorings.
169 	 * Make the aliases upper- or camelcase to distinguish them from properties.
170 	 */
171 	protected XStream registerAliases(final XStream xs) {
172 		xs.alias("measure", Measure.class);
173 		xs.alias("rock", RockDouble.class);
174 		// 
175 		xs.alias("IODocument", IONode.class);
176 		xs.alias("IOTrajectories", IOTrajectories.class);
177 		// 
178 		xs.alias("StoredTrajectory", StoredTrajectorySet.class);
179 		xs.alias("CombinedCurve", CurveCombined.class);
180 		xs.alias("part", Part.class);
181 		xs.alias("TransformedCurve", CurveTransformed.class);
182 		xs.alias("PolynomeCurve", PolynomeCurve.class);
183 		xs.alias("PointCurve", CurveStill.class);
184 		// 
185 		xs.alias("CurveManager", CurveManager.class);
186 		xs.alias("CurveStore", CurveStoreImpl.class);
187 		xs.alias("NewtonStopDetector", NewtonStopDetector.class);
188 		xs.alias("CollissionSpin", CollissionSpin.class);
189 		xs.alias("NewtonCollissionDetector", NewtonCollissionDetector.class);
190 		xs.alias("BisectionCollissionDetector",
191 				BisectionCollissionDetector.class);
192 		xs.alias("NoCurlCurler", CurlerNoCurl.class);
193 		return xs;
194 	}
195 
196 	protected XStream registerConverter(final XStream xs) {
197 		xs.registerConverter(new MeasureConverter());
198 		xs.registerConverter(new DoubleArrayConverter());
199 		xs.registerConverter(new RockConverter());
200 		return xs;
201 	}
202 
203 	public String write(final IONode src) {
204 		return xs.toXML(src);
205 	}
206 
207 	public void write(final IONode src, final OutputStream dst) {
208 		xs.toXML(src, dst);
209 	}
210 
211 	public void write(final IONode src, final Writer dst) {
212 		xs.toXML(src, dst);
213 	}
214 }