/*******************************************************************************
* Copyright 2011 Alex 'Ript' Malyshev <alexript@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package net.autosauler.ballance.server.model;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.autosauler.ballance.server.mongodb.Database;
import net.autosauler.ballance.shared.CurrValue;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.allen_sauer.gwt.log.client.Log;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
/**
* The Class Currency.
*/
public class Currency {
/** The Constant CURRENCYTABLE. */
final private static String CURRENCYTABLE = "currency";
/** The Constant CBRDATEFORMAT. */
final private static String CBRDATEFORMAT = "dd/MM/yyyy";
/** The cbr date formatter. */
private static SimpleDateFormat formatter = null;
/** The defaultcurrency. */
private static String defaultcurrency = "RUR";
static {
GlobalSettings settings = Database.getSettings();
if (settings != null) {
defaultcurrency = settings.get("currency.default", defaultcurrency);
settings.save();
}
}
public static Double convert(Double summ, String fromcurr, String tocurr,
Date valuedate) {
Double result = summ;
if (!fromcurr.equals(tocurr)) {
Double from = summ;
if (!fromcurr.equals(defaultcurrency)) {
from = Currency.get(fromcurr, valuedate);
}
if (tocurr.equals(defaultcurrency)) {
result = summ * from;
} else {
Double to = Currency.get(tocurr, valuedate);
result = (summ * from) / to;
}
}
return result;
}
/**
* Creates the default records.
*
* @param db
* the db
*/
public static void createDefaultRecords(DB db) {
if (db != null) {
DBCollection coll = db.getCollection(CURRENCYTABLE);
if (coll.getCount() < 1) {
if (formatter == null) {
formatter = new SimpleDateFormat(CBRDATEFORMAT);
}
String day = formatter.format(new Date());
receiveCBR(day, db);
BasicDBObject i = new BasicDBObject();
i.put("date", 1);
i.put("mnemo", 1);
coll.createIndex(i);
i = new BasicDBObject();
i.put("timestamp", 1);
i.put("mnemo", 1);
coll.createIndex(i);
}
}
}
/**
* Find database record for currency for date.
*
* @param mnemo
* the mnemo
* @param day
* the day
* @return the dB object
*/
private static DBObject find(String mnemo, String day) {
DBObject myDoc = null;
DB db = Database.get(null);
if (db != null) {
DBCollection coll = db.getCollection(CURRENCYTABLE);
BasicDBObject query = new BasicDBObject();
query.put("date", day);
query.put("mnemo", mnemo);
myDoc = coll.findOne(query);
}
return myDoc;
}
/**
* Find preivous currency value.
*
* @param mnemo
* the mnemo
* @param day
* the day
* @return the dB object
*/
private static DBObject findPreivous(String mnemo, Date day) {
Long toplimit = day.getTime();
DBObject myDoc = null;
DB db = Database.get(null);
if (db != null) {
DBCollection coll = db.getCollection(CURRENCYTABLE);
BasicDBObject query = new BasicDBObject();
query.put("timestamp", new BasicDBObject("$lt", toplimit));
query.put("mnemo", mnemo);
myDoc = coll.findOne(query, new BasicDBObject("$orderby",
"timestamp"));
}
return myDoc;
}
/**
* Gets the values for mnemos set.
*
* @param mnemos
* the currency mnemos
* @param date
* the date
* @return the hash map
*/
public static HashMap<String, Double> get(List<String> mnemos, Date date) {
HashMap<String, Double> values = new HashMap<String, Double>();
Iterator<String> i = mnemos.iterator();
while (i.hasNext()) {
String mnemo = i.next();
values.put(mnemo, get(mnemo, date));
}
return values;
}
/**
* Gets the currency value for today.
*
* @param mnemo
* the mnemo
* @return the double
*/
public static Double get(String mnemo) {
return get(mnemo, new Date());
}
/**
* Gets the currency value for date.
*
* @param mnemo
* the mnemo
* @param date
* the date
* @return the double
*/
public static Double get(String mnemo, Date date) {
if (formatter == null) {
formatter = new SimpleDateFormat(CBRDATEFORMAT);
}
String day = formatter.format(date);
Double val = new Double(1.0);
if (mnemo.equals(defaultcurrency)) {
return val;
}
Database.retain();
DBObject myDoc = find(mnemo, day);
if (myDoc != null) { // if value is exists in database
val = (Double) myDoc.get("val");
} else {
receiveCBR(day, null);
myDoc = find(mnemo, day);
if (myDoc != null) { // if value is downloaded
val = (Double) myDoc.get("val");
} else {
myDoc = findPreivous(mnemo, date);
if (myDoc != null) { // if old value is exists
val = (Double) myDoc.get("val");
}
}
}
Database.release();
return val;
}
/**
* Gets the.
*
* @param mnemo
* the mnemo
* @param startdate
* the startdate
* @param enddate
* the enddate
* @return the list
*/
public static List<CurrValue> get(String mnemo, Date startdate, Date enddate) {
List<CurrValue> values = new ArrayList<CurrValue>();
Date i = startdate;
while (i.before(enddate)) {
Double val = Currency.get(mnemo, i);
CurrValue cv = new CurrValue(i, val);
values.add(cv);
i = new Date(i.getTime() + (1000 * 60 * 60 * 24));
}
return values;
}
/**
* Gets the xml-node value.
*
* @param element
* the element
* @param nodename
* the nodename
* @return the node value
*/
private static String getNodeValue(Element element, String nodename) {
NodeList fstNmElmntLst = element.getElementsByTagName(nodename);
Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
NodeList fstNm = fstNmElmnt.getChildNodes();
String val = (fstNm.item(0)).getNodeValue();
// log.trace(nodename + ": " + val);
return val;
}
/**
* Receive currency values from cbr (http://www.cbr.ru).
*
* @param day
* the day
* @param database
* the database
*/
private static void receiveCBR(String day, DB database) {
String requesturi = "http://www.cbr.ru/scripts/XML_daily.asp?date_req="
+ day;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
Document doc = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
Log.error(ex.getMessage());
} finally {
try {
doc = db.parse(requesturi);
} catch (SAXException ex) {
Log.error(ex.getMessage());
} catch (IOException ex) {
Log.error(ex.getMessage());
} finally {
try {
doc.getDocumentElement().normalize();
Log.trace("Root element "
+ doc.getDocumentElement().getNodeName());
NodeList nodeLst = doc.getElementsByTagName("Valute");
Log.trace("Information of all valutes");
Database.retain();
if (database == null) {
database = Database.get(null);
}
if (database != null) {
DBCollection coll = database
.getCollection(CURRENCYTABLE);
Date now = new Date();
Long timestamp = now.getTime();
for (int s = 0; s < nodeLst.getLength(); s++) {
Node fstNode = nodeLst.item(s);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElmnt = (Element) fstNode;
// String id = fstElmnt.getAttribute("ID");
// String numcode = getNodeValue(fstElmnt,
// "NumCode");
String mnemo = getNodeValue(fstElmnt,
"CharCode");
Integer nominal = Integer
.parseInt(getNodeValue(fstElmnt,
"Nominal"));
// String name = getNodeValue(fstElmnt, "Name");
Double value = Double.parseDouble(getNodeValue(
fstElmnt, "Value").replace(',', '.'));
BasicDBObject dbdoc = new BasicDBObject();
dbdoc.put("date", day);
dbdoc.put("mnemo", mnemo);
dbdoc.put("timestamp", timestamp);
dbdoc.put("val", new Double(value / nominal));
coll.insert(dbdoc);
}
}
}
Database.release();
}
catch (Exception ex) {
Log.error(ex.getMessage());
Database.release();
}
}
}
}
}