Extract creation of intervals into IntervalFactory

This commit is contained in:
Thomas Lauf 2018-10-05 13:48:55 +02:00
parent 8008cd8312
commit 1a24c49507
9 changed files with 190 additions and 110 deletions

View file

@ -11,6 +11,7 @@ set (timew_SRCS CLI.cpp CLI.h
Exclusion.cpp Exclusion.h
Extensions.cpp Extensions.h
Interval.cpp Interval.h
IntervalFactory.cpp IntervalFactory.h
Range.cpp Range.h
Rules.cpp Rules.h
TagInfo.cpp TagInfo.h

View file

@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 - 2016, Paul Beckingham, Federico Hernandez.
// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -32,56 +32,6 @@
#include <sstream>
#include <JSON.h>
////////////////////////////////////////////////////////////////////////////////
// Syntax:
// 'inc' [ <iso> [ '-' <iso> ]] [ '#' <tag> [ <tag> ... ]]
void Interval::initialize (const std::string& line)
{
Lexer lexer (line);
std::vector <std::string> tokens;
std::string token;
Lexer::Type type;
while (lexer.token (token, type))
tokens.push_back (Lexer::dequote (token));
// Minimal requirement 'inc'.
if (!tokens.empty () &&
tokens[0] == "inc")
{
unsigned int offset = 0;
// Optional <iso>
if (tokens.size () > 1 &&
tokens[1].length () == 16)
{
start = Datetime (tokens[1]);
offset = 1;
// Optional '-' <iso>
if (tokens.size () > 3 &&
tokens[2] == "-" &&
tokens[3].length () == 16)
{
end = Datetime (tokens[3]);
offset = 3;
}
}
// Optional '#' <tag>
if (tokens.size () > 2 + offset &&
tokens[1 + offset] == "#")
{
// Optional <tag> ...
for (unsigned int i = 2 + offset; i < tokens.size (); ++i)
_tags.insert (tokens[i]);
}
return;
}
throw format ("Unrecognizable line '{1}'.", line);
}
////////////////////////////////////////////////////////////////////////////////
bool Interval::empty () const
{
@ -218,32 +168,5 @@ void Interval::setRange (const Datetime& start, const Datetime& end)
this->end = end;
}
Interval Interval::fromJson (std::string jsonString)
{
Interval interval = Interval ();
if (!jsonString.empty ())
{
auto* json = (json::object*) json::parse (jsonString);
json::array* tags = (json::array*) json->_data["tags"];
if (tags != nullptr)
{
for (auto& tag : tags->_data)
{
auto* value = (json::string*) tag;
interval.tag(value->_data);
}
}
json::string* start = (json::string*) json->_data["start"];
interval.start = Datetime(start->_data);
json::string* end = (json::string*) json->_data["end"];
interval.end = (end != nullptr) ? Datetime(end->_data) : 0;
}
return interval;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 - 2016, Paul Beckingham, Federico Hernandez.
// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -35,7 +35,6 @@ class Interval : public Range
{
public:
Interval () = default;
void initialize (const std::string&);
bool empty () const;
bool hasTag (const std::string&) const;
@ -50,8 +49,6 @@ public:
std::string json () const;
std::string dump () const;
static Interval fromJson (std::string json);
public:
int id {0};
bool synthetic {false};

116
src/IntervalFactory.cpp Normal file
View file

@ -0,0 +1,116 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// https://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <format.h>
#include <Lexer.h>
#include <IntervalFactory.h>
#include <JSON.h>
////////////////////////////////////////////////////////////////////////////////
// Syntax:
// 'inc' [ <iso> [ '-' <iso> ]] [ '#' <tag> [ <tag> ... ]]
Interval IntervalFactory::fromSerialization (const std::string &line)
{
Lexer lexer (line);
std::vector <std::string> tokens;
std::string token;
Lexer::Type type;
while (lexer.token (token, type))
{
tokens.push_back (Lexer::dequote (token));
}
// Minimal requirement 'inc'.
if (!tokens.empty () &&
tokens[0] == "inc")
{
Interval interval = Interval ();
unsigned int offset = 0;
// Optional <iso>
if (tokens.size () > 1 &&
tokens[1].length () == 16)
{
interval.start = Datetime (tokens[1]);
offset = 1;
// Optional '-' <iso>
if (tokens.size () > 3 &&
tokens[2] == "-" &&
tokens[3].length () == 16)
{
interval.end = Datetime (tokens[3]);
offset = 3;
}
}
// Optional '#' <tag>
if (tokens.size () > 2 + offset &&
tokens[1 + offset] == "#")
{
// Optional <tag> ...
for (unsigned int i = 2 + offset; i < tokens.size (); ++i)
interval.tag (tokens[i]);
}
return interval;
}
throw format ("Unrecognizable line '{1}'.", line);
}
////////////////////////////////////////////////////////////////////////////////
Interval IntervalFactory::fromJson (std::string jsonString)
{
Interval interval = Interval ();
if (!jsonString.empty ())
{
auto* json = (json::object*) json::parse (jsonString);
json::array* tags = (json::array*) json->_data["tags"];
if (tags != nullptr)
{
for (auto& tag : tags->_data)
{
auto* value = (json::string*) tag;
interval.tag(value->_data);
}
}
json::string* start = (json::string*) json->_data["start"];
interval.start = Datetime(start->_data);
json::string* end = (json::string*) json->_data["end"];
interval.end = (end != nullptr) ? Datetime(end->_data) : 0;
}
return interval;
}
////////////////////////////////////////////////////////////////////////////////

40
src/IntervalFactory.h Normal file
View file

@ -0,0 +1,40 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// https://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_INTERVALFACTORY
#define INCLUDED_INTERVALFACTORY
#include <Interval.h>
#include <string>
class IntervalFactory
{
public:
static Interval fromSerialization (const std::string &line);
static Interval fromJson (std::string jsonString);
};
#endif

View file

@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
// Copyright 2016, 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -28,11 +28,12 @@
#include <timew.h>
#include <iostream>
#include <format.h>
#include <IntervalFactory.h>
static void undoIntervalAction(UndoAction& action, Database& database)
{
Interval before = Interval::fromJson (action.getBefore ());
Interval after = Interval::fromJson (action.getAfter ());
Interval before = IntervalFactory::fromJson (action.getBefore ());
Interval after = IntervalFactory::fromJson (action.getAfter ());
database.modifyInterval (after, before, false);
}

View file

@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -32,6 +32,7 @@
#include <timew.h>
#include <algorithm>
#include <iostream>
#include "IntervalFactory.h"
////////////////////////////////////////////////////////////////////////////////
// A filter is just another interval, containing start, end and tags.
@ -316,8 +317,7 @@ std::vector <Interval> getAllInclusions (Database& database)
std::vector <Interval> all;
for (auto& line : database.allLines ())
{
Interval i;
i.initialize (line);
Interval i = IntervalFactory::fromSerialization (line);
all.push_back (i);
}
@ -675,14 +675,14 @@ Interval getLatestInterval (Database& database)
// ^ 20
if (line.find (" - ") != 20)
{
i.initialize (line);
i = IntervalFactory::fromSerialization (line);
return i;
}
}
auto lastLine = database.lastLine ();
if (! lastLine.empty ())
i.initialize (lastLine);
i = IntervalFactory::fromSerialization (lastLine);
return i;
}

View file

@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 - 2018, Paul Beckingham, Federico Hernandez.
// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -26,6 +26,7 @@
#include <timew.h>
#include <test.h>
#include <src/IntervalFactory.h>
////////////////////////////////////////////////////////////////////////////////
void test_flatten (
@ -36,7 +37,7 @@ void test_flatten (
const std::vector <std::string>& output)
{
Interval i;
i.initialize (input);
i = IntervalFactory::fromSerialization (input);
auto results = flatten (i, exclusions);
@ -44,7 +45,7 @@ void test_flatten (
for (unsigned int i = 0; i < std::min (output.size (), results.size ()); ++i)
{
Interval tmp;
tmp.initialize (output[i]);
tmp = IntervalFactory::fromSerialization (output[i]);
t.is (tmp.start.toISO (), results[i].start.toISO (), "flatten: " + label + " start matches");
t.is (tmp.end.toISO (), results[i].end.toISO (), "flatten: " + label + " end matches");

View file

@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 - 2018, Paul Beckingham, Federico Hernandez.
// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -26,6 +26,7 @@
#include <cmake.h>
#include <Interval.h>
#include <IntervalFactory.h>
#include <test.h>
////////////////////////////////////////////////////////////////////////////////
@ -82,83 +83,83 @@ int main (int, char**)
// Round-trip parsing.
Interval i4;
i4.initialize ( "inc");
i4 = IntervalFactory::fromSerialization ("inc");
t.is (i4.serialize (), "inc",
"Round-trip 'inc'");
Interval i5;
i5.initialize ( "inc # foo");
i5 = IntervalFactory::fromSerialization ("inc # foo");
t.is (i5.serialize (), "inc # foo",
"Round-trip 'inc # foo'");
Interval i6;
i6.initialize ( "inc # bar foo");
i6 = IntervalFactory::fromSerialization ("inc # bar foo");
t.is (i6.serialize (), "inc # bar foo",
"Round-trip 'inc # bar foo'");
Interval i7;
i7.initialize ( "inc 19700101T000001Z");
i7 = IntervalFactory::fromSerialization ("inc 19700101T000001Z");
t.is (i7.serialize (), "inc 19700101T000001Z",
"Round-trip 'inc 19700101T000001Z'");
Interval i8;
i8.initialize ( "inc 19700101T000001Z - 19700101T000002Z");
i8 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z");
t.is (i8.serialize (), "inc 19700101T000001Z - 19700101T000002Z",
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z'");
Interval i9;
i9.initialize ( "inc 19700101T000001Z # bar foo");
i9 = IntervalFactory::fromSerialization ("inc 19700101T000001Z # bar foo");
t.is (i9.serialize (), "inc 19700101T000001Z # bar foo",
"Round-trip 'inc 19700101T000001Z # bar foo'");
Interval i10;
i10.initialize ( "inc 19700101T000001Z - 19700101T000002Z # bar foo");
i10 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # bar foo");
t.is (i10.serialize (), "inc 19700101T000001Z - 19700101T000002Z # bar foo",
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z # bar foo'");
Interval i11;
i11.initialize ( "inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo");
i11 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo");
t.is (i11.serialize (), "inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo",
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo'");
// std::string json () const;
Interval i12;
i12.initialize ( "inc");
i12 = IntervalFactory::fromSerialization ("inc");
t.is (i12.json (), "{}",
"JSON '{}'");
Interval i13;
i13.initialize ( "inc # foo");
i13 = IntervalFactory::fromSerialization ("inc # foo");
t.is (i13.json (), "{\"tags\":[\"foo\"]}",
"JSON '{\"tags\":[\"foo\"]}'");
Interval i14;
i14.initialize ( "inc # bar foo");
i14 = IntervalFactory::fromSerialization ("inc # bar foo");
t.is (i14.json (), "{\"tags\":[\"bar\",\"foo\"]}",
"JSON '{\"tags\":[\"bar\",\"foo\"]}'");
Interval i15;
i15.initialize ( "inc 19700101T000001Z");
i15 = IntervalFactory::fromSerialization ("inc 19700101T000001Z");
t.is (i15.json (), "{\"start\":\"19700101T000001Z\"}",
"JSON '{\"start\":\"19700101T000001Z\"}'");
Interval i16;
i16.initialize ( "inc 19700101T000001Z - 19700101T000002Z");
i16 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z");
t.is (i16.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}",
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}'");
Interval i17;
i17.initialize ( "inc 19700101T000001Z # bar foo");
i17 = IntervalFactory::fromSerialization ("inc 19700101T000001Z # bar foo");
t.is (i17.json (), "{\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}",
"JSON '{\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}'");
Interval i18;
i18.initialize ( "inc 19700101T000001Z - 19700101T000002Z # bar foo");
i18 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # bar foo");
t.is (i18.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}",
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}'");
Interval i19;
i19.initialize ( "inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo");
i19 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo");
t.is (i19.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}",
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}'");