1 #include "gretl_func.h"
2 #include "gretl_string_table.h" /* for csvdata */
3 #include "csvdata.h"
4 
5 /* call hansl code from dbnomics.gfn to get a series bundle */
6 
get_dbn_series_bundle(const char * datacode,int * err)7 static gretl_bundle *get_dbn_series_bundle (const char *datacode,
8 					    int *err)
9 {
10     gretl_bundle *b = NULL;
11     fncall *fc;
12 
13     fc = get_pkg_function_call("dbnomics_get_series", "dbnomics", NULL);
14     if (fc == NULL) {
15 	*err = E_DATA;
16     } else {
17 	*err = push_anon_function_arg(fc, GRETL_TYPE_STRING,
18 				      (void *) datacode);
19 	if (!*err) {
20 	    *err = gretl_function_exec(fc, GRETL_TYPE_BUNDLE, NULL,
21 				       &b, NULL, NULL);
22 	}
23 	if (b != NULL) {
24 	    int dberr = gretl_bundle_get_int(b, "error", NULL);
25 
26 	    if (dberr) {
27 		const char *msg =
28 		    gretl_bundle_get_string(b, "errmsg", NULL);
29 
30 		*err = E_DATA;
31 		if (msg != NULL) {
32 		    gretl_errmsg_set(msg);
33 		} else {
34 		    gretl_errmsg_sprintf(_("%s: no data found"), datacode);
35 		}
36 		gretl_bundle_destroy(b);
37 		b = NULL;
38 	    }
39 	} else if (!*err) {
40 	    gretl_errmsg_sprintf(_("%s: no data found"), datacode);
41 	    *err = E_DATA;
42 	}
43     }
44 
45     return b;
46 }
47 
48 struct dbn_sorter {
49     const char *s;
50     int t;
51 };
52 
write_dbn_csv(char ** S,int T,gretl_matrix * v,struct dbn_sorter * ds,FILE * fp)53 static int write_dbn_csv (char **S, int T,
54 			  gretl_matrix *v,
55 			  struct dbn_sorter *ds,
56 			  FILE *fp)
57 {
58     int t, i;
59 
60     if (gretl_is_null_matrix(v)) {
61 	gretl_errmsg_set("Failed to get data from dbnomics");
62 	return E_DATA;
63     }
64 
65     gretl_push_c_numeric_locale();
66 
67     fputs("obs dbnomics_data\n", fp);
68     for (t=0; t<T; t++) {
69 	i = (ds != NULL)? ds[t].t : t;
70 	if (i >= v->rows || na(v->val[i])) {
71 	    fprintf(fp, "%s NA\n", S[i]);
72 	} else {
73 	    fprintf(fp, "%s %.12g\n", S[i], v->val[i]);
74 	}
75     }
76 
77     gretl_pop_c_numeric_locale();
78 
79     return 0;
80 }
81 
dbtcomp(const void * a,const void * b)82 static int dbtcomp (const void *a, const void *b)
83 {
84     const struct dbn_sorter *ds1 = a, *ds2 = b;
85 
86     return strcmp(ds1->s, ds2->s);
87 }
88 
89 /* remedial code for the case where the "periods" in
90    JSON from dbnomics are not actually in temporal
91    order
92 */
93 
maybe_reorder_dbn_data(char ** S,int T,gretl_matrix * v,FILE * fp)94 static int maybe_reorder_dbn_data (char **S, int T,
95 				   gretl_matrix *v,
96 				   FILE *fp)
97 {
98     struct dbn_sorter *ds;
99     int t, err = 0;
100 
101     ds = malloc(T * sizeof *ds);
102     if (ds == NULL) {
103 	return E_ALLOC;
104     }
105 
106     for (t=0; t<T; t++) {
107 	ds[t].s = S[t];
108 	ds[t].t = t;
109     }
110 
111     qsort(ds, T, sizeof *ds, dbtcomp);
112     err = write_dbn_csv(S, T, v, ds, fp);
113     free(ds);
114 
115     return err;
116 }
117 
118 /* write the info from @P (periods) and @v (values) to
119    CSV, then grab it back using the gretl CSV reader
120    to populate @dbset
121 */
122 
dbn_dset_from_csv(DATASET * dbset,gretl_array * P,gretl_matrix * v)123 static int dbn_dset_from_csv (DATASET *dbset,
124 			      gretl_array *P,
125 			      gretl_matrix *v)
126 {
127     PRN *prn = NULL;
128     gchar *fname;
129     FILE *fp;
130     int T, err = 0;
131 
132 #if DB_DEBUG
133     prn = gretl_print_new(GRETL_PRINT_STDERR, NULL);
134 #endif
135 
136     fname = g_strdup_printf("%sdbnomics_tmp.txt", gretl_dotdir());
137     fp = gretl_fopen(fname, "wb");
138 
139     if (fp == NULL) {
140 	err = E_FOPEN;
141     } else {
142 	char **S = gretl_array_get_strings(P, &T);
143 
144 	err = write_dbn_csv(S, T, v, NULL, fp);
145 	fclose(fp);
146 
147 	if (!err) {
148 	    err = import_csv(fname, dbset, OPT_NONE, prn);
149 	}
150 	if (!err && !dataset_is_time_series(dbset)) {
151 	    /* try again, after sorting by "period" strings */
152 	    gretl_remove(fname);
153 	    fp = gretl_fopen(fname, "wb");
154 	    if (fp == NULL) {
155 		err = E_FOPEN;
156 	    } else {
157 		err = maybe_reorder_dbn_data(S, T, v, fp);
158 		fclose(fp);
159 		free_Z(dbset);
160 		clear_datainfo(dbset, CLEAR_FULL);
161 		if (!err) {
162 		    err = import_csv(fname, dbset, OPT_NONE, prn);
163 		}
164 	    }
165 	}
166 	gretl_remove(fname);
167     }
168 
169     g_free(fname);
170     gretl_print_destroy(prn);
171 
172     return err;
173 }
174 
175 /* obtain a dbnomics series bundle and process the info
176    it contains into a SERIESINFO struct
177 */
178 
179 static int
get_dbnomics_series_info(const char * id,SERIESINFO * sinfo)180 get_dbnomics_series_info (const char *id, SERIESINFO *sinfo)
181 {
182     gretl_bundle *b;
183     DATASET dbset = {0};
184     gretl_array *P;
185     gretl_matrix *v;
186     int T, err = 0;
187 
188     /* FIXME check for required form PROV/DSET/SERIES */
189 
190     b = get_dbn_series_bundle(id, &err);
191     if (err) {
192 	fprintf(stderr, "get_dbn_series_bundle: err=%d\n", err);
193 	goto bailout;
194     }
195 
196     T = gretl_bundle_get_int(b, "T", &err);
197     P = gretl_bundle_get_array(b, "period", &err);
198     v = gretl_bundle_get_matrix(b, "value", &err);
199     if (!err && (T <= 0 || P == NULL || v == NULL)) {
200 	fprintf(stderr, "get_dbnomics_series_info: invalid bundle content\n");
201 	err = E_DATA;
202 	goto bailout;
203     }
204 
205     /* write bundle content as CSV and use CSV reader to
206        construct a one-series dataset */
207     err = dbn_dset_from_csv(&dbset, P, v);
208 
209     if (!err) {
210 	/* transcribe info to SERIESINFO format */
211 	const char *s2 = gretl_bundle_get_string(b, "series_name", NULL);
212 	char *rawname = strrchr(id, '/') + 1;
213 	gchar *descrip;
214 
215 	sinfo->t1 = dbset.t1;
216 	sinfo->t2 = dbset.t2;
217 	sinfo->nobs = dbset.n;
218 	sinfo->pd = dbset.pd;
219 	strcpy(sinfo->stobs, dbset.stobs);
220 	strcpy(sinfo->endobs, dbset.endobs);
221 	/* set up name and description */
222 	gretl_normalize_varname(sinfo->varname, rawname, 0, 0);
223 	descrip = g_strdup_printf("%s: %s", id, s2);
224 	series_info_set_description(sinfo, descrip);
225 	g_free(descrip);
226 	/* steal the data array */
227 	sinfo->data = dbset.Z[1];
228 	dbset.Z[1] = NULL;
229     }
230 
231     free_Z(&dbset);
232     clear_datainfo(&dbset, CLEAR_FULL);
233 
234  bailout:
235 
236     gretl_bundle_destroy(b);
237 
238     return err;
239 }
240 
241 /* transfer the data stored on @sinfo into @Z */
242 
get_dbnomics_data(const char * fname,SERIESINFO * sinfo,double ** Z)243 static int get_dbnomics_data (const char *fname,
244 			      SERIESINFO *sinfo,
245 			      double **Z)
246 {
247     memcpy(Z[1], sinfo->data, sinfo->nobs * sizeof(double));
248     free(sinfo->data);
249     sinfo->data = NULL;
250 
251     return 0;
252 }
253