View Javadoc
1   package org.thegalactic.context.io;
2   
3   /*
4    * ContextSerializerSLF.java
5    *
6    * Copyright: 2010-2015 Karell Bertet, France
7    * Copyright: 2015-2016 The Galactic Organization, France
8    *
9    * License: http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html CeCILL-B license
10   *
11   * This file is part of java-lattices.
12   * You can redistribute it and/or modify it under the terms of CeCILL-B license.
13   */
14  import java.io.BufferedReader;
15  import java.io.BufferedWriter;
16  import java.io.IOException;
17  import java.util.ArrayList;
18  import java.util.List;
19  import java.util.SortedSet;
20  import java.util.StringTokenizer;
21  import java.util.TreeMap;
22  import java.util.TreeSet;
23  
24  import org.thegalactic.context.Context;
25  import org.thegalactic.io.Reader;
26  import org.thegalactic.io.Writer;
27  
28  /**
29   * This class defines the way for reading a context from a slf file.
30   *
31   */
32  public final class ContextSerializerSLF implements Reader<Context>, Writer<Context> {
33  
34      /**
35       * String extension.
36       */
37      private static final String EXTENSION = "slf";
38  
39      /**
40       * Header.
41       */
42      private static final String HEADER = "[Lattice]";
43  
44      /**
45       * Objects.
46       */
47      private static final String OBJECTS = "[Objects]";
48  
49      /**
50       * Attributes.
51       */
52      private static final String ATTRIBUTES = "[Attributes]";
53  
54      /**
55       * relation.
56       */
57      private static final String RELATION = "[relation]";
58  
59      /**
60       * Misformed exception.
61       */
62      private static final String MISFORMED = "Misformated SLF file.";
63  
64      /**
65       * The singleton INSTANCE.
66       */
67      private static final ContextSerializerSLF INSTANCE = new ContextSerializerSLF();
68  
69      /**
70       * Return the singleton INSTANCE of this class.
71       *
72       * @return the singleton INSTANCE
73       */
74      public static ContextSerializerSLF getINSTANCE() {
75          return INSTANCE;
76      }
77  
78      /**
79       * Register this class for reading and writing .slf files.
80       */
81      public static void register() {
82          ContextIOFactory.getInstance().registerReader(ContextSerializerSLF.getINSTANCE(), EXTENSION);
83          ContextIOFactory.getInstance().registerWriter(ContextSerializerSLF.getINSTANCE(), EXTENSION);
84      }
85  
86      /**
87       * This class is not designed to be publicly instantiated.
88       */
89      private ContextSerializerSLF() {
90      }
91  
92      /**
93       * Read a context from a file.
94       *
95       * The following format is respected:
96       *
97       * The number of objects and observation on two separated lines The list of
98       * objects on seprated lines The list of attributes on separated lines
99       *
100      * then, for each observations, the list of its intent on a line, written
101      * like 0 1 0
102      *
103      * ~~~
104      * [Lattice]
105      * 2
106      * 3
107      * [Objects]
108      * 1 2
109      * [Attributes]
110      * a b c
111      * [relation]
112      * 0 1 0
113      * 1 1 0
114      * ~~~
115      *
116      * @param context a context to read
117      * @param file    a file
118      *
119      * @throws IOException When an IOException occurs
120      *
121      * @todo use StreamTokenizer
122      */
123     public void read(final Context context, final BufferedReader file) throws IOException {
124 
125         if (!file.readLine().equals(HEADER)) {
126             throw new IOException(MISFORMED);
127         }
128 
129         final int countObservations = Integer.parseInt(file.readLine());
130         final int countAttributes = Integer.parseInt(file.readLine());
131 
132         if (!file.readLine().equals(OBJECTS)) {
133             throw new IOException(MISFORMED);
134         }
135 
136         final List<Comparable> observations = new ArrayList(countObservations);
137         final List<Comparable> attributes = new ArrayList(countAttributes);
138         final TreeMap<Comparable, TreeSet<Comparable>> intent = new TreeMap();
139         final TreeMap<Comparable, TreeSet<Comparable>> extent = new TreeMap();
140 
141         String line = file.readLine();
142         while (!ATTRIBUTES.equals(line)) {
143             observations.add(line);
144             intent.put(line, new TreeSet());
145             line = file.readLine();
146         }
147         line = file.readLine();
148         while (!RELATION.equals(line)) {
149             attributes.add(line);
150             extent.put(line, new TreeSet());
151             line = file.readLine();
152         }
153 
154         context.addAllToAttributes(new TreeSet(attributes));
155         context.addAllToObservations(new TreeSet(observations));
156 
157         for (int i = 0; i < countObservations; i++) {
158             line = file.readLine();
159             final StringTokenizer tokenizer = new StringTokenizer(line);
160             int count = 0;
161             while (tokenizer.hasMoreTokens()) {
162                 final String next = tokenizer.nextToken();
163                 if ("1".equals(next)) {
164                     context.addExtentIntent(observations.get(i), attributes.get(count));
165                 }
166                 count++;
167             }
168             if (count != countAttributes) {
169                 throw new IOException(MISFORMED);
170             }
171         }
172         context.setBitSets();
173     }
174 
175     /**
176      * Write a context to a file.
177      *
178      * The Standard Lattice Format SLF format file is respected :
179      *
180      * The following format is respected:
181      *
182      * The number of objects and observation on two separated lines The list of
183      * objects on seprated lines The list of attributes on separated lines
184      *
185      * then, for each observations, the list of its intent on a line, written
186      * like 0 1 0
187      *
188      * ~~~
189      * [Lattice]
190      * 2
191      * 3
192      * [Objects]
193      * 1
194      * 2
195      * [Attributes]
196      * a
197      * b
198      * c
199      * [relation]
200      * 0 1 0
201      * 1 1 0
202      * ~~~
203      *
204      * @param context a context to write
205      * @param file    a file
206      *
207      * @throws IOException When an IOException occurs
208      */
209     public void write(final Context context, final BufferedWriter file) throws IOException {
210         file.write(HEADER);
211         file.newLine();
212         file.write(String.valueOf(context.getObservations().size()));
213         file.newLine();
214         file.write(String.valueOf(context.getAttributes().size()));
215         file.newLine();
216         file.write(OBJECTS);
217         file.newLine();
218         for (final Comparable observation : context.getObservations()) {
219             file.write(observation.toString());
220             file.newLine();
221         }
222         file.write(ATTRIBUTES);
223         file.newLine();
224         for (final Comparable attribute : context.getAttributes()) {
225             file.write(attribute.toString());
226             file.newLine();
227         }
228         file.write(RELATION);
229         file.newLine();
230         for (final Comparable observation : context.getObservations()) {
231             final SortedSet<Comparable> intent = context.getIntent(observation);
232             for (final Comparable attribute : context.getAttributes()) {
233                 if (intent.contains(attribute)) {
234                     file.write("1 ");
235                 } else {
236                     file.write("0 ");
237                 }
238             }
239             file.newLine();
240         }
241     }
242 }