View Javadoc
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 }