1 /*
2 * Copyright 2008, 2009 Ange Optimization ApS
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package eu.simuline.octave.io.spi;
17
18 import java.io.IOException;
19 import java.io.Writer;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 import javax.imageio.spi.ServiceRegistry;
25
26 import eu.simuline.octave.type.OctaveObject;
27
28 /**
29 * Service Provider Interface for the IO handler
30 * that can write {@link OctaveObject}s.
31 * The according implementations
32 * are in package {@link eu.simuline.octave.io.impl}
33 * and extend this class.
34 * These classes are registered in the jar-file
35 * under <code>META-INF/services/eu.simuline.octave.io.OctaveDataWriter</code>.
36 *
37 * @param <T>
38 * the type extending {@link OctaveObject} this writer can write.
39 */
40 public abstract class OctaveDataWriter<T extends OctaveObject> {
41
42 /**
43 * Maps the {@link #javaType()}
44 * which represents an octave type
45 * of an {@link OctaveDataWriter} to the {@link OctaveDataWriter} itself
46 * which is able to write the octave type to a writer.
47 */
48 private static
49 Map<Class<? extends OctaveObject>, OctaveDataWriter<?>> wRITERS;
50
51 /**
52 * @param <T>
53 * @param type
54 * @return The OctaveDataWriter or null if it does not exist
55 */
56 @SuppressWarnings("unchecked")
57 public static <T extends OctaveObject>
58 OctaveDataWriter<T> getOctaveDataWriter(final T type) {
59 initWriterIfNecessary();
60 return (OctaveDataWriter<T>) wRITERS.get(type.getClass());
61 }
62
63 //synchronized
64 private static synchronized void initWriterIfNecessary() {
65 if (wRITERS != null) {
66 return;
67 }
68 wRITERS = new HashMap
69 <Class<? extends OctaveObject>, OctaveDataWriter<?>>();
70 @SuppressWarnings("rawtypes")
71 final Iterator<OctaveDataWriter> sp =
72 ServiceRegistry.lookupProviders(OctaveDataWriter.class);
73 OctaveDataWriter<?> odw, odwOrg;
74 while (sp.hasNext()) {
75 odw = sp.next();
76 assert odw != null;
77 odwOrg = wRITERS.put(odw.javaType(), odw);
78 if (odwOrg != null) {
79 // Here, for one type more than one writer is defined.
80 throw new IllegalStateException
81 ("Java type " + odw.javaType() +
82 " has writers of type " + odw.getClass() +
83 " and " + odwOrg.getClass() + ". ");
84 }
85 }
86 }
87
88 /**
89 * Could be OctaveScalar or OctaveMatrix.
90 *
91 * @return the {@link Class} of the {@link OctaveObject}
92 * that this IO handler loads and saves
93 */
94 public abstract Class<T> javaType();
95
96 /**
97 * @param writer
98 * the Writer to write to
99 * @param octaveType
100 * the value to write
101 * @throws IOException
102 */
103 public abstract void write(Writer writer, T octaveType) throws IOException;
104
105 }