1756 lines
51 KiB
C++
1756 lines
51 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
----
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
Started July 2014, Fabio Vald\'{e}s
|
|
|
|
*/
|
|
#include "Tools.h"
|
|
|
|
using namespace std;
|
|
using namespace datetime;
|
|
|
|
using namespace temporalalgebra;
|
|
namespace stj {
|
|
|
|
/*
|
|
\section{Implementation of class ~Tools~}
|
|
|
|
\subsection{Function ~intersect~}
|
|
|
|
*/
|
|
void Tools::intersect(const vector<set<TupleId> >& tidsets,
|
|
set<TupleId>& result) {
|
|
result.clear();
|
|
if (tidsets.empty()) {
|
|
return;
|
|
}
|
|
vector<set<TupleId>::iterator> it;
|
|
for (unsigned int i = 0; i < tidsets.size(); i++) { // initialize iterators
|
|
// cout << "size of set " << i << " is " << tidsets[i].size() << endl;
|
|
set<TupleId>::iterator iter = tidsets[i].begin();
|
|
it.push_back(iter);
|
|
if (iter == tidsets[i].end()) { // empty set
|
|
return;
|
|
}
|
|
}
|
|
while (true) {
|
|
unsigned int min(UINT_MAX), max(0);
|
|
for (unsigned int i = 0; i < tidsets.size(); i++) {
|
|
if (*(it[i]) < min) {
|
|
min = *(it[i]);
|
|
}
|
|
if (*(it[i]) > max) {
|
|
max = *(it[i]);
|
|
}
|
|
}
|
|
if (min == max) {
|
|
result.insert(min);
|
|
for (unsigned int i = 0; i < tidsets.size(); i++) {
|
|
it[i]++;
|
|
if (it[i] == tidsets[i].end()) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else { // min < max
|
|
for (unsigned int i = 0; i < tidsets.size(); i++) {
|
|
while (*it[i] < max) {
|
|
it[i]++;
|
|
if (it[i] == tidsets[i].end()) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tools::intersectPairs(vector<set<pair<TupleId, int> > >& posVec,
|
|
set<pair<TupleId, int> >*& result) {
|
|
result->clear();
|
|
if (posVec.empty()) {
|
|
return;
|
|
}
|
|
if (posVec.size() == 1) {
|
|
result = &(posVec[0]);
|
|
return;
|
|
}
|
|
vector<set<pair<TupleId, int> >::iterator> it;
|
|
for (unsigned int i = 0; i < posVec.size(); i++) { // initialize iterators
|
|
// cout << "size of set " << i << " is " << posVec[i].size() << endl;
|
|
set<pair<TupleId, int> >::iterator iter = posVec[i].begin();
|
|
it.push_back(iter);
|
|
if (iter == posVec[i].end()) { // empty set
|
|
return;
|
|
}
|
|
}
|
|
while (true) {
|
|
pair<TupleId, int> min = make_pair(UINT_MAX, INT_MAX);
|
|
pair<TupleId, int> max = make_pair(0, INT_MIN);
|
|
for (unsigned int i = 0; i < posVec.size(); i++) {
|
|
if (*(it[i]) < min) {
|
|
min = *(it[i]);
|
|
}
|
|
if (*(it[i]) > max) {
|
|
max = *(it[i]);
|
|
}
|
|
}
|
|
if (min == max) {
|
|
result->insert(min);
|
|
for (unsigned int i = 0; i < posVec.size(); i++) {
|
|
it[i]++;
|
|
if (it[i] == posVec[i].end()) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else { // min < max
|
|
for (unsigned int i = 0; i < posVec.size(); i++) {
|
|
while (*it[i] < max) {
|
|
it[i]++;
|
|
if (it[i] == posVec[i].end()) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tools::uniteLast(unsigned int size, vector<set<TupleId> >& tidsets) {
|
|
if (tidsets.size() < size) {
|
|
return;
|
|
}
|
|
for (unsigned int i = tidsets.size() - size + 1; i < tidsets.size(); i++) {
|
|
tidsets[tidsets.size() - size].insert(tidsets[i].begin(), tidsets[i].end());
|
|
}
|
|
for (unsigned int i = 1; i < size; i++) {
|
|
tidsets.pop_back();
|
|
}
|
|
}
|
|
|
|
void Tools::uniteLastPairs(unsigned int size,
|
|
vector<set<pair<TupleId, int> > >& posVec) {
|
|
if (posVec.size() < size) {
|
|
return;
|
|
}
|
|
for (unsigned int i = posVec.size() - size + 1; i < posVec.size(); i++) {
|
|
posVec[posVec.size() - size].insert(posVec[i].begin(), posVec[i].end());
|
|
}
|
|
for (unsigned int i = 1; i < size; i++) {
|
|
posVec.pop_back();
|
|
}
|
|
}
|
|
|
|
void Tools::filterPairs(set<pair<TupleId, int> >* pairs,
|
|
const set<TupleId>& pos, set<pair<TupleId, int> >*& result) {
|
|
if (pos.empty() || pairs->empty()) {
|
|
result = pairs;
|
|
return;
|
|
}
|
|
set<pair<TupleId, int> >::iterator ip = pairs->begin();
|
|
set<TupleId>::iterator it = pos.begin();
|
|
set<pair<TupleId, int> >::iterator ir = result->begin();
|
|
while ((ip != pairs->end()) && (it != pos.end())) {
|
|
if (ip->first == *it) {
|
|
ir = result->insert(ir, *ip);
|
|
ip++;
|
|
it++;
|
|
}
|
|
else if (ip->first < *it) {
|
|
ip++;
|
|
}
|
|
else {
|
|
it++;
|
|
}
|
|
}
|
|
if (it == pos.end()) {
|
|
while (ip != pairs->end()) {
|
|
ir = result->insert(ir, *ip);
|
|
ip++;
|
|
}
|
|
}
|
|
}
|
|
|
|
string Tools::int2String(int i) {
|
|
stringstream result;
|
|
result << i;
|
|
return result.str();
|
|
}
|
|
|
|
int Tools::str2Int(string const &text) {
|
|
int result;
|
|
stringstream ss(text);
|
|
if((ss >> result).fail())
|
|
result = 0;
|
|
return result;
|
|
}
|
|
|
|
void Tools::deleteSpaces(string &text) {
|
|
size_t pos = 0;
|
|
while ((pos = text.find(' ', pos)) != string::npos)
|
|
text.erase(pos, 1);
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~convert~}
|
|
|
|
Converts a string into a char[*].
|
|
|
|
*/
|
|
char* Tools::convert(string arg) {
|
|
return strdup(arg.c_str());
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~eraseQM~}
|
|
|
|
Deletes enclosing quotation marks from a string.
|
|
|
|
*/
|
|
void Tools::eraseQM(string& arg) {
|
|
if (arg.at(0) == '"') {
|
|
arg = arg.substr(1, arg.length() - 2);
|
|
}
|
|
}
|
|
|
|
void Tools::addQM(string& arg) {
|
|
if (arg.at(0) != '"') {
|
|
arg.insert(0, "\"");
|
|
arg.append("\"");
|
|
}
|
|
}
|
|
|
|
void Tools::simplifyRegEx(string ®Ex) {
|
|
for (unsigned int i = 0; i < regEx.length(); i++) {
|
|
switch (regEx[i]) {
|
|
case '*': {
|
|
regEx[i] = '?';
|
|
break;
|
|
}
|
|
case '+': {
|
|
regEx.erase(i, 1);
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
function ~setToString~
|
|
|
|
*/
|
|
string Tools::setToString(const set<string>& input) {
|
|
set<string>::iterator i;
|
|
stringstream result;
|
|
if (input.size() == 1) {
|
|
result << *(input.begin());
|
|
}
|
|
else if (input.size() > 1) {
|
|
result << "{";
|
|
for (i = input.begin(); i != input.end(); i++) {
|
|
if (i != input.begin()) {
|
|
result << ", ";
|
|
}
|
|
result << *i;
|
|
}
|
|
result << "}";
|
|
}
|
|
return result.str();
|
|
}
|
|
|
|
/*
|
|
function ~createSetMatrix~
|
|
|
|
Creates and returns a twodimensional array that is used to store the matching
|
|
positions.
|
|
|
|
*/
|
|
|
|
set<unsigned int>** Tools::createSetMatrix(unsigned int dim1,unsigned int dim2){
|
|
set<unsigned int>** result = new set<unsigned int>*[dim1];
|
|
for (unsigned int i = 0; i < dim1; i++) {
|
|
result[i] = new set<unsigned int>[dim2];
|
|
}
|
|
return result;
|
|
};
|
|
|
|
/*
|
|
function ~deleteSetMatrix~
|
|
|
|
Deletes a twodimensional array.
|
|
|
|
*/
|
|
|
|
void Tools::deleteSetMatrix(set<unsigned int>** &victim, unsigned int dim1) {
|
|
if (victim) {
|
|
for (unsigned int i = 0; i < dim1; i++) {
|
|
if (victim[i]) {
|
|
delete[] victim[i];
|
|
}
|
|
}
|
|
delete[] victim;
|
|
victim = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
function ~prefixCount~
|
|
|
|
Returns the number of strings from which ~str~ is a prefix. This is needed in
|
|
MLabel::buildIndex.
|
|
|
|
*/
|
|
int Tools::prefixCount(string str, set<string> strings) {
|
|
set<string>::iterator it;
|
|
int result = 0;
|
|
for (it = strings.begin(); it != strings.end(); it++) {
|
|
if ((it->substr(0, str.length()) == str) && (*it != str)) {
|
|
result++;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Tools::splitPattern(string& input, vector<string>& result) {
|
|
result.clear();
|
|
if (input.empty()) {
|
|
return;
|
|
}
|
|
size_t pos = input.find('{');
|
|
if (pos == 0) { // ({2012, 2013}, ...)
|
|
result.push_back(input.substr(0, input.find('}') + 1));
|
|
if (input.find('{', 1) != string::npos) { // ({2012, 2013}, {a, b, c})
|
|
result.push_back(input.substr(input.find('{', 1)));
|
|
}
|
|
else { // ({2012, 2013} a)
|
|
result.push_back(input.substr(input.find('}') + 1));
|
|
}
|
|
}
|
|
else if (pos == string::npos) { // no curly brackets
|
|
if (input.find(' ') == string::npos) { // * or +
|
|
result.push_back(input);
|
|
}
|
|
else { // (2012 a)
|
|
result.push_back(input.substr(0, input.find(' ')));
|
|
result.push_back(input.substr(input.find(' ')));
|
|
}
|
|
}
|
|
else { // (2012 {a, b, c})
|
|
result.push_back(input.substr(0, input.find(' ')));
|
|
result.push_back(input.substr(input.find(' ')));
|
|
}
|
|
}
|
|
|
|
/*
|
|
function ~extractVar~
|
|
|
|
Takes an assignment string like ~time:=Z.time~ and returns the variable string.
|
|
|
|
*/
|
|
string Tools::extractVar(const string& input) {
|
|
int posEq = input.find('=');
|
|
int posDot = input.find('.');
|
|
return input.substr(posEq + 1, posDot - posEq - 1);
|
|
}
|
|
|
|
int Tools::getKey(const string& type, Tuple *tuple /* = 0 */,
|
|
ListExpr tupleType /* = 0 */) {
|
|
if (type.empty()) {
|
|
cout << "Error: empty string after variable" << endl;
|
|
return -1;
|
|
}
|
|
if (type == "label") return 0;
|
|
if (type == "place") return 1;
|
|
if (type == "time") return 2;
|
|
if (type == "start") return 3;
|
|
if (type == "end") return 4;
|
|
if (type == "leftclosed") return 5;
|
|
if (type == "rightclosed") return 6;
|
|
if (type == "card") return 7;
|
|
if (type == "labels") return 8;
|
|
if (type == "places") return 9;
|
|
if (tuple) {
|
|
if (tupleType == 0) {
|
|
cout << "Error: no tuple type found" << endl;
|
|
return -1;
|
|
}
|
|
if (nl->ListLength(tupleType) != 2) {
|
|
cout << "Error: list length must be 2" << endl;
|
|
return -1;
|
|
}
|
|
if (!IsTupleDescription(nl->Second(tupleType))) {
|
|
cout << "Error: list is not a tuple description" << endl;
|
|
return -1;
|
|
}
|
|
ListExpr aType;
|
|
int pos = FindAttribute(nl->Second(tupleType), type, aType);
|
|
if (pos == 0) {
|
|
cout << "Attribute " << type << " not found" << endl;
|
|
return -1;
|
|
}
|
|
return pos + 99;
|
|
}
|
|
else {
|
|
cout << "Error: type " << type << " is invalid without tuple" << endl;
|
|
}
|
|
return -1; // should not occur
|
|
}
|
|
|
|
string Tools::getDataType(const int key) {
|
|
switch (key) {
|
|
case -2: return MBool::BasicType();
|
|
case -1: return CcBool::BasicType();
|
|
case 0: return Label::BasicType();
|
|
case 1: return Place::BasicType();
|
|
case 2: return SecInterval::BasicType();
|
|
case 3:
|
|
case 4: return Instant::BasicType();
|
|
case 5:
|
|
case 6: return CcBool::BasicType();
|
|
case 7: return CcInt::BasicType();
|
|
case 8: return Labels::BasicType();
|
|
case 9: return Places::BasicType();
|
|
default: return "error";
|
|
}
|
|
}
|
|
|
|
DataType Tools::getDataType(const string& type) {
|
|
if (type == "mlabel") return MLABEL;
|
|
if (type == "mlabels") return MLABELS;
|
|
if (type == "mplace") return MPLACE;
|
|
return MPLACES;
|
|
}
|
|
|
|
DataType Tools::getDataType(TupleType *ttype, const int attrno) {
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
AttributeType attrType = ttype->GetAttributeType(attrno);
|
|
string typeName = sc->GetTypeName(attrType.algId, attrType.typeId);
|
|
return getDataType(typeName);
|
|
}
|
|
|
|
string Tools::getTypeName(TupleType *ttype, const int attrno) {
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
AttributeType attrType = ttype->GetAttributeType(attrno);
|
|
return sc->GetTypeName(attrType.algId, attrType.typeId);
|
|
}
|
|
|
|
int Tools::getNoComponents(Relation *rel, const TupleId tid, const string &type,
|
|
const int attrno) {
|
|
Tuple *tuple = rel->GetTuple(tid, true);
|
|
if (type == "mreal") {
|
|
((MReal*)tuple->GetAttribute(attrno))->GetNoComponents();
|
|
}
|
|
else if (type == "mint") {
|
|
((MInt*)tuple->GetAttribute(attrno))->GetNoComponents();
|
|
}
|
|
else if (type == "mpoint") {
|
|
((MPoint*)tuple->GetAttribute(attrno))->GetNoComponents();
|
|
}
|
|
else if (type == "mregion") {
|
|
((MRegion*)tuple->GetAttribute(attrno))->GetNoComponents();
|
|
}
|
|
else if (type == "mbool") {
|
|
((MBool*)tuple->GetAttribute(attrno))->GetNoComponents();
|
|
}
|
|
tuple->DeleteIfAllowed();
|
|
return -1;
|
|
}
|
|
|
|
bool Tools::isSymbolicType(ListExpr type) {
|
|
return ((nl->ToString(type) == "mlabel") || (nl->ToString(type) == "mlabels")
|
|
|| (nl->ToString(type) == "mplace") || (nl->ToString(type) == "mplaces"));
|
|
}
|
|
|
|
string Tools::getWeekdayStr(const int weekday) {
|
|
if (weekday < 0 || weekday > 6) {
|
|
return string();
|
|
}
|
|
std::string weekdays[7] = {"monday", "tuesday", "wednesday", "thursday",
|
|
"friday", "saturday", "sunday"};
|
|
return weekdays[weekday];
|
|
}
|
|
|
|
string Tools::getMonthStr(const int month) {
|
|
if (month < 0 || month > 11) {
|
|
return string();
|
|
}
|
|
static std::string months[12] = {"january", "february", "march", "april",
|
|
"may", "june", "july", "august", "september",
|
|
"october", "november", "december"};
|
|
return months[month];
|
|
}
|
|
|
|
string Tools::getDaytimeStr(const int daytime) {
|
|
if (daytime < 0 || daytime > 3) {
|
|
return string();
|
|
}
|
|
static std::string daytimes[4] = {"morning", "afternoon", "evening", "night"};
|
|
return daytimes[daytime];
|
|
}
|
|
|
|
/*
|
|
function ~extendDate~
|
|
|
|
Takes a datetime string and extends it to the format YYYY-MM-DD-HH:MM:SS.MMM,
|
|
the variable ~start~ decides on the values.
|
|
|
|
*/
|
|
string Tools::extendDate(string input, const bool start) {
|
|
string result, mask;
|
|
int month, daysInMonth, year;
|
|
if (start) {
|
|
mask.assign("-01-01-00:00:00");
|
|
}
|
|
else {
|
|
mask.assign("-12-31-23:59:59.999");
|
|
}
|
|
if (input[input.size() - 1] == '-') { // handle case 2011-04-02-
|
|
input.resize(input.size() - 1);
|
|
}
|
|
result.assign(input);
|
|
size_t pos = 1;
|
|
if ((pos = input.find('-', pos)) == string::npos) {
|
|
result.append(mask.substr(0));
|
|
return result;
|
|
}
|
|
pos++;
|
|
if ((pos = input.find('-', pos)) == string::npos) {
|
|
if (!start) {
|
|
stringstream yearStream(input.substr(0, input.find('-')));
|
|
stringstream monthStream(input.substr(input.find('-') + 1));
|
|
stringstream dayStream;
|
|
if ((monthStream >> month).fail()) {
|
|
cout << "month stringstream error" << endl;
|
|
return input + mask.substr(3);
|
|
}
|
|
else {
|
|
switch (month){
|
|
case 1:
|
|
case 3:
|
|
case 5:
|
|
case 7:
|
|
case 8:
|
|
case 10:
|
|
case 12:
|
|
daysInMonth = 31;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
case 9:
|
|
case 11:
|
|
daysInMonth = 30;
|
|
break;
|
|
case 2:
|
|
if ((yearStream >> year).fail()) {
|
|
cout << "year stringstream error" << endl;
|
|
return input + mask.substr(3);
|
|
}
|
|
else {
|
|
if (((year % 4 == 0) && (year % 100 != 0))
|
|
|| (year % 400 == 0)) {
|
|
daysInMonth = 29;
|
|
}
|
|
else {
|
|
daysInMonth = 28;
|
|
}
|
|
}
|
|
break;
|
|
default: // should not occur
|
|
cout << "month " << month << " does not exist" << endl;
|
|
return input + mask.substr(3);
|
|
}
|
|
}
|
|
dayStream << "-" << daysInMonth;
|
|
result.append(dayStream.str());
|
|
result.append(mask.substr(6));
|
|
return result;
|
|
}
|
|
}
|
|
pos = input.find('-') + 1;
|
|
if ((pos = input.find('-', pos)) == string::npos) {
|
|
result.append(mask.substr(3));
|
|
return result;
|
|
}
|
|
pos++;
|
|
if ((pos = input.find('-', pos)) == string::npos) {
|
|
result.append(mask.substr(6));
|
|
return result;
|
|
}
|
|
pos++;
|
|
if ((pos = input.find(':', pos)) == string::npos) {
|
|
result.append(mask.substr(9));
|
|
return result;
|
|
}
|
|
pos++;
|
|
if ((pos = input.find(':', pos)) == string::npos) {
|
|
result.append(mask.substr(12));
|
|
return result;
|
|
}
|
|
pos++;
|
|
if ((pos = input.find('.', pos)) == string::npos) {
|
|
result.append(mask.substr(15));
|
|
return result;
|
|
}
|
|
return input;
|
|
}
|
|
|
|
/*
|
|
function ~checkSemanticDate~
|
|
Checks whether ~text~ is a valid semantic date string or a valid database object
|
|
of type ~Periods~ and contains the time interval defined by ~uIv~. If the
|
|
parameter ~resultNeeded~ is ~false~, the function will only check the validity
|
|
of ~text~.
|
|
|
|
*/
|
|
bool Tools::checkSemanticDate(const string &text, const SecInterval &uIv,
|
|
const bool eval) {
|
|
Instant uStart = uIv.start;
|
|
Instant uEnd = uIv.end;
|
|
bool isSemanticDate = false;
|
|
for (int i = 0; i < 12; i++) {
|
|
if (!text.compare(getMonthStr(i))) {
|
|
isSemanticDate = true;
|
|
}
|
|
else if (i < 7) {
|
|
if (!text.compare(getWeekdayStr(i))) {
|
|
isSemanticDate = true;
|
|
}
|
|
else if (i < 4) {
|
|
if (!text.compare(getDaytimeStr(i))) {
|
|
isSemanticDate = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (isSemanticDate && !eval) {
|
|
return true;
|
|
}
|
|
else if (isSemanticDate && eval) {
|
|
if ((uStart.GetYear() == uEnd.GetYear()) // year and month of start and end
|
|
&& (uStart.GetMonth() == uEnd.GetMonth())) { //must coincode for match
|
|
for (int i = 0; i < 12; i++) { // handle months
|
|
if (!text.compare(getMonthStr(i))) {
|
|
return (i == uStart.GetMonth() - 1);
|
|
}
|
|
} // for weekdays and daytimes, start and end day have to coincide
|
|
if (uStart.GetGregDay() == uEnd.GetGregDay()) {
|
|
for (int i = 0; i < 7; i++) { // handle weekdays
|
|
if (!text.compare(getWeekdayStr(i))) {
|
|
return (i == uStart.GetWeekday());
|
|
}
|
|
}
|
|
for (int i = 0; i < 4; i++) { // handle daytimes
|
|
if (!text.compare(getDaytimeStr(i))) {
|
|
switch (i) {
|
|
case 0:
|
|
return (uStart.GetHour() >= 0) && (uEnd.GetHour() <= 11);
|
|
case 1:
|
|
return (uStart.GetHour() >= 12) && (uEnd.GetHour() <= 16);
|
|
case 2:
|
|
return (uStart.GetHour() >= 17) && (uEnd.GetHour() <= 20);
|
|
case 3:
|
|
return (uStart.GetHour() >= 21) && (uEnd.GetHour() <= 23);
|
|
default: // cannot occur
|
|
cout << "daytime error" << endl;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // different months => match impossible
|
|
}
|
|
else {
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
const int errPos = 0;
|
|
ListExpr errInfo;
|
|
bool ok;
|
|
if (Periods::checkType(sc->GetObjectTypeExpr(text)) ||
|
|
SecInterval::checkType(sc->GetObjectTypeExpr(text))) {
|
|
Word pWord = sc->InObject(sc->GetObjectTypeExpr(text),
|
|
sc->GetObjectValue(text), errPos, errInfo, ok);
|
|
if (!ok) {
|
|
cout << "Error: InObject failed." << endl;
|
|
return false;
|
|
}
|
|
else {
|
|
if (Periods::checkType(sc->GetObjectTypeExpr(text))) {
|
|
Periods* period = static_cast<Periods*>(pWord.addr);
|
|
return (eval ? period->Contains(uIv) : true);
|
|
}
|
|
else {
|
|
SecInterval* interval = static_cast<SecInterval*>(pWord.addr);
|
|
return (eval ? interval->Contains(uIv) : true);
|
|
}
|
|
}
|
|
}
|
|
cout << text << " is not a periods / interval object." << endl;
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
function ~checkDaytime~
|
|
|
|
Checks whether the daytime interval resulting from text (e.g., 0:00[~]8:00)
|
|
contains the one from the unit label.
|
|
|
|
*/
|
|
bool Tools::checkDaytime(const string& text, const SecInterval& uIv) {
|
|
if ((uIv.start.GetYear() == uIv.end.GetYear())
|
|
&& (uIv.start.GetMonth() == uIv.end.GetMonth())
|
|
&& (uIv.start.GetGregDay() == uIv.end.GetGregDay())) {
|
|
string startString, endString;
|
|
stringstream startStream;
|
|
startStream << uIv.start.GetYear() << "-" << uIv.start.GetMonth() << "-"
|
|
<< uIv.start.GetGregDay() << "-";
|
|
startString.assign(startStream.str());
|
|
endString.assign(startString);
|
|
startString.append(text.substr(0, text.find('~')));
|
|
endString.append(text.substr(text.find('~') + 1));
|
|
Instant pStart(instanttype);
|
|
Instant pEnd(instanttype);
|
|
if (!pStart.ReadFrom(extendDate(startString, true))) {
|
|
cout << "error: ReadFrom " << extendDate(startString, true) << endl;
|
|
return false;
|
|
}
|
|
if (!pEnd.ReadFrom(extendDate(endString, false))) {
|
|
cout << "error: ReadFrom " << extendDate(endString, false) << endl;
|
|
return false;
|
|
}
|
|
SecInterval pInterval(pStart, pEnd, true, true);
|
|
return pInterval.Contains(uIv);
|
|
} // no match possible in case of different days
|
|
return false;
|
|
}
|
|
|
|
int Tools::getDaytime(const int hour) {
|
|
if (hour < 0 || hour > 23) {
|
|
return INT_MIN;
|
|
}
|
|
if (hour <= 11) {
|
|
return 0;
|
|
}
|
|
if (hour <= 16) {
|
|
return 1;
|
|
}
|
|
if (hour <= 20) {
|
|
return 2;
|
|
}
|
|
return 3;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~isInterval~}
|
|
|
|
*/
|
|
bool Tools::isInterval(const string& str) {
|
|
if (str.empty()) {
|
|
return false;
|
|
}
|
|
if ((str[0] > 96) && (str[0] < 123)) { // 1st case: semantic date/time
|
|
return false;
|
|
}
|
|
if (isDaytime(str)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~isDaytime~}
|
|
|
|
*/
|
|
bool Tools::isDaytime(const string& str) {
|
|
if ((str.find('-') == string::npos) // 2nd case: 19:09~22:00
|
|
&& ((str.find(':') < str.find('~')) // on each side of [~],
|
|
|| (str[0] == '~')) // there has to be either xx:yy or nothing
|
|
&& ((str.find(':', str.find('~')) != string::npos)
|
|
|| str[str.size() - 1] == '~' || str.find('~') == string::npos)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~semanticToTimePer~}
|
|
|
|
*/
|
|
void Tools::semanticToTimePer(const string& spec,
|
|
const NewPair<int64_t, int64_t> limits, Periods& result) {
|
|
Periods tempResult(true);
|
|
Instant leftLimit(limits.first), rightLimit(limits.second);
|
|
Instant startTemp(instanttype), endTemp(instanttype);
|
|
Interval<Instant> limitsIv(leftLimit, rightLimit, true, true);
|
|
// cout << "limits from multi-index are " << leftLimit << ", " << rightLimit
|
|
// << endl;
|
|
bool found = false;
|
|
for (int i = 0; i < 7 && !found; i++) {
|
|
if (spec == getWeekdayStr(i)) {
|
|
found = true;
|
|
int firstDay;
|
|
if (i >= leftLimit.GetWeekday()) {
|
|
firstDay = leftLimit.GetDay() + i - leftLimit.GetWeekday();
|
|
}
|
|
else {
|
|
firstDay = leftLimit.GetDay() + 7 - (leftLimit.GetWeekday() - i);
|
|
}
|
|
for (int d = firstDay; d <= rightLimit.GetDay(); d = d + 7) {
|
|
Instant startTmp(d, 0, instanttype), endTmp(d, 86399999, instanttype);
|
|
Interval<Instant> ivTemp(startTmp, endTmp, true, true);
|
|
tempResult.MergeAdd(ivTemp);
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < 12 && !found; i++) {
|
|
if (spec == getMonthStr(i)) {
|
|
found = true;
|
|
for (int y = leftLimit.GetYear(); y <= rightLimit.GetYear(); y++) {
|
|
startTemp.Set(y, i + 1, 1, 0, 0, 0, 0);
|
|
endTemp.Set(y, i + 1, 31, 23, 59, 59, 999);
|
|
if (endTemp.GetGregDay() < 31) {
|
|
endTemp.Set(y, i + 1, 31 - endTemp.GetGregDay(), 23, 59, 59, 999);
|
|
}
|
|
Interval<Instant> ivTemp(startTemp, endTemp, true, true);
|
|
tempResult.MergeAdd(ivTemp);
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < 4 && !found; i++) {
|
|
if (spec == getDaytimeStr(i)) {
|
|
int startHours[5] = {0, 12, 17, 20, 24};
|
|
found = true;
|
|
for (int d = leftLimit.GetDay(); d <= rightLimit.GetDay(); d++) {
|
|
Instant startTmp(d, 0, instanttype), endTmp(d, 0, instanttype);
|
|
startTmp.Set(startTmp.GetYear(), startTmp.GetMonth(),
|
|
startTmp.GetGregDay(), startHours[i], 0, 0, 0);
|
|
endTmp.Set(endTmp.GetYear(), endTmp.GetMonth(), endTmp.GetGregDay(),
|
|
startHours[i + 1] - 1, 59, 59, 999);
|
|
Interval<Instant> ivTemp(startTmp, endTmp, true, true);
|
|
tempResult.MergeAdd(ivTemp);
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
result.SetDefined(false);
|
|
}
|
|
else {
|
|
tempResult.Intersection(limitsIv, result);
|
|
// cout << "sTTP result: " << result << endl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~specToPeriods~}
|
|
|
|
*/
|
|
void Tools::specToPeriods(const string& spec,
|
|
const NewPair<int64_t, int64_t> limits, Periods& result) {
|
|
// cout << "start sTP with |" << spec << "|" << endl;
|
|
result.Clear();
|
|
Instant first(limits.first), last(limits.second);
|
|
if (spec.empty()) {
|
|
result.SetDefined(false);
|
|
}
|
|
else if (isInterval(spec)) {
|
|
result.SetDefined(true);
|
|
SecInterval iv(first, last, true, true);
|
|
stringToInterval(spec, iv);
|
|
result.Add(iv);
|
|
}
|
|
else if (isDaytime(spec)) {
|
|
result.SetDefined(true);
|
|
stringToDaytimePer(spec, limits, result);
|
|
}
|
|
else {
|
|
semanticToTimePer(spec, limits, result);
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~stringToInterval~}
|
|
|
|
*/
|
|
void Tools::stringToInterval(const string& str, SecInterval& result) {
|
|
if (!isInterval(str)) {
|
|
result.SetDefined(false);
|
|
return;
|
|
}
|
|
Instant pStart(instanttype);
|
|
Instant pEnd(instanttype);
|
|
if (str[0] == '~') { // 3rd case: ~2012-05-12
|
|
pStart.ToMinimum();
|
|
pEnd.ReadFrom(extendDate(str.substr(1), false));
|
|
}
|
|
else if (str[str.size() - 1] == '~') { // 4th case: 2011-04-02-19:09~
|
|
pStart.ReadFrom(extendDate(str.substr(0, str.size() - 1), true));
|
|
pEnd.ToMaximum();
|
|
}
|
|
else if (str.find('~') == string::npos) { // 5th case: no [~] found
|
|
pStart.ReadFrom(extendDate(str, true));
|
|
pEnd.ReadFrom(extendDate(str, false));
|
|
}
|
|
else { // sixth case: 2012-05-12-20:00~2012-05-12-22:00
|
|
pStart.ReadFrom(extendDate(str.substr(0, str.find('~')), true));
|
|
pEnd.ReadFrom(extendDate(str.substr(str.find('~') + 1), false));
|
|
}
|
|
result.Set(pStart, pEnd, true, true);
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~setDaytime~}
|
|
|
|
*/
|
|
void Tools::setDaytime(const string& str, const bool isStart, Instant& result) {
|
|
// cout << "setDaytime(" << str << ", " << isStart << ")" << endl;
|
|
string src(str);
|
|
size_t pos = 0;
|
|
int hour(-1), minute(-1), second(-1), millisecond(-1);
|
|
pos = src.find(":");
|
|
if (pos != string::npos) {
|
|
istringstream istr(src.substr(0, pos));
|
|
istr >> hour;
|
|
// cout << "found hour. " << hour << endl;
|
|
src = src.substr(pos + 1);
|
|
pos = src.find(':');
|
|
if (pos != string::npos) {
|
|
istr.clear();
|
|
istringstream istr(src.substr(0, pos));
|
|
istr >> minute;
|
|
// cout << "found minute. " << minute << endl;
|
|
src = src.substr(pos + 1);
|
|
pos = src.find('.');
|
|
if (pos != string::npos) { // all values given, 19:09:09.009
|
|
istr.clear();
|
|
istringstream istr(src.substr(0, pos));
|
|
istr >> second;
|
|
// cout << "found second. " << second << endl;
|
|
istringstream iistr(src.substr(pos + 1));
|
|
iistr >> millisecond;
|
|
// cout << "found millisecond " << millisecond << endl;
|
|
}
|
|
else { // no millisecond, 19:09:09
|
|
istr.clear();
|
|
istringstream istr(src.substr(0, src.find('~')));
|
|
istr >> second;
|
|
// cout << "found second " << second << endl;
|
|
millisecond = (isStart ? 0 : 999);
|
|
}
|
|
}
|
|
else { // no second, 19:09
|
|
istringstream istr(src.substr(0, src.find('~')));
|
|
istr >> minute;
|
|
// cout << "found minute " << minute << endl;
|
|
second = (isStart ? 0 : 59);
|
|
millisecond = (isStart ? 0 : 999);
|
|
}
|
|
}
|
|
else {
|
|
istringstream istr(src.substr(0, src.find('~')));
|
|
istr >> hour;
|
|
// cout << "found hour " << hour << endl;
|
|
minute = (isStart ? 0 : 59);
|
|
second = (isStart ? 0 : 59);
|
|
millisecond = (isStart ? 0 : 999);
|
|
}
|
|
result.Set(result.GetYear(), result.GetMonth(), result.GetGregDay(), hour,
|
|
minute, second, millisecond);
|
|
// cout << "result of setDaytime: " << result << endl;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~stringToDaytmePer~}
|
|
|
|
*/
|
|
void Tools::stringToDaytimePer(const string& str,
|
|
const NewPair<int64_t, int64_t> limits, Periods& result) {
|
|
Instant leftLimit(limits.first), rightLimit(limits.second);
|
|
Interval<Instant> limitsIv(leftLimit, rightLimit, true, true);
|
|
Instant leftDummy(leftLimit), rightDummy(rightLimit);
|
|
leftDummy.Set(leftLimit.GetYear(), leftLimit.GetMonth(),
|
|
leftLimit.GetGregDay(), 0, 0, 0, 0);
|
|
rightDummy.Set(rightLimit.GetYear(), rightLimit.GetMonth(),
|
|
rightLimit.GetGregDay(), 23, 59, 59, 999);
|
|
size_t pos = str.find('~');
|
|
if (pos == 0) { // ~19:09; left limit remains unchanged
|
|
setDaytime(str.substr(1), false, rightDummy);
|
|
}
|
|
else if (pos == string::npos) { // 19:09
|
|
setDaytime(str, true, leftDummy);
|
|
setDaytime(str, false, rightDummy);
|
|
}
|
|
else if (pos == str.length() - 1) { // 19:09~ ; right limit remains unchanged
|
|
setDaytime(str.substr(0, pos), true, leftDummy);
|
|
}
|
|
else { // 19:09~20:15
|
|
setDaytime(str.substr(0, pos), true, leftDummy);
|
|
setDaytime(str.substr(pos + 1), false, rightDummy);
|
|
}
|
|
int startDay = std::floor(leftDummy.ToDouble());
|
|
int endDay = std::floor(rightDummy.ToDouble());
|
|
double startDaytime = leftDummy.ToDouble() - std::floor(leftDummy.ToDouble());
|
|
double endDaytime = rightDummy.ToDouble() - std::floor(rightDummy.ToDouble());
|
|
Periods tempResult(true);
|
|
for (int i = startDay; i <= endDay; i++) {
|
|
Instant startTemp(startDaytime + i);
|
|
Instant endTemp(endDaytime + i);
|
|
Interval<Instant> iv(startTemp, endTemp, true, true);
|
|
tempResult.MergeAdd(iv);
|
|
}
|
|
tempResult.Intersection(limitsIv, result);
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~orderCheckInsert~}
|
|
|
|
*/
|
|
bool Tools::orderCheckInsert(Range<CcReal> *range, const Interval<CcReal> &iv) {
|
|
set<Interval<CcReal>, ivCmp> ivSet;
|
|
Interval<CcReal> ivTemp;
|
|
for (int i = 0; i < range->GetNoComponents(); i++) {
|
|
range->Get(i, ivTemp);
|
|
ivSet.insert(ivTemp);
|
|
}
|
|
ivSet.insert(iv); // intervals are ordered in ivSet
|
|
range->Clear();
|
|
for (set<Interval<CcReal>, ivCmp>::iterator it = ivSet.begin();
|
|
it != ivSet.end(); it++) {
|
|
range->MergeAdd(*it);
|
|
}
|
|
return range->IsValid();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~parseInterval~}
|
|
|
|
*/
|
|
bool Tools::parseInterval(const string& input, bool &isEmpty, int &pos,
|
|
int &endpos, Word &value) {
|
|
double left(0.0), right(0.0);
|
|
bool lc(true), rc(true);
|
|
endpos = input.find(' ', pos);
|
|
stringstream leftss(input.substr(pos + 1, endpos));
|
|
leftss >> left;
|
|
if (input[pos] == '<') { // interval
|
|
pos = input.find_first_not_of(' ', endpos);
|
|
endpos = input.find(' ', pos);
|
|
stringstream rightss(input.substr(pos, endpos - 1));
|
|
rightss >> right;
|
|
if (right < left) {
|
|
cout << "invalid interval" << endl;
|
|
return false;
|
|
}
|
|
if (input.find('>', pos) > input.find(' ', pos)) { // <x y lc rc>
|
|
if (input[pos] != 't' && input[pos] != 'f') {
|
|
cout << "\"t\" or \"f\" expected for interval, instead of \""
|
|
<< input[pos] << "\"" << endl;
|
|
return false;
|
|
}
|
|
lc = (input[pos] == 't');
|
|
pos = input.find_first_not_of(' ', pos + 1);
|
|
rc = (input[pos] == 't');
|
|
pos = input.find('>', pos) + 1;
|
|
}
|
|
endpos = input.find(' ', pos);
|
|
pos = input.find_first_not_of(' ', endpos);
|
|
}
|
|
else { // single value
|
|
right = left;
|
|
pos = input.find_first_not_of(' ', endpos);
|
|
}
|
|
CcReal ccleft(left);
|
|
CcReal ccright(right);
|
|
Interval<CcReal> iv(ccleft, ccright, lc, rc);
|
|
if (isEmpty) {
|
|
value.addr = new Range<CcReal>(true);
|
|
((Range<CcReal>*)value.addr)->Add(iv);
|
|
isEmpty = false;
|
|
}
|
|
else {
|
|
if (!Tools::orderCheckInsert((Range<CcReal>*)value.addr, iv)) {
|
|
cout << "error: interval " << input << " cannot be inserted" << endl;
|
|
return false;
|
|
}
|
|
}
|
|
// cout << "interval " << (lc ? "[" : "(") << left << ", " << right
|
|
// << (rc ? "]" : ")") << " inserted" << endl;
|
|
endpos = pos - 1;
|
|
pos = input.find_first_not_of(' ', pos);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~isSetRel~}
|
|
|
|
*/
|
|
bool Tools::isSetRel(const string& input, int &pos, int &endpos,
|
|
SetRel &setrel) {
|
|
if (input.substr(pos, 8) == "disjoint") {
|
|
setrel = DISJOINT;
|
|
}
|
|
else if (input.substr(pos, 8) == "superset") {
|
|
setrel = SUPERSET;
|
|
}
|
|
else if (input.substr(pos, 5) == "equal") {
|
|
setrel = EQUAL;
|
|
}
|
|
else if (input.substr(pos, 9) == "intersect") {
|
|
setrel = INTERSECT;
|
|
}
|
|
if (setrel != STANDARD) {
|
|
pos = input.find_first_of('{', pos);
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~parseBoolorObj~}
|
|
|
|
*/
|
|
bool Tools::parseBoolorObj(const string& input, bool &isEmpty, int &pos,
|
|
int &endpos, Word &value, std::string& type) {
|
|
if (!stringutils::isLetter(input[pos])) {
|
|
return false;
|
|
}
|
|
endpos = input.find_first_of(" ,)}", pos) - 1;
|
|
if (input.substr(pos, 4) == "TRUE") {
|
|
if (isEmpty) {
|
|
value.addr = new CcBool(true, true);
|
|
}
|
|
else {
|
|
((CcBool*)value.addr)->Set(true, true);
|
|
}
|
|
type = CcBool::BasicType();
|
|
}
|
|
else if (input.substr(pos, 5) == "FALSE") {
|
|
if (isEmpty) {
|
|
value.addr = new CcBool(true, false);
|
|
} // no else required; false remains false; true remains true
|
|
type = CcBool::BasicType();
|
|
}
|
|
else {
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
string name = input.substr(pos, endpos - pos + 1);
|
|
if (!sc->IsObjectName(name)) {
|
|
cout << name << " is not an object name" << endl;
|
|
return false;
|
|
}
|
|
Word valuePart;
|
|
bool defined;
|
|
if (!sc->GetObject(name, valuePart, defined)) {
|
|
cout << "object " << name << " could not be read" << endl;
|
|
return false;
|
|
}
|
|
type = nl->ToString(sc->GetObjectTypeExpr(name));
|
|
if (type == "rect") {
|
|
type = "region";
|
|
if (isEmpty) {
|
|
value.addr = new Region(*((Rectangle<2>*)valuePart.addr));
|
|
((Rectangle<2>*)valuePart.addr)->DeleteIfAllowed();
|
|
}
|
|
else {
|
|
Region rect(*((Rectangle<2>*)valuePart.addr));
|
|
((Rectangle<2>*)valuePart.addr)->DeleteIfAllowed();
|
|
Region res(true);
|
|
((Region*)value.addr)->Union(rect, res);
|
|
((Region*)value.addr)->DeleteIfAllowed();
|
|
((Region*)value.addr)->CopyFrom(&res);
|
|
// ((Region*)value.addr)->Print(cout); cout << endl;
|
|
}
|
|
}
|
|
else if (type == "region") {
|
|
if (isEmpty) {
|
|
value.addr = valuePart.addr;
|
|
}
|
|
else {
|
|
Region res(true);
|
|
((Region*)value.addr)->Union(*((Region*)valuePart.addr), res);
|
|
((Region*)valuePart.addr)->DeleteIfAllowed();
|
|
((Region*)value.addr)->CopyFrom(&res);
|
|
}
|
|
}
|
|
else if (type == "line") {
|
|
Region res(true);
|
|
if (isEmpty) {
|
|
Region emptyReg(true);
|
|
emptyReg.Union(*((Line*)valuePart.addr), res);
|
|
((Line*)valuePart.addr)->DeleteIfAllowed();
|
|
value.addr = new Region(res);
|
|
}
|
|
else {
|
|
((Region*)value.addr)->Union(*((Line*)valuePart.addr), res);
|
|
}
|
|
}
|
|
else if (type == "label") {
|
|
if (isEmpty) {
|
|
value.addr = new Labels(true);
|
|
((Labels*)value.addr)->Append(*((Label*)valuePart.addr));
|
|
((Label*)valuePart.addr)->DeleteIfAllowed();
|
|
}
|
|
else {
|
|
((Labels*)value.addr)->Append(*((Label*)valuePart.addr));
|
|
((Label*)valuePart.addr)->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else if (type == "labels") {
|
|
if (isEmpty) {
|
|
value.addr = valuePart.addr;
|
|
}
|
|
else {
|
|
set<string> labels;
|
|
((Labels*)valuePart.addr)->GetValues(labels);
|
|
((Labels*)value.addr)->Append(labels);
|
|
}
|
|
}
|
|
else if (type == "place") {
|
|
// TODO.
|
|
}
|
|
else if (type == "places") {
|
|
// TODO.
|
|
}
|
|
else if (type == "interval") {
|
|
if (isEmpty) {
|
|
value.addr = new Range<CcReal>(true);
|
|
((Range<CcReal>*)value.addr)->Add((*(Interval<CcReal>*)valuePart.addr));
|
|
delete (Interval<CcReal>*)valuePart.addr;
|
|
}
|
|
else {
|
|
orderCheckInsert((Range<CcReal>*)value.addr,
|
|
*((Interval<CcReal>*)valuePart.addr));
|
|
delete (Interval<CcReal>*)valuePart.addr;
|
|
}
|
|
}
|
|
else if (type == "bool") {
|
|
if (isEmpty) {
|
|
value.addr = valuePart.addr;
|
|
}
|
|
else {
|
|
((CcBool*)value.addr)->Set(true, ((CcBool*)value.addr)->GetValue() ||
|
|
((CcBool*)valuePart.addr)->GetValue());
|
|
((CcBool*)valuePart.addr)->DeleteIfAllowed();
|
|
}
|
|
}
|
|
else {
|
|
cout << "type " << type << " is invalid" << endl;
|
|
return false;
|
|
}
|
|
}
|
|
pos = input.find_first_not_of(' ', endpos + 1);
|
|
isEmpty = false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~checkAttrType~}
|
|
|
|
*/
|
|
bool Tools::checkAttrType(const string& typeName, const Word &value) {
|
|
if (value.addr == 0) {
|
|
return true;
|
|
}
|
|
else {
|
|
if (typeName == "mlabel" || typeName == "mlabels") {
|
|
return ((Labels*)value.addr)->IsDefined();
|
|
}
|
|
else if (typeName == "mplace" || typeName == "mplaces") {
|
|
return ((Places*)value.addr)->IsDefined();
|
|
}
|
|
else if (typeName == "mpoint" || typeName == "mregion") {
|
|
return ((Region*)value.addr)->IsDefined();
|
|
}
|
|
else if (typeName == "mbool") {
|
|
return ((CcBool*)value.addr)->IsDefined();
|
|
}
|
|
else if (typeName == "mint" || typeName == "mreal") {
|
|
return ((Range<CcReal>*)value.addr)->IsDefined();
|
|
}
|
|
}
|
|
cout << "invalid type " << typeName << endl;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~isRelevantAttr~}
|
|
|
|
*/
|
|
bool Tools::isRelevantAttr(const string& name) {
|
|
set<string> relevantAttrTypes;
|
|
relevantAttrTypes.insert("mbool");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mint");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mlabel");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mlabels");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mplace");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mplace");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mpoint");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mreal");
|
|
relevantAttrTypes.insert(relevantAttrTypes.end(), "mregion");
|
|
return relevantAttrTypes.find(name) != relevantAttrTypes.end();
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~isMovingAttr~}
|
|
|
|
*/
|
|
bool Tools::isMovingAttr(const ListExpr ttype, const int attrno) {
|
|
if (!nl->HasLength(ttype, 2)) {
|
|
return false;
|
|
}
|
|
if (attrno < 1 || attrno > nl->ListLength(nl->Second(ttype))) {
|
|
return false;
|
|
}
|
|
if (!nl->HasLength(nl->Nth(attrno, nl->Second(ttype)), 2)) {
|
|
return false;
|
|
}
|
|
return isRelevantAttr(nl->ToString(nl->Second(nl->Nth(attrno,
|
|
nl->Second(ttype)))));
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~getRelevantAttrs~}
|
|
|
|
*/
|
|
vector<pair<int, string> > Tools::getRelevantAttrs(TupleType *ttype,
|
|
const int majorAttrNo, int& majorValueNo) {
|
|
vector<pair<int, string> > result;
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
for (int i = 0; i < ttype->GetNoAttributes(); i++) {
|
|
AttributeType attrType = ttype->GetAttributeType(i);
|
|
string typeName = sc->GetTypeName(attrType.algId, attrType.typeId);
|
|
if (i == majorAttrNo) {
|
|
majorValueNo = result.size();
|
|
}
|
|
if (isRelevantAttr(typeName)) {
|
|
result.push_back(make_pair(i, typeName));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~deleteValue~}
|
|
|
|
*/
|
|
void Tools::deleteValue(Word &value, const string &type) {
|
|
if (value.addr == 0) {
|
|
return;
|
|
}
|
|
if (type == "mlabel" || type == "mlabels") {
|
|
((Labels*)value.addr)->DeleteIfAllowed();
|
|
}
|
|
else if (type == "mplace" || type == "mplaces") {
|
|
((Places*)value.addr)->DeleteIfAllowed();
|
|
}
|
|
else if (type == "mpoint" || type == "mregion") {
|
|
((Region*)value.addr)->DeleteIfAllowed();
|
|
}
|
|
else if (type == "mbool") {
|
|
((CcBool*)value.addr)->DeleteIfAllowed();
|
|
}
|
|
else if (type == "mint" || type == "mreal") {
|
|
((Range<CcReal>*)value.addr)->DeleteIfAllowed();
|
|
}
|
|
else { // cannot occur
|
|
cout << "cannot delete invalid type " << type << endl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~timesMatch~}
|
|
|
|
Checks whether the time interval ~uIv~ is completely enclosed by each of the
|
|
intervals specified in ~ivs~. If ~ivs~ is empty, the result is ~true~.
|
|
|
|
*/
|
|
bool Tools::timesMatch(const Interval<Instant>& iv, const set<string>& ivs) {
|
|
if (ivs.empty()) {
|
|
return true;
|
|
}
|
|
bool elementOk(false);
|
|
SecInterval pIv(true);
|
|
for (set<string>::iterator j = ivs.begin(); j != ivs.end(); j++) {
|
|
if (((*j)[0] > 96) && ((*j)[0] < 123)) { // 1st case: semantic date/time
|
|
elementOk = checkSemanticDate(*j, iv, true);
|
|
}
|
|
else if (((*j).find('-') == string::npos) // 2nd case: 19:09~22:00
|
|
&& (((*j).find(':') < (*j).find('~')) // on each side of [~],
|
|
|| ((*j)[0] == '~')) // there has to be either xx:yy or nothing
|
|
&& (((*j).find(':', (*j).find('~')) != string::npos)
|
|
|| (*j)[(*j).size() - 1] == '~')) {
|
|
elementOk = checkDaytime(*j, iv);
|
|
}
|
|
else {
|
|
stringToInterval(*j, pIv);
|
|
elementOk = pIv.Contains(iv);
|
|
}
|
|
if (!elementOk) { // all intervals have to match
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~processQueryStr~}
|
|
|
|
Invoked by ~initOpTrees~ and others.
|
|
|
|
*/
|
|
pair<QueryProcessor*, OpTree> Tools::processQueryStr(string query, int type) {
|
|
pair<QueryProcessor*, OpTree> result;
|
|
result.first = 0;
|
|
result.second = 0;
|
|
SecParser parser;
|
|
string qParsed;
|
|
ListExpr qList, rType;
|
|
bool correct(false), evaluable(false), defined(false), isFunction(false);
|
|
if (parser.Text2List(query, qParsed)) {
|
|
cout << "Text2List(" << query << ") failed" << endl;
|
|
return result;
|
|
}
|
|
if (!nl->ReadFromString(qParsed, qList)) {
|
|
cout << "ReadFromString(" << qParsed << ") failed" << endl;
|
|
return result;
|
|
}
|
|
result.first = new QueryProcessor(nl, am);
|
|
try {
|
|
result.first->Construct(nl->Second(qList), correct, evaluable, defined,
|
|
isFunction, result.second, rType);
|
|
}
|
|
catch (...) {
|
|
delete result.first;
|
|
result.first = 0;
|
|
result.second = 0;
|
|
}
|
|
if (!correct || !evaluable || !defined) {
|
|
cout << "correct: " << (correct ? "TRUE" : "FALSE") << endl
|
|
<< "evaluable: " << (evaluable ? "TRUE" : "FALSE") << endl
|
|
<< "defined: " << (correct ? "TRUE" : "FALSE") << endl;
|
|
delete result.first;
|
|
result.first = 0;
|
|
result.second = 0;
|
|
return result;
|
|
}
|
|
if (nl->ToString(rType) != getDataType(type)) {
|
|
if (nl->ToString(rType) != getDataType(-2)) {
|
|
cout << "incorrect result type: " << nl->ToString(rType) << "; should be "
|
|
<< getDataType(type) << " or " << getDataType(-2) << endl;
|
|
delete result.first;
|
|
result.first = 0;
|
|
result.second = 0;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~evaluate~}
|
|
|
|
The string ~input~ is evaluated by Secondo. The result is returned as a Word.
|
|
|
|
*/
|
|
// Word evaluate(string input) {
|
|
// SecParser qParser;
|
|
// string query, queryStr;
|
|
// ListExpr queryList;
|
|
// Word queryResult;
|
|
// input.insert(0, "query ");
|
|
// if (!qParser.Text2List(input, queryStr)) {
|
|
// if (nl->ReadFromString(queryStr, queryList)) {
|
|
// if (!nl->IsEmpty(nl->Rest(queryList))) {
|
|
// query = nl->ToString(nl->First(nl->Rest(queryList)));
|
|
// if (qp->ExecuteQuery(query, queryResult)) {
|
|
// return queryResult;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// return queryResult;
|
|
// }
|
|
|
|
|
|
|
|
bool Tools::createTransitions(const bool dortmund,
|
|
map<string, set<string> >& transitions) {
|
|
if (dortmund) {
|
|
map<string, set<string> >::iterator im;
|
|
set<string>::iterator it;
|
|
transitions["Aplerbeck"].insert("Hörde");
|
|
transitions["Aplerbeck"].insert("Innenstadt-Ost");
|
|
transitions["Aplerbeck"].insert("Brackel");
|
|
transitions["Brackel"].insert("Innenstadt-Nord");
|
|
transitions["Brackel"].insert("Innenstadt-Ost");
|
|
transitions["Brackel"].insert("Scharnhorst");
|
|
transitions["Eving"].insert("Huckarde");
|
|
transitions["Eving"].insert("Innenstadt-Nord");
|
|
transitions["Eving"].insert("Mengede");
|
|
transitions["Eving"].insert("Scharnhorst");
|
|
transitions["Hörde"].insert("Hombruch");
|
|
transitions["Hörde"].insert("Innenstadt-Ost");
|
|
transitions["Hombruch"].insert("Innenstadt-Ost");
|
|
transitions["Hombruch"].insert("Innenstadt-West");
|
|
transitions["Hombruch"].insert("Lütgendortmund");
|
|
transitions["Huckarde"].insert("Innenstadt-Nord");
|
|
transitions["Huckarde"].insert("Innenstadt-West");
|
|
transitions["Huckarde"].insert("Lütgendortmund");
|
|
transitions["Huckarde"].insert("Mengede");
|
|
transitions["Innenstadt-Nord"].insert("Innenstadt-Ost");
|
|
transitions["Innenstadt-Nord"].insert("Innenstadt-West");
|
|
transitions["Innenstadt-Nord"].insert("Scharnhorst");
|
|
transitions["Innenstadt-Ost"].insert("Innenstadt-West");
|
|
transitions["Innenstadt-West"].insert("Lütgendortmund");
|
|
for (im = transitions.begin(); im != transitions.end(); im++) {
|
|
for (it = im->second.begin(); it != im->second.end(); it++) {
|
|
transitions[*it].insert(im->first); // add symmetric transitions
|
|
}
|
|
transitions[im->first].insert(im->first); // remaining in the same area
|
|
}
|
|
}
|
|
else {
|
|
Word kreis, kreisrtree;
|
|
bool defined;
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
if (!sc->GetObject("Kreis", kreis, defined)) {
|
|
cout << "Error: GetObject Kreis failed" << endl;
|
|
return false;
|
|
}
|
|
if (!defined) {
|
|
cout << "Error: object Kreis undefined" << endl;
|
|
return false;
|
|
}
|
|
if (!sc->GetObject("Kreisrtree", kreisrtree, defined)) {
|
|
cout << "Error: GetObject Kreisrtree failed" << endl;
|
|
return false;
|
|
}
|
|
if (!defined) {
|
|
cout << "Error: object Kreisrtree undefined" << endl;
|
|
return false;
|
|
}
|
|
Relation *rel = (Relation*)(kreis.addr);
|
|
R_Tree<2, TupleId> *rtree = (R_Tree<2, TupleId>*)(kreisrtree.addr);
|
|
RelationIterator *it1 = new RelationIterator(*rel);
|
|
Tuple *tuple1 = it1->GetNextTuple();
|
|
R_TreeLeafEntry<2, TupleId> leaf;
|
|
Tuple *tuple2 = 0;
|
|
while (tuple1) {
|
|
string name1 = ((CcString*)(tuple1->GetAttribute(0)))->GetValue();
|
|
Region *r1 = (Region*)(tuple1->GetAttribute(4));
|
|
Rectangle<2> bbox = r1->BoundingBox();
|
|
if (rtree->First(bbox, leaf)) {
|
|
tuple2 = rel->GetTuple(leaf.info, true);
|
|
string name2 = ((CcString*)(tuple2->GetAttribute(0)))->GetValue();
|
|
transitions[name1.substr(3)].insert(name2.substr(3));
|
|
tuple2->DeleteIfAllowed();
|
|
while (rtree->Next(leaf)) {
|
|
tuple2 = rel->GetTuple(leaf.info, true);
|
|
string name2 = ((CcString*)(tuple2->GetAttribute(0)))->GetValue();
|
|
transitions[name1.substr(3)].insert(name2.substr(3));
|
|
tuple2->DeleteIfAllowed();
|
|
}
|
|
}
|
|
tuple1->DeleteIfAllowed();
|
|
tuple1 = it1->GetNextTuple();
|
|
}
|
|
delete it1;
|
|
delete rtree;
|
|
delete rel;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
\subsection{Function ~createLabelSequence~}
|
|
|
|
Creates a vector of string containing either districts of Dortmund or German
|
|
counties in a random but sensible order.
|
|
|
|
*/
|
|
bool Tools::createLabelSequence(const int size, const int number,
|
|
const bool dortmund, map<string, set<string> >& transitions,
|
|
vector<string>& result) {
|
|
time_t t;
|
|
time(&t);
|
|
srand((unsigned int)t);
|
|
map<string, set<string> >::iterator im;
|
|
set<string>::iterator it;
|
|
for (int i = 0; i < number; i++) {
|
|
im = transitions.begin();
|
|
int choice = rand() % transitions.size();
|
|
advance(im, choice);
|
|
string name = im->first;
|
|
result.push_back(name);
|
|
for (int j = 1; j < size; j++) {
|
|
it = transitions[name].begin();
|
|
choice = rand() % transitions[name].size();
|
|
advance(it, choice);
|
|
name = *it;
|
|
result.push_back(name);
|
|
}
|
|
}
|
|
return result.size() == (unsigned int)(size * number);
|
|
}
|
|
|
|
void Tools::printNfa(vector<map<int, int> > &nfa, set<int> &finalStates) {
|
|
map<int, int>::iterator it;
|
|
for (unsigned int i = 0; i < nfa.size(); i++) {
|
|
cout << (finalStates.count(i) ? " * " : " ") << "state " << i << ": ";
|
|
for (it = nfa[i].begin(); it != nfa[i].end(); it++) {
|
|
cout << "---" << it->first << "---> " << it->second << " ";
|
|
}
|
|
cout << endl << endl;
|
|
}
|
|
}
|
|
|
|
void Tools::makeNFApersistent(vector<map<int, int> > &nfa,set<int> &finalStates,
|
|
DbArray<NFAtransition> &trans, DbArray<int> &s2p, map<int, int> &state2Pat) {
|
|
NFAtransition tr;
|
|
map<int, int>::iterator im;
|
|
for (unsigned int i = 0; i < nfa.size(); i++) {
|
|
tr.oldState = i;
|
|
for (im = nfa[i].begin(); im != nfa[i].end(); im++) {
|
|
tr.trigger = im->first;
|
|
tr.newState = im->second;
|
|
trans.Append(tr);
|
|
}
|
|
s2p.Append(state2Pat[i]);
|
|
}
|
|
}
|
|
|
|
void Tools::createNFAfromPersistent(DbArray<NFAtransition> &trans,
|
|
DbArray<int> &s2p, vector<map<int, int> > &nfa, set<int> &finalStates) {
|
|
nfa.clear();
|
|
finalStates.clear();
|
|
map<int, int> emptymap;
|
|
NFAtransition tr;
|
|
for (int i = 0; i < trans.Size(); i++) {
|
|
trans.Get(i, tr);
|
|
while (tr.oldState >= (int)nfa.size()) {
|
|
nfa.push_back(emptymap);
|
|
}
|
|
nfa[tr.oldState][tr.trigger] = tr.newState;
|
|
}
|
|
int pat = INT_MAX;
|
|
for (int i = 1; i < s2p.Size(); i++) {
|
|
s2p.Get(i, pat);
|
|
if ((pat != INT_MAX) && (pat >= 0)) {
|
|
finalStates.insert(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
DistanceFunSym Tools::getDistanceFunSym(std::string funName) {
|
|
std::transform(funName.begin(), funName.end(), funName.begin(),
|
|
(int (*)(int))::tolower);
|
|
if (funName == "equallabels") {
|
|
return EQUALLABELS;
|
|
}
|
|
else if (funName == "prefix") {
|
|
return PREFIX;
|
|
}
|
|
else if (funName == "suffix") {
|
|
return SUFFIX;
|
|
}
|
|
else if (funName == "prefixsuffix") {
|
|
return PREFIXSUFFIX;
|
|
}
|
|
else {
|
|
return ERROR;
|
|
}
|
|
}
|
|
|
|
bool Tools::getGeoFromORel(const std::string& relName, const unsigned int ref,
|
|
const bool bbox, Word& geo, std::string& type) {
|
|
if (ref == 0) {
|
|
geo.addr = new Rectangle<2>(true);
|
|
((Rectangle<2>*)(geo.addr))->SetDefined(false);
|
|
return true;
|
|
}
|
|
SecondoCatalog* sc = SecondoSystem::GetCatalog();
|
|
Word orelPtr;
|
|
bool defined;
|
|
if (!sc->GetObject(relName, orelPtr, defined)) {
|
|
cout << "Error: cannot find relation 'Places'" << endl;
|
|
return false;
|
|
}
|
|
if (!defined) {
|
|
cout << "Error: relation 'Places' is undefined" << endl;
|
|
return false;
|
|
}
|
|
OrderedRelation *orel = static_cast<OrderedRelation*>(orelPtr.addr);
|
|
vector<void*> attributes(1);
|
|
vector<SmiKey::KeyDataType> attrTypes(1);
|
|
attrTypes[0] = SmiKey::Integer;
|
|
attributes[0] = new CcInt(true, ref);
|
|
CompositeKey fromKey(attributes, attrTypes, false);
|
|
CompositeKey toKey(attributes, attrTypes, true);
|
|
OrderedRelationIterator *rit =
|
|
(OrderedRelationIterator*)orel->MakeRangeScan(fromKey, toKey);
|
|
Tuple *pt = rit->GetNextTuple();
|
|
if (bbox) {
|
|
geo.addr = pt->GetAttribute(5);
|
|
type = Rectangle<2>::BasicType();
|
|
}
|
|
else {
|
|
if (pt->GetAttribute(1)->IsDefined()) {
|
|
geo.addr = pt->GetAttribute(1)->Copy(); // point
|
|
type = Point::BasicType();
|
|
}
|
|
else if (pt->GetAttribute(2)->IsDefined()) {
|
|
geo.addr = pt->GetAttribute(2)->Copy(); // line
|
|
type = Line::BasicType();
|
|
}
|
|
else if (pt->GetAttribute(3)->IsDefined()) {
|
|
geo.addr = pt->GetAttribute(3)->Copy(); // region
|
|
type = Region::BasicType();
|
|
}
|
|
else {
|
|
geo.addr = 0;
|
|
cout << "Error: no defined geometry for reference " << ref << endl;
|
|
}
|
|
}
|
|
((CcInt*)attributes[0])->DeleteIfAllowed();
|
|
// pt->DeleteIfAllowed();
|
|
return (geo.addr != 0);
|
|
}
|
|
|
|
bool Tools::getRectFromOrel(const std::string& relName, const unsigned int ref,
|
|
Rectangle<2>& box) {
|
|
Word geo;
|
|
std::string type;
|
|
if (!getGeoFromORel(relName, ref, true, geo, type)) {
|
|
return false;
|
|
}
|
|
box.CopyFrom((Rectangle<2>*)(geo.addr));
|
|
return true;
|
|
}
|
|
|
|
}
|