main.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package main;
  2. import (
  3. "io";
  4. "os";
  5. "fmt";
  6. "time";
  7. "strings";
  8. "reflect";
  9. "net/url";
  10. "net/http";
  11. "encoding/json";
  12. "github.com/xaionaro/gorm";
  13. _ "github.com/mattn/go-sqlite3";
  14. models "devel.mephi.ru/ut/download-publications-models"
  15. );
  16. type Config struct {
  17. DBPath string;
  18. PublicationsURL string;
  19. AuthorshipsURL string;
  20. };
  21. func stripChars(str, chr string) string { // The function is from here: https://www.rosettacode.org/wiki/Strip_a_set_of_characters_from_a_string#Go
  22. return strings.Map(func(r rune) rune {
  23. if strings.IndexRune(chr, r) < 0 {
  24. return r
  25. }
  26. return -1
  27. }, str)
  28. }
  29. func getJson(urlStr string) (r []map[string]interface{}, err error) {
  30. var reader io.Reader;
  31. u, e := url.Parse(urlStr);
  32. if (e == nil && u.Scheme != "") {
  33. resp, err := http.Get(urlStr);
  34. if (err != nil) {
  35. return r, err;
  36. }
  37. defer resp.Body.Close();
  38. reader = resp.Body;
  39. } else {
  40. file, err := os.Open(urlStr);
  41. if (err != nil) {
  42. return r, err;
  43. }
  44. defer file.Close();
  45. reader = file;
  46. }
  47. decoder := json.NewDecoder(reader);
  48. decoder.UseNumber();
  49. decoder.Decode(&r);
  50. return r, nil;
  51. }
  52. func getConfig() (config Config) {
  53. file, err := os.Open("config.json");
  54. if (err != nil) {
  55. fmt.Errorf("Config file error: %v", err.Error());
  56. os.Exit(-1);
  57. }
  58. defer file.Close();
  59. decoder := json.NewDecoder(file);
  60. decoder.Decode(&config);
  61. //fmt.Printf("config: %v\n", config);
  62. return config;
  63. }
  64. func parseValue(in interface{}) (out interface{}) {
  65. switch v := in.(type) {
  66. case json.Number:
  67. i,_ := v.Int64();
  68. return int(i);
  69. case string:
  70. t,e := time.Parse("2006-01-02T15:04:05.000-07:00", v); //????-??-??T??:??:??.???+??:??
  71. if (e == nil) {
  72. return t;
  73. }
  74. break;
  75. }
  76. return in;
  77. }
  78. // TODO: make this function recursive
  79. func parse(datasValueMap []map[string]interface{}, dataSample interface{}) (interface{}) {
  80. dataFieldMap := make(map[string]string);
  81. dataValue := reflect.ValueOf(dataSample).Elem();
  82. dataType := dataValue.Type();
  83. //datas := reflect.MakeSlice(reflect.SliceOf(dataType), 0, 0)
  84. var datas []interface{}
  85. // Getting fields names and making a map of ToLower(Name) -> Name
  86. fields := dataValue.NumField();
  87. for i:=0; i<fields; i++ {
  88. field := dataType.Field(i);
  89. dataFieldMap[strings.ToLower(field.Name)] = field.Name;
  90. if (field.Type.Kind() == reflect.Struct) {
  91. fieldValue := dataValue.Field(i);
  92. subFields := fieldValue.NumField();
  93. for i:=0; i<subFields; i++ {
  94. subField := field.Type.Field(i);
  95. dataFieldMap[strings.ToLower(subField.Name)] = subField.Name;
  96. }
  97. }
  98. }
  99. // Setting values
  100. dataPtr := reflect.New(dataType);
  101. data := dataPtr.Elem();
  102. for _,row := range datasValueMap {
  103. data.Set(reflect.Zero(dataType));
  104. for k,v := range row {
  105. sk := strings.ToLower(stripChars(k, "_"));
  106. field := data.FieldByName(dataFieldMap[ sk ]);
  107. switch vt := v.(type) {
  108. case map[string]interface{}:
  109. for k,v := range vt {
  110. sk := strings.ToLower(stripChars(k, "_"));
  111. field.FieldByName(dataFieldMap[ sk ]).Set(reflect.ValueOf(parseValue( v )));
  112. }
  113. continue;
  114. }
  115. field.Set(reflect.ValueOf(parseValue( v )));
  116. }
  117. datas = append(datas, data.Interface());
  118. }
  119. return datas
  120. }
  121. func getDB(config Config) (db gorm.DB, err error) {
  122. connectionString := "file:"+config.DBPath+"?cache=shared&mode=rwc"
  123. //fmt.Printf("connectionString: %v\n", connectionString);
  124. db, err = gorm.Open("sqlite3", connectionString);
  125. if (err != nil) {
  126. return db, err;
  127. }
  128. db.DB().SetMaxIdleConns(1);
  129. db.SingularTable(true);
  130. return db, err;
  131. }
  132. func main() {
  133. config := getConfig();
  134. db,err := getDB(config);
  135. if (err != nil) {
  136. fmt.Errorf("DB error: %v", err.Error());
  137. os.Exit(-1);
  138. }
  139. publicationsValueMap, err := getJson(config.PublicationsURL);
  140. if (err != nil) {
  141. fmt.Errorf("Error: %v", err.Error());
  142. os.Exit(-1);
  143. }
  144. authorshipsValueMap, err := getJson(config.AuthorshipsURL);
  145. if (err != nil) {
  146. fmt.Errorf("Error: %v", err.Error());
  147. os.Exit(-1);
  148. }
  149. //os.Exit(-1);
  150. publications := parse(publicationsValueMap, &models.Publication{}).([]interface{});
  151. authorships := parse(authorshipsValueMap, &models.Authorship{} ).([]interface{});
  152. //fmt.Printf("%v", publications);
  153. //fmt.Printf("%v", authorships);
  154. db.CreateTable(&models.Publication{});
  155. db.CreateTable(&models.Authorship{}).Model(&models.Authorship{}).AddUniqueIndex("authorship_uniidx", "article_id", "termit_id");
  156. transaction := db.Begin();
  157. for _,publication := range publications {
  158. row := publication.(models.Publication);
  159. transaction.Create(&row);
  160. }
  161. for _,authorship := range authorships {
  162. row := authorship.(models.Authorship);
  163. transaction.Create(&row);
  164. }
  165. transaction.Commit();
  166. os.Exit(0);
  167. }