/*
*
*/
package org.smartly.packages.mongo.impl.io;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import org.json.JSONArray;
import org.json.JSONObject;
import org.smartly.IConstants;
import org.smartly.commons.csv.CSVFileReader;
import org.smartly.commons.csv.CSVReader;
import org.smartly.commons.util.*;
import org.smartly.packages.mongo.impl.IMongoConstants;
import org.smartly.packages.mongo.impl.StandardCodedException;
import org.smartly.packages.mongo.impl.db.GenericMongoService;
import org.smartly.packages.mongo.impl.util.MongoUtils;
import java.io.FileReader;
import java.io.StringReader;
import java.util.*;
/**
* @author angelo.geminiani
*/
public class MongoImporter {
/**
* Use this field to store localizations into single json file to import.
* 'localizations' field will be removed and localizations will be added to each collection field.<br>
* i.e. : 'localizations':[
* {'lang':'it', 'name':'un nome', 'description':'una descrizione'},
* {'lang':'en', 'name':'a name', 'description':'a description'}
* ]
*/
public static final String FIELD_LOCALIZATIONS = IMongoConstants.FIELD_LOCALIZATIONS;
public static final String FIELD_LANG = IMongoConstants.FIELD_LANG;
public static final String LANG_BASE = IMongoConstants.LANG_BASE;
// ------------------------------------------------------------------------
// variables
// ------------------------------------------------------------------------
private final GenericMongoService _srvc;
// ------------------------------------------------------------------------
// constructor
// ------------------------------------------------------------------------
public MongoImporter(final DB db, final String collName)
throws StandardCodedException {
_srvc = new GenericMongoService(db, collName, new String[0]);
}
// ------------------------------------------------------------------------
// p u b l i c
// ------------------------------------------------------------------------
//-- UTILS --//
/**
* Parse an item and search for all paths in values
*
* @param root Resource root. i.e. "/org/sf/app/package/"
* @param item Item to parse for paths in key values
*/
public static void replaceResourcePaths(final String root, final DBObject item) {
final Set<String> keys = item.keySet();
for (final String key : keys) {
final Object value = item.get(key);
if (value instanceof String && value.toString().startsWith(IConstants.FOLDER_SEPARATOR)) {
final String file = PathUtils.concat(root, value.toString());
final String text = ClassLoaderUtils.getResourceAsString(file);
if (StringUtils.hasText(text)) {
if (StringUtils.isJSON(text)) {
item.put(key, MongoUtils.parseObject(text));
} else {
item.put(key, text);
}
}
}
}
}
//-- IMPORT --//
public List<DBObject> importFromFile(final String filepath) throws Exception {
return this.importFromFile(filepath);
}
public List<DBObject> importFromFile(final String filepath,
final ImporterIterator iterator) throws Exception {
List<DBObject> result = null;
if (isCSVFile(filepath)) {
final CSVFileReader reader = new CSVFileReader(filepath);
try {
final List<Map<String, String>> data = reader.readAllAsMap(true);
result = this.doImport(data, iterator);
} catch (Throwable t) {
}
reader.close();
} else if (isJSONFile(filepath)) {
final String json = FileUtils.copyToString(new FileReader(filepath));
final JsonWrapper jsw = JsonWrapper.wrap(json);
if (jsw.isJSONArray()) {
result = this.doImport(jsw.getJSONArray(), iterator);
}
}
return null != result ? result : new ArrayList<DBObject>();
}
public List<DBObject> importFromString(final String text) throws Exception {
return this.importFromString(text, null);
}
public List<DBObject> importFromString(final String text,
final ImporterIterator iterator) throws Exception {
List<DBObject> result = null;
if (StringUtils.isJSONArray(text)) {
final JsonWrapper jsw = JsonWrapper.wrap(text);
if (jsw.isJSONArray()) {
result = this.doImport(jsw.getJSONArray(), iterator);
}
} else {
final CSVReader reader = new CSVReader();
reader.setReader(new StringReader(text));
try {
final List<Map<String, String>> data = reader.readAllAsMap(true);
result = this.doImport(data, iterator);
} catch (Throwable t) {
}
reader.close();
}
return null != result ? result : new ArrayList<DBObject>();
}
public List<DBObject> importFromResource(final String resourceName) throws Exception {
return this.importFromResource(resourceName, null);
}
public List<DBObject> importFromResource(final String resourceName,
final ImporterIterator iterator) throws Exception {
List<DBObject> result = null;
if (isCSVFile(resourceName)) {
final List<Map<String, String>> data = readCSV(resourceName);
if (null != data) {
result = this.doImport(data, iterator);
} else {
throw new Exception(
FormatUtils.format("Resource is Empty. Please, check {0} for syntax errors", resourceName));
}
} else if (isJSONFile(resourceName)) {
final JSONArray data = readJSONArray(resourceName);
if (null != data) {
result = this.doImport(data, iterator);
} else {
throw new Exception(
FormatUtils.format("Resource is Empty. Please, check {0} for syntax errors", resourceName));
}
}
return null != result ? result : new ArrayList<DBObject>();
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private List<DBObject> doImport(final List<Map<String, String>> data,
final ImporterIterator iterator) throws StandardCodedException {
final List<DBObject> result = new LinkedList<DBObject>();
for (final Map<String, String> item : data) {
final DBObject dbo = new BasicDBObject(item);
if (null != iterator) {
_srvc.upsert(iterator.importing(dbo));
} else {
_srvc.upsert(dbo);
}
result.add(dbo);
}
return result;
}
private List<DBObject> doImport(final JSONArray list,
final ImporterIterator iterator) throws Exception {
final List<DBObject> result = new LinkedList<DBObject>();
for (int i = 0; i < list.length(); i++) {
final JSONObject jso = list.getJSONObject(i);
final DBObject dbo = MongoUtils.parseObject(jso);
//-- item --//
final DBObject item;
if (null != iterator) {
item = iterator.importing(dbo);
} else {
item = dbo;
}
//-- localizations --//
List localizations = null;
if (dbo.containsField(FIELD_LOCALIZATIONS)) {
final Object obj = MongoUtils.remove(item, FIELD_LOCALIZATIONS);
if (obj instanceof List) {
localizations = (List) obj;
}
final List languages = this.doImportLocalizations(item, localizations);
if (null != languages && languages.size() > 0) {
MongoUtils.put(item, FIELD_LOCALIZATIONS, languages);
} else {
MongoUtils.remove(item, FIELD_LOCALIZATIONS);
}
}
_srvc.upsert(item);
result.add(item);
}
return result;
}
/**
* Import all translations contained in a field named "localizations".
* This method will import all translations into localized collections (ex: "mycoll_it").
* Returns a list of String containig all languages inported (i.e. "['base', 'it', 'en']")
*
* @param item Item to localize
* @param localizations List of DBObject. "[{'lang':'it', 'name':'Ciao'}, {'lang':'en', 'name':'Hello'}]"
* @return Returns a list of String containig all languages inported (i.e. "['base', 'it', 'en']")
*/
private List doImportLocalizations(final DBObject item, final List localizations) {
final BasicDBList languages = new BasicDBList();
final Object id = MongoUtils.getId(item);
if (CollectionUtils.isListOf(localizations, DBObject.class)) {
for (final Object local_item : localizations) {
if (local_item instanceof DBObject) {
final DBObject dbo = (DBObject) local_item;
final String lang = MongoUtils.getString(dbo, FIELD_LANG);
final Set<String> keys = dbo.keySet();
for (final String key : keys) {
if (!FIELD_LANG.equalsIgnoreCase(key) && dbo.containsField(key)) {
final Object value = dbo.get(key);
if (null != value) {
if (StringUtils.hasText(lang)) {
_srvc.addLocalization(id, lang, key, value);
if (!languages.contains(lang)) {
languages.add(lang);
}
} else {
// default language
item.put(key, value);
if (!languages.contains(LANG_BASE)) {
languages.add(LANG_BASE);
}
}
}
}
}
}
}
} else if (CollectionUtils.isListOf(localizations, String.class)) {
return localizations;
}
return languages;
}
// --------------------------------------------------------------------
// S T A T I C
// --------------------------------------------------------------------
private static JSONArray readJSONArray(final String resourceName) throws Exception {
final String text = ClassLoaderUtils.getResourceAsString(resourceName);
final JSONArray array = JsonWrapper.wrap(text).getJSONArray();
return array;
}
private static List<Map<String, String>> readCSV(final String resource) throws Exception {
String text = ClassLoaderUtils.getResourceAsString(resource);
final CSVReader reader = new CSVReader(new StringReader(text), ';');
return reader.readAllAsMap(true);
}
private static boolean isJSONFile(final String name) {
return PathUtils.getFilenameExtension(name, true).equalsIgnoreCase(".json");
}
private static boolean isCSVFile(final String name) {
return PathUtils.getFilenameExtension(name, true).equalsIgnoreCase(".csv");
}
// --------------------------------------------------------------------
// EMBEDDED
// --------------------------------------------------------------------
public interface ImporterIterator {
DBObject importing(DBObject item);
}
}