]> git.mjollnir.org Git - moodle.git/blob
2fb5a4e7601b4b76daed0e28a7afb163483a65a4
[moodle.git] /
1 package flare.data.converters
2 {
3         import flare.data.DataField;
4         import flare.data.DataSchema;
5         import flare.data.DataSet;
6         import flare.data.DataTable;
7         import flare.data.DataUtil;
8         
9         import flash.utils.ByteArray;
10         import flash.utils.IDataInput;
11         import flash.utils.IDataOutput;
12
13         /**
14          * Converts data between delimited text (e.g., tab delimited) and
15          * flare DataSet instances.
16          */
17         public class DelimitedTextConverter implements IDataConverter
18         {
19                 private var _delim:String;
20                 
21                 public function get delimiter():String { return _delim; }
22                 public function set delimiter(d:String):void { _delim = d; }
23                 
24                 /**
25                  * Creates a new DelimitedTextConverter.
26                  * @param delim the delimiter string separating values (tab by default)
27                  */
28                 public function DelimitedTextConverter(delim:String="\t")
29                 {
30                         _delim = delim;
31                 }
32                 
33                 /**
34                  * @inheritDoc
35                  */
36                 public function read(input:IDataInput, schema:DataSchema=null):DataSet
37                 {
38                         return parse(input.readUTFBytes(input.bytesAvailable), schema);
39                 }
40                 
41                 /**
42                  * Converts data from a tab-delimited string into ActionScript objects.
43                  * @param input the loaded input data
44                  * @param schema a data schema describing the structure of the data.
45                  *  Schemas are optional in many but not all cases.
46                  * @param data an array in which to write the converted data objects.
47                  *  If this value is null, a new array will be created.
48                  * @return an array of converted data objects. If the <code>data</code>
49                  *  argument is non-null, it is returned.
50                  */
51                 public function parse(text:String, schema:DataSchema=null):DataSet
52                 {
53                         var tuples:Array = [];
54                         var lines:Array = text.split(/\r\n|\r|\n/);
55                         
56                         if (schema == null) {
57                                 schema = inferSchema(lines);
58                         }
59                         
60                         var i:int = schema.hasHeader ? 1 : 0;
61                         for (; i<lines.length; ++i) {
62                                 var line:String = lines[i];
63                                 if (line.length == 0) break;
64                                 var tok:Array = line.split(_delim);
65                                 var tuple:Object = {};
66                                 for (var j:int=0; j<schema.numFields; ++j) {
67                                         var field:DataField = schema.getFieldAt(j);
68                                         tuple[field.name] = DataUtil.parseValue(tok[j], field.type);
69                                 }
70                                 tuples.push(tuple);
71                         }
72                         return new DataSet(new DataTable(tuples, schema));
73                 }
74                 
75                 /**
76                  * @inheritDoc
77                  */
78                 public function write(data:DataSet, output:IDataOutput=null):IDataOutput
79                 {
80                         if (output==null) output = new ByteArray();
81                         var tuples:Array = data.nodes.data;
82                         var schema:DataSchema = data.nodes.schema;
83                         
84                         for each (var tuple:Object in tuples) {
85                                 var i:int = 0, s:String;
86                                 if (schema == null) {
87                                         for (var name:String in tuple) {
88                                                 if (i>0) output.writeUTFBytes(_delim);
89                                                 output.writeUTFBytes(String(tuple[name])); // TODO: proper string formatting
90                                                 ++i;
91                                         }
92                                 } else {
93                                         for (;i<schema.numFields; ++i) {
94                                                 var f:DataField = schema.getFieldAt(i);
95                                                 if (i>0) output.writeUTFBytes(_delim);
96                                                 output.writeUTFBytes(String(tuple[f.name])); // TODO proper string formatting
97                                         }
98                                 }
99                                 output.writeUTFBytes("\n");
100                         }
101                         return output;
102                 }
103                 
104                 /**
105                  * Infers the data schema by checking values of the input data.
106                  * @param lines an array of lines of input text
107                  * @return the inferred schema
108                  */
109                 protected function inferSchema(lines:Array):DataSchema
110                 {
111                         var header:Array = lines[0].split(_delim);
112                         var types:Array = new Array(header.length);
113                         
114                         // initialize data types
115                         var tok:Array = lines[1].split(_delim);
116                         for (var col:int=0; col<header.length; ++col) {
117                                 types[col] = DataUtil.type(tok[col]);
118                         }
119                         
120                         // now process data to infer types
121                         for (var i:int = 2; i<lines.length; ++i) {
122                                 tok = lines[i].split(_delim);
123                                 for (col=0; col<tok.length; ++col) {
124                                         if (types[col] == -1) continue;
125                                         var type:int = DataUtil.type(tok[col]);
126                                         if (types[col] != type) {
127                                                 types[col] = -1;
128                                         }
129                                 }
130                         }
131                         
132                         // finally, we create the schema
133                         var schema:DataSchema = new DataSchema();
134                         schema.hasHeader = true;
135                         for (col=0; col<header.length; ++col) {
136                                 schema.addField(new DataField(header[col],
137                                         types[col]==-1 ? DataUtil.STRING : types[col]));
138                         }
139                         return schema;
140                 }
141                 
142         } // end of class DelimitedTextConverter
143 }