text:
/*
 * @Author: Lavender
 * @Date: 2022-02-20 21:14:26
 * @LastEditors: Lavender
 * @LastEditTime: 2022-02-28 12:21:24
 * @Description: sidecar的main函数（主要用于命令行参数配置以及启动对应类型的sidecar）
 * @FilePath: /Microservice-Workflows-Agency/main.cpp
 */

#include "cmdline.h"
#include "request.h"

#include <boost/asio.hpp>

#include <iostream>
#include <list>
#include <stdexcept>

using boost::asio::ip::tcp;
using string = std::string;

//
// 设置命令行参数
//
void setParser(cmdline::parser& cmdParser) {
    cmdParser.add<string>("host", '\0', "host", true);
    cmdParser.add<string>("port", '\0', "port", true);
    cmdParser.add<string>("target", '\0', "target", true);
    cmdParser.add<string>("method", '\0', "request method", false, "GET", cmdline::oneof<string>("GET", "POST"));
    cmdParser.add<string>("ifile", '\0', "input filename", false);
    cmdParser.add<string>("ofile", '\0', "output filename", false);
}

inline void setIfstream(std::ifstream& input_stream, std::string&& input_filename) {
    input_stream.open(input_filename, std::ios::in);
}

inline void setOfstream(std::ofstream& output_stream, std::string&& output_filename) {
    output_stream.open(output_filename, std::ios::out | std::ios::trunc);
}

inline int getFilename(cmdline::parser& cmdParser, std::string& input_filename, std::string& output_filename) {
    int state = 0;
    if (cmdParser.exist("ifile")) input_filename = cmdParser.get<string>("ifile"), state += 1;
    if (cmdParser.exist("ofile")) output_filename = cmdParser.get<string>("ofile"), state += 1 << 1;
    return state;
}

int main(int argc, char* argv[]) {
    try {
        // 使用第三方库cmdline进行命令行参数解析
        cmdline::parser cmdParser;
        setParser(cmdParser);
        cmdParser.parse_check(argc, argv);

        std::ifstream input_stream;
        std::ofstream output_stream;
        string input_filename, output_filename;

        boost::asio::io_service io_service;
        string host = cmdParser.get<string>("host");
        string port = cmdParser.get<string>("port");
        string target = cmdParser.get<string>("target");
        string method = cmdParser.get<string>("method");
        int state = getFilename(cmdParser, input_filename, output_filename);
        setIfstream(input_stream, std::move(input_filename));
        setOfstream(output_stream, std::move(output_filename));
        std::shared_ptr<session> client;
        switch (state) {
            case 1:
                {
                    client = std::make_shared<session>(io_service, std::move(input_stream));
                    break;
                }
            case 2:
                {
                    client = std::make_shared<session>(io_service, std::move(output_stream));
                    break;
                }
            case 3:
                {
                    client = std::make_shared<session>(io_service, std::move(input_stream), std::move(output_stream));
                    break;
                }
            default:
                {
                    client = std::make_shared<session>(io_service);
                    break;
                }
        }
        client->run(host.c_str(), port.c_str(), target.c_str(), method.c_str());
        io_service.run();
    } catch (std::invalid_argument& ia) {
        // 捕捉stoi异常
        std::cerr << "stoi转换异常:" << ia.what() << std::endl;

    } catch (std::exception& e) {
        // 捕捉其他异常
        std::cerr << "Exception: " << e.what() << std::endl;
    }
}

ext: cpp


text:
#include <Eigen/Core>
#include <Eigen/Sparse>
#include <iostream>

void gradient_descent_test(const std::function<double(const double)> f, const std::function<double(const double)> gf, const double x0, double & fx, double & x, std::vector<double> & intervals, std::vector<double> & values, std::vector<double> & minima){
//    for (int i = 0; i<intervals.size(); i++) {
//        std::cout << " " << intervals[i];
//    }
    //std::cout << std::endl;
    int max_iter = 100;
    //double alpha = 0.02;
    double alpha = 0.02; // CHANGE THIS BACK
    double tau,g;
    double min = 0.0;
    double max = 1.0;
    double tol = 1e-6;
    double xmin = x0;
    double xmax = x0;
    x = x0;

    double prev_x = 10000000.0;
    int iter = 0;
    bool stop = false;
    double x_candidate,fx_candidate;
    g = 100.0;
    //std::cout << "run" << std::endl;
    int in_existing_interval = -1;
    assert(iter<max_iter && !stop && abs(x-prev_x)>tol);
    while (iter<max_iter && !stop && abs(x-prev_x)>tol) {
        xmin = std::min(xmin,x);
        xmax = std::max(xmax,x);

        for (int mm = 0; mm < (intervals.size()/2); mm++) {
            if ((x >= (intervals[2*mm]-1e-6)) && (x <= (intervals[2*mm+1]+1e-6)) ){
                fx = values[mm];
                x = minima[mm];
                in_existing_interval = mm;
                break;
             //   in_existing_interval = true;
            }
        }
        if (in_existing_interval>-1) {
            break;
        }
        if (iter==0) {
            fx = f(x);
        }
//        if (fx<-0.1) {
//            break;
//        }

        g = gf(x);
        //std::cout << g << std::endl;
        tau = alpha;
        prev_x = x;
        for (int div = 1; div<10; div++) {
            iter = iter + 1;
            assert(iter<max_iter);
            x_candidate = x - tau* ( (double) (g > 0) - (g < 0));
            x_candidate = std::max(std::min(x_candidate,1.0),0.0);
            fx_candidate = f(x_candidate);
            if ((fx_candidate-fx)<(0.5*(x_candidate - x)*g)) {
                x = x_candidate;
                fx = fx_candidate;
                //std::cout << div << std::endl;
                break;
            }
            tau = 0.5*tau;
            if (div==9) {
                //std::cout << div << std::endl;
                stop = true;
            }
        }
    }

    if (in_existing_interval==-1) {
        // we have discovered a new interval
        intervals.push_back(xmin);
        intervals.push_back(xmax);
        values.push_back(fx);
        minima.push_back(x);
    }else{
        // grow interval
        intervals[2*in_existing_interval] = std::min(intervals[2*in_existing_interval],xmin);
        intervals[2*in_existing_interval+1] = std::max(intervals[2*in_existing_interval+1],xmax);
    }

  //  std::cout << iter << std::endl;

//    for (int i = 0; i<intervals.size(); i++) {
//        std::cout << " " << intervals[i];
//    }
//    std::cout << std::endl;

}

max_stars_repo_name: sgsellan/swept-volumes

max_issues_repo_name: sgsellan/swept-volumes

max_forks_repo_name: sgsellan/swept-volumes


text:
#include "dicomsender.h"
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
#include "destinationentry.h"

// work around the fact that dcmtk doesn't work in unicode mode, so all string operation needs to be converted from/to mbcs
#ifdef _UNICODE
#undef _UNICODE
#undef UNICODE
#define _UNDEFINEDUNICODE
#endif

#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/oflog/oflog.h"
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmnet/dimse.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/scu.h"

#ifdef _UNDEFINEDUNICODE
#define _UNICODE 1
#define UNICODE 1
#endif

class DICOMSenderImpl
{

public:
    DICOMSenderImpl(PatientData &patientdata);
    ~DICOMSenderImpl(void);

    void DoSendPatientAsync(std::string PatientID, std::string PatientName, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination);
    void DoSendPatient(std::string PatientID, std::string PatientName, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay);

    void DoSendStudyAsync(std::string studyuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination);
    void DoSendStudy(std::string studyuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay);

    void DoSendSeriesAsync(std::string studyuid, std::string seriesuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination);
    void DoSendSeries(std::string studyuid, std::string seriesuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay);

    void DoQuickSendAsync(DestinationEntry destination);
    void DoQuickSend();

    static bool Echo(DestinationEntry destination);

    std::string ReadLog();
    void WriteLog(const char *msg);
    void WriteLog(std::string &msg);

    void Cancel();
    bool IsDone();
protected:
    static void DoSendPatientThread(void *obj);
    static void DoSendStudyThread(void *obj);
    static void DoSendSeriesThread(void *obj);
    static void DoQuickSendThread(void *obj);
    PatientData &patientdata;

    void DoSendStuff();
    int SendABatch();

    bool IsCanceled();
    void ClearCancel();
    void SetDone(bool state);

    // threading data
    boost::mutex mutex;
    bool cancelEvent, doneEvent;
    std::string PatientID;
    std::string PatientName;
    std::string studyuid, seriesuid;
    bool changeinfo;
    std::string NewPatientID;
    std::string NewPatientName;
    std::string NewBirthDay;
    DestinationEntry m_destination;

    typedef std::map<std::string, std::set<std::string> > mapset;
    mapset sopclassuidtransfersyntax;

    class GUILog
    {
    public:
        void Write(const char *msg);
        void Write(const OFCondition &cond);
        void Write(std::stringstream &stream);
        std::string Read();
    protected:
        std::stringstream mycout;
        boost::mutex mycoutmutex;
    };

    GUILog log;

    typedef std::map<std::string, boost::filesystem::path, doj::alphanum_less<std::string> > naturalpathmap;
    int fillstudies(Study &study);
    int fillseries(Series &series);
    int fillinstances(Instance &instance, naturalpathmap *entries);
    std::vector<std::string> studies, series;
    naturalpathmap instances;    // sopid, filename, this ensures we send out instances in sopid order
};

DICOMSenderImpl::DICOMSenderImpl(PatientData &patientdata)
    : patientdata(patientdata)
{
    cancelEvent = doneEvent = false;
}

DICOMSenderImpl::~DICOMSenderImpl()
{
}

void DICOMSenderImpl::DoSendPatientAsync(std::string PatientID, std::string PatientName, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination)
{
    SetDone(false);
    ClearCancel();

    this->PatientID = PatientID;
    this->PatientName = PatientName;
    this->changeinfo = changeinfo;
    this->NewPatientID = NewPatientID;
    this->NewPatientName = NewPatientName;
    this->NewBirthDay = NewBirthDay;
    this->m_destination = destination;

    // start the thread, let the sender manage (e.g. cancel), so we don't need to track anymore
    boost::thread t(DICOMSenderImpl::DoSendPatientThread, this);
    t.detach();
}

void DICOMSenderImpl::DoSendStudyAsync(std::string studyuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination)
{
    SetDone(false);
    ClearCancel();

    this->studyuid = studyuid;
    this->changeinfo = changeinfo;
    this->NewPatientID = NewPatientID;
    this->NewPatientName = NewPatientName;
    this->NewBirthDay = NewBirthDay;
    this->m_destination = destination;

    // start the thread, let the sender manage (e.g. cancel), so we don't need to track anymore
    boost::thread t(DICOMSenderImpl::DoSendStudyThread, this);
    t.detach();
}

void DICOMSenderImpl::DoSendSeriesAsync(std::string studyuid, std::string seriesuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination)
{
    SetDone(false);
    ClearCancel();

    this->studyuid = studyuid;
    this->seriesuid = seriesuid;
    this->changeinfo = changeinfo;
    this->NewPatientID = NewPatientID;
    this->NewPatientName = NewPatientName;
    this->NewBirthDay = NewBirthDay;
    this->m_destination = destination;

    // start the thread, let the sender manage (e.g. cancel), so we don't need to track anymore
    boost::thread t(DICOMSenderImpl::DoSendSeriesThread, this);
    t.detach();
}

void DICOMSenderImpl::DoQuickSendAsync(DestinationEntry destination)
{
    SetDone(false);
    ClearCancel();

    this->m_destination = destination;
    this->changeinfo = false;

    // start the thread, let the sender manage (e.g. cancel), so we don't need to track anymore
    boost::thread t(DICOMSenderImpl::DoQuickSendThread, this);
    t.detach();
}

class MyAppender : public dcmtk::log4cplus::Appender
{
public:
    MyAppender(DICOMSenderImpl &sender) : sender(sender) {}
    virtual void close() { closed = true; }
protected:
    virtual void append(const dcmtk::log4cplus::spi::InternalLoggingEvent& event)
    {
        sender.WriteLog(formatEvent(event).c_str());
    }

    DICOMSenderImpl &sender;
};

void DICOMSenderImpl::DoSendPatientThread(void *obj)
{
    DICOMSenderImpl *me = (DICOMSenderImpl *) obj;
    dcmtk::log4cplus::SharedAppenderPtr stringlogger(new MyAppender(*me));
    dcmtk::log4cplus::Logger rootLogger = dcmtk::log4cplus::Logger::getRoot();
    rootLogger.removeAllAppenders();
    rootLogger.addAppender(stringlogger);

    OFLog::configure(OFLogger::INFO_LOG_LEVEL);

    if (me)
    {
        me->DoSendPatient(me->PatientID, me->PatientName, me->changeinfo, me->NewPatientID, me->NewPatientName, me->NewBirthDay);
        me->SetDone(true);
    }

    rootLogger.removeAllAppenders();
    dcmtk::log4cplus::threadCleanup();
}

void DICOMSenderImpl::DoSendStudyThread(void *obj)
{
    DICOMSenderImpl *me = (DICOMSenderImpl *)obj;
    dcmtk::log4cplus::SharedAppenderPtr stringlogger(new MyAppender(*me));
    dcmtk::log4cplus::Logger rootLogger = dcmtk::log4cplus::Logger::getRoot();
    rootLogger.removeAllAppenders();
    rootLogger.addAppender(stringlogger);

    OFLog::configure(OFLogger::INFO_LOG_LEVEL);

    if (me)
    {
        me->DoSendStudy(me->studyuid, me->changeinfo, me->NewPatientID, me->NewPatientName, me->NewBirthDay);
        me->SetDone(true);
    }

    rootLogger.removeAllAppenders();
    dcmtk::log4cplus::threadCleanup();
}

void DICOMSenderImpl::DoSendSeriesThread(void *obj)
{
    DICOMSenderImpl *me = (DICOMSenderImpl *)obj;
    dcmtk::log4cplus::SharedAppenderPtr stringlogger(new MyAppender(*me));
    dcmtk::log4cplus::Logger rootLogger = dcmtk::log4cplus::Logger::getRoot();
    rootLogger.removeAllAppenders();
    rootLogger.addAppender(stringlogger);

    OFLog::configure(OFLogger::INFO_LOG_LEVEL);

    if (me)
    {
        me->DoSendSeries(me->studyuid, me->seriesuid, me->changeinfo, me->NewPatientID, me->NewPatientName, me->NewBirthDay);
        me->SetDone(true);
    }

    rootLogger.removeAllAppenders();
    dcmtk::log4cplus::threadCleanup();
}

void DICOMSenderImpl::DoQuickSendThread(void *obj)
{
    DICOMSenderImpl *me = (DICOMSenderImpl *)obj;
    dcmtk::log4cplus::SharedAppenderPtr stringlogger(new MyAppender(*me));
    dcmtk::log4cplus::Logger rootLogger = dcmtk::log4cplus::Logger::getRoot();
    rootLogger.removeAllAppenders();
    rootLogger.addAppender(stringlogger);

    OFLog::configure(OFLogger::INFO_LOG_LEVEL);

    if (me)
    {
        me->DoQuickSend();
        me->SetDone(true);
    }

    rootLogger.removeAllAppenders();
    dcmtk::log4cplus::threadCleanup();
}

std::string DICOMSenderImpl::ReadLog()
{
    return log.Read();
}

void DICOMSenderImpl::WriteLog(const char *msg)
{
    log.Write(msg);
}

void DICOMSenderImpl::WriteLog(std::string &msg)
{
    log.Write(msg.c_str());
}

void DICOMSenderImpl::GUILog::Write(const char *msg)
{
    boost::mutex::scoped_lock lk(mycoutmutex);
    mycout << msg;
}

void DICOMSenderImpl::GUILog::Write(const OFCondition &cond)
{
    OFString dumpmsg; DimseCondition::dump(dumpmsg, cond); dumpmsg.append("\n");
    Write(dumpmsg.c_str());
}

void DICOMSenderImpl::GUILog::Write(std::stringstream &stream)
{
    Write(stream.str().c_str());
    stream.str(std::string());
}

std::string DICOMSenderImpl::GUILog::Read()
{
    boost::mutex::scoped_lock lk(mycoutmutex);
    std::string str = mycout.str();
    mycout.str("");
    return str;
}

class DcmDatasetEditor
{
public:
    DcmDatasetEditor(DcmDataset* dataset) : dataset(dataset) {};
    bool updateStringAttributeValue(DcmItem* dataset, const DcmTagKey& key, std::string value);
    void replacePatientInfoInformation(std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay);
protected:
    DcmDataset* dataset;
};

void DICOMSenderImpl::DoSendPatient(std::string PatientID, std::string PatientName, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay)
{
    std::stringstream msg;
    msg << "gathering images\n";
    log.Write(msg);
    msg.str("");

    // get a list of files
    patientdata.GetStudies(PatientID, PatientName, boost::bind(&DICOMSenderImpl::fillstudies, this, _1));
    for (std::vector<std::string>::iterator it = studies.begin() ; it != studies.end(); ++it)
    {
        patientdata.GetSeries(*it, boost::bind(&DICOMSenderImpl::fillseries, this, _1));
        for (std::vector<std::string>::iterator it2 = series.begin() ; it2 != series.end(); ++it2)
        {
            patientdata.GetInstances(*it2, boost::bind(&DICOMSenderImpl::fillinstances, this, _1, &instances));
        }
    }

    DoSendStuff();
}

void DICOMSenderImpl::DoSendStudy(std::string studyuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay)
{
    std::stringstream msg;
    msg << "gathering images\n";
    log.Write(msg);
    msg.str("");

    // get a list of files
    patientdata.GetSeries(studyuid, boost::bind(&DICOMSenderImpl::fillseries, this, _1));
    for (std::vector<std::string>::iterator it2 = series.begin(); it2 != series.end(); ++it2)
    {
        patientdata.GetInstances(*it2, boost::bind(&DICOMSenderImpl::fillinstances, this, _1, &instances));
    }

    DoSendStuff();
}

void DICOMSenderImpl::DoSendSeries(std::string studyuid, std::string seriesuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay)
{
    std::stringstream msg;
    msg << "gathering images\n";
    log.Write(msg);
    msg.str("");

    // get a list of files
    patientdata.GetSeries(studyuid, boost::bind(&DICOMSenderImpl::fillseries, this, _1));
    for (std::vector<std::string>::iterator it2 = series.begin(); it2 != series.end(); ++it2)
    {
        if(*it2 == seriesuid)
            patientdata.GetInstances(*it2, boost::bind(&DICOMSenderImpl::fillinstances, this, _1, &instances));
    }

    DoSendStuff();
}

void DICOMSenderImpl::DoQuickSend()
{
    std::stringstream msg;
    msg << "gathering images\n";
    log.Write(msg);
    msg.str("");

    // get a list of files
    patientdata.GetInstances(boost::bind(&DICOMSenderImpl::fillinstances, this, _1, &instances));

    DoSendStuff();
}

void DICOMSenderImpl::DoSendStuff()
{
    std::stringstream msg;
    msg << "Sending " << instances.size() << " images\n";
    log.Write(msg);

    int retry = 0;
    int unsentcountbefore = 0;
    int unsentcountafter = 0;
    do
    {
        // get number of unsent images
        unsentcountbefore = instances.size();

        // batch send
        if (unsentcountbefore > 0)
            SendABatch();

        unsentcountafter = instances.size();

        // only do a sleep if there's more to send, we didn't send anything out, and we still want to retry
        if (unsentcountafter > 0 && unsentcountbefore == unsentcountafter && retry < 10000)
        {
            retry++;
            msg << unsentcountafter << " images left to send\n";
            log.Write(msg);
            log.Write("Waiting 1 mins before retry\n");

            // sleep loop with cancel check, 1 minutes
            int sleeploop = 5 * 60 * 1;
            while (sleeploop > 0)
            {
#ifdef _WIN32
                Sleep(200);
#else
                usleep(200 * 1000);
#endif
                sleeploop--;
                if (IsCanceled())
                    break;
            }
        }
        else        // otherwise, the next loop is not a retry
        {
            retry = 0;
        }
    } while (!IsCanceled() && unsentcountafter > 0 && retry < 10000);

    // clear
    instances.clear();
    series.clear();
    studies.clear();
    sopclassuidtransfersyntax.clear();
}

int DICOMSenderImpl::fillstudies(Study &study)
{
    studies.push_back(study.studyuid);
    return 0;
}

int DICOMSenderImpl::fillseries(Series &series)
{
    this->series.push_back(series.seriesuid);
    return 0;
}

int DICOMSenderImpl::fillinstances(Instance &instance, naturalpathmap *entries)
{
    // add file to send
    entries->insert(std::pair<std::string, boost::filesystem::path>(instance.sopuid, instance.filename));

    // remember the class and transfersyntax
    sopclassuidtransfersyntax[instance.sopclassuid].insert(instance.transfersyntax);
    return 0;
}

class MyDcmSCU: public DcmSCU
{
public:
    MyDcmSCU(DICOMSenderImpl &sender) : sender(sender) {}
    bool newtransfer;
protected:
    virtual void notifySENDProgress(const unsigned long byteCount)
    {
        /*if(newtransfer)
        {
            sender.WriteLog("|");
            newtransfer = false;
        }
        else
            sender.WriteLog(".");*/
    }

    DICOMSenderImpl &sender;
};

int DICOMSenderImpl::SendABatch()
{
    MyDcmSCU scu(*this);

    scu.setVerbosePCMode(true);
    scu.setAETitle(m_destination.ourAETitle.c_str());
    scu.setPeerHostName(m_destination.destinationHost.c_str());
    scu.setPeerPort(m_destination.destinationPort);
    scu.setPeerAETitle(m_destination.destinationAETitle.c_str());
    scu.setACSETimeout(30);
    scu.setDIMSETimeout(60);
    scu.setDatasetConversionMode(true);

    OFList<OFString> defaulttransfersyntax;
    defaulttransfersyntax.push_back(UID_LittleEndianExplicitTransferSyntax);

    // for every class..
    for(mapset::iterator it = sopclassuidtransfersyntax.begin(); it != sopclassuidtransfersyntax.end(); it++)
    {
        // make list of what's in the file, and propose it first.  default proposed as a seperate context
        OFList<OFString> transfersyntax;
        for(std::set<std::string>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++)
        {
            if(*it2 != UID_LittleEndianExplicitTransferSyntax)
                transfersyntax.push_back(it2->c_str());
        }

        if(transfersyntax.size() > 0)
            scu.addPresentationContext(it->first.c_str(), transfersyntax);

        // propose the default UID_LittleEndianExplicitTransferSyntax
        scu.addPresentationContext(it->first.c_str(), defaulttransfersyntax);
    }

    OFCondition cond;

    if(scu.initNetwork().bad())
        return 1;

    if(scu.negotiateAssociation().bad())
        return 1;

    naturalpathmap::iterator itr = instances.begin();
    while(itr != instances.end())
    {
        if(IsCanceled())
        {
            log.Write("Send canceled\n");
            break;
        }

        Uint16 status;

        std::stringstream msg;
        msg << "Sending file: " << itr->second << "\n";
        log.Write(msg);
        scu.newtransfer = true;

        // load file
        DcmFileFormat dcmff;
        dcmff.loadFile(itr->second.string().c_str());

        if(changeinfo)
        {
            dcmff.getDataset()->putAndInsertString(DCM_PatientID, NewPatientID.c_str());
            dcmff.getDataset()->putAndInsertString(DCM_PatientName, NewPatientName.c_str());
            dcmff.getDataset()->putAndInsertString(DCM_PatientBirthDate, NewBirthDay.c_str());
        }

        // do some precheck of the transfer syntax
        DcmXfer fileTransfer(dcmff.getDataset()->getOriginalXfer());
        OFString sopclassuid;
        dcmff.getDataset()->findAndGetOFString(DCM_SOPClassUID, sopclassuid);

        msg << "File encoding: " << fileTransfer.getXferName() << "\n";
        log.Write(msg);

        // out found.. change to
        T_ASC_PresentationContextID pid = scu.findAnyPresentationContextID(sopclassuid, fileTransfer.getXferID());

        cond = scu.sendSTORERequest(pid, "", dcmff.getDataset(), status);
        if (cond.good() && (status == 0 || (status & 0xf000) == 0xb000))
            instances.erase(itr++);
        else if(cond == DUL_PEERABORTEDASSOCIATION)
            return 1;
        else            // some error? keep going
        {
            itr++;
        }
        /*if(!scu.newtransfer)
            log.Write("|");*/

        log.Write("\n");
    }

    scu.releaseAssociation();
    return 0;
}

bool DICOMSenderImpl::Echo(DestinationEntry destination)
{
    DcmSCU scu;

    scu.setVerbosePCMode(true);
    scu.setAETitle(destination.ourAETitle.c_str());
    scu.setPeerHostName(destination.destinationHost.c_str());
    scu.setPeerPort(destination.destinationPort);
    scu.setPeerAETitle(destination.destinationAETitle.c_str());
    scu.setACSETimeout(30);
    scu.setDIMSETimeout(60);
    scu.setDatasetConversionMode(true);

    OFList<OFString> transfersyntax;
    transfersyntax.push_back(UID_LittleEndianExplicitTransferSyntax);
    transfersyntax.push_back(UID_LittleEndianImplicitTransferSyntax);
    scu.addPresentationContext(UID_VerificationSOPClass, transfersyntax);

    OFCondition cond;
    cond = scu.initNetwork();
    if(cond.bad())
        return false;

    cond = scu.negotiateAssociation();
    if(cond.bad())
        return false;

    cond = scu.sendECHORequest(0);

    scu.releaseAssociation();

    if(cond == EC_Normal)
    {
        return true;
    }

    return false;
}

bool DcmDatasetEditor::updateStringAttributeValue(DcmItem* dataset, const DcmTagKey& key, std::string value)
{
    DcmStack stack;
    DcmTag tag(key);

    OFCondition cond = EC_Normal;
    cond = dataset->search(key, stack, ESM_fromHere, false);
    if (cond != EC_Normal)
    {
        return false;
    }

    DcmElement* elem = (DcmElement*) stack.top();

    DcmVR vr(elem->ident());
    if (elem->getLength() > vr.getMaxValueLength())
    {
        return false;
    }

    cond = elem->putOFStringArray(value.c_str());
    if (cond != EC_Normal)
    {
        return false;
    }

    return true;
}

void DcmDatasetEditor::replacePatientInfoInformation(std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay)
{
    if (NewPatientID.length() != 0)
        updateStringAttributeValue(dataset, DCM_PatientID, NewPatientID);

    if (NewPatientName.length() != 0)
        updateStringAttributeValue(dataset, DCM_PatientName, NewPatientName);

    if (NewBirthDay.length() != 0)
        updateStringAttributeValue(dataset, DCM_PatientBirthDate, NewBirthDay);
}

void DICOMSenderImpl::Cancel()
{
    boost::mutex::scoped_lock lk(mutex);
    cancelEvent = true;
}

void DICOMSenderImpl::ClearCancel()
{
    boost::mutex::scoped_lock lk(mutex);
    cancelEvent = false;
}

bool DICOMSenderImpl::IsDone()
{
    boost::mutex::scoped_lock lk(mutex);
    return doneEvent;
}

bool DICOMSenderImpl::IsCanceled()
{
    boost::mutex::scoped_lock lk(mutex);
    return cancelEvent;
}

void DICOMSenderImpl::SetDone(bool state)
{
    boost::mutex::scoped_lock lk(mutex);
    doneEvent = state;
}

DICOMSender::DICOMSender(PatientData &patientdata)
{
    impl = new DICOMSenderImpl(patientdata);
}

DICOMSender::~DICOMSender(void)
{
    delete impl;
}

void DICOMSender::DoSendPatientAsync(std::string PatientID, std::string PatientName, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination)
{
    impl->DoSendPatientAsync(PatientID, PatientName, changeinfo, NewPatientID, NewPatientName, NewBirthDay, destination);
}

void DICOMSender::DoSendStudyAsync(std::string studyuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination)
{
    impl->DoSendStudyAsync(studyuid, changeinfo, NewPatientID, NewPatientName, NewBirthDay, destination);
}

void DICOMSender::DoSendSeriesAsync(std::string studyuid, std::string seriesuid, bool changeinfo, std::string NewPatientID, std::string NewPatientName, std::string NewBirthDay, DestinationEntry destination)
{
    impl->DoSendSeriesAsync(studyuid, seriesuid, changeinfo, NewPatientID, NewPatientName, NewBirthDay, destination);
}

void DICOMSender::DoQuickSendAsync(DestinationEntry destination)
{
    impl->DoQuickSendAsync(destination);
}

bool DICOMSender::Echo(DestinationEntry destination)
{
    return DICOMSenderImpl::Echo(destination);
}

std::string DICOMSender::ReadLog()
{
    return impl->ReadLog();
}

void DICOMSender::Cancel()
{
    impl->Cancel();
}

bool DICOMSender::IsDone()
{
    return impl->IsDone();
}


text:
// Copyright Abel Sinkovics (abel@sinkovics.hu) 2011.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <mpllibs/metamonad/monoid.hpp>
#include <mpllibs/metamonad/tmp_tag.hpp>
#include <mpllibs/metamonad/lambda.hpp>
#include <mpllibs/metamonad/name.hpp>

#include <mpllibs/metamonad/mconcat.hpp>

#include <boost/test/unit_test.hpp>

#include "common.hpp"

#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/list_c.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/times.hpp>
#include <boost/mpl/assert.hpp>

using boost::mpl::_1;
using boost::mpl::_2;
using boost::mpl::plus;
using boost::mpl::times;

using mpllibs::metamonad::tmp_tag;
using mpllibs::metamonad::lambda;

using namespace mpllibs::metamonad::name;

namespace
{
  struct plus_tag : tmp_tag<plus_tag> {};
  struct mult_tag : tmp_tag<mult_tag> {};
}

namespace mpllibs
{
  namespace metamonad
  {
    namespace v1
    {
      template <>
      struct monoid<plus_tag> : monoid_defaults<plus_tag>
      {
        typedef int0 mempty;
        typedef lambda_c<a, b, plus<a, b> >::type mappend;
      };

      template <>
      struct monoid<mult_tag> : monoid_defaults<mult_tag>
      {
        typedef int1 mempty;
        typedef lambda_c<a, b, times<a, b> >::type mappend;
      };
    }
  }
}

BOOST_AUTO_TEST_CASE(test_monoid)
{
  using mpllibs::metamonad::mconcat;

  using boost::mpl::equal_to;
  using boost::mpl::list_c;
  using boost::mpl::int_;

  // test_concat_plus
  BOOST_MPL_ASSERT((
    equal_to<int13, mconcat<plus_tag, list_c<int, 1, 2, 3, 4, 3> >::type>
  ));

  // test_concat_mult
  BOOST_MPL_ASSERT((
    equal_to<int_<72>, mconcat<mult_tag, list_c<int, 1, 2, 3, 4, 3> >::type>
  ));
}


text:
//=======================================================================
// Copyright (c) 2013 Piotr Wygocki
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
/**
 * @file knapsack_0_1.hpp
 * @brief
 * @author Piotr Wygocki
 * @version 1.0
 * @date 2013-09-30
 */
#ifndef PAAL_KNAPSACK_0_1_HPP
#define PAAL_KNAPSACK_0_1_HPP

#include "paal/utils/functors.hpp"
#include "paal/utils/knapsack_utils.hpp"
#include "paal/utils/less_pointees.hpp"
#include "paal/utils/irange.hpp"
#include "paal/dynamic/knapsack/fill_knapsack_dynamic_table.hpp"
#include "paal/dynamic/knapsack/knapsack_common.hpp"
#include "paal/greedy/knapsack_0_1_two_app.hpp"

#include <boost/range/adaptor/reversed.hpp>
#include <boost/function_output_iterator.hpp>
#include <boost/optional.hpp>

#include <vector>

namespace paal {

namespace detail {

/**
 * @brief For 0/1 knapsack dynamic algorithm for given element the table has to
 * be traversed from the highest to the lowest element
 */
struct Knapsack_0_1_get_position_range {
    template <typename T>
    auto operator()(T begin, T end)
        ->decltype(irange(begin, end) | boost::adaptors::reversed) {
        return irange(begin, end) | boost::adaptors::reversed;
    }
};

/**
 * @brief This class helps solving 0/1 knapsack problem.
 *        Function solve returns the optimal value
 *        Function Retrieve solution returns chosen elements
 *
 * @tparam Objects
 * @tparam ObjectSizeFunctor
 * @tparam ObjectValueFunctor
 */
template <typename Objects, typename ObjectSizeFunctor,
          typename ObjectValueFunctor, typename Comparator>
class Knapsack_0_1 {
    using base = knapsack_base<Objects, ObjectSizeFunctor, ObjectValueFunctor>;
    using SizeType = typename base::SizeType;
    using ValueType = typename base::ValueType;
    using ObjectType = typename base::ObjectType;
    using ObjectRef = typename base::ObjectRef;
    using ReturnType = typename base::return_type;
    using ValueOrNull = boost::optional<ValueType>;
    static_assert(std::is_integral<SizeType>::value,
                  "Size type must be integral");
    using ValueOrNullVector = std::vector<ValueOrNull>;

  public:

    Knapsack_0_1(ObjectSizeFunctor size, ObjectValueFunctor value,
                 Comparator compare = Comparator())
        : m_size(size), m_value(value), m_comparator(compare) {}

    /**
     * @brief  Function solves dynamic programming problem
     * @returns the optimal value
     */
    template <typename GetBestElement>
    ReturnType solve(Objects objects, SizeType capacity,
                     GetBestElement getBest) {
        m_object_on_size.resize(capacity + 1);
        fill_table(m_object_on_size, objects, capacity);
        auto maxValue = getBest(m_object_on_size.begin(),
                                m_object_on_size.end(), m_comparator);

        if (maxValue != m_object_on_size.end()) {
            return ReturnType(**maxValue, maxValue - m_object_on_size.begin());
        } else {
            return ReturnType(ValueType{}, SizeType{});
        }
    }

    //@brief here we find actual solution
    // that is, the chosen objects
    // this is done by simple divide and conquer strategy
    template <typename OutputIterator>
    void retrieve_solution(ValueType maxValue, SizeType size, Objects objects,
                           OutputIterator & out) const {
        m_object_on_size.resize(size + 1);
        m_object_on_size_rec.resize(size + 1);
        retrieve_solution_rec(maxValue, size, std::begin(objects),
                              std::end(objects), out);
    }

  private:
    template <typename OutputIterator, typename ObjectsIter>
    void retrieve_solution_rec(ValueType maxValue, SizeType capacity,
                               ObjectsIter oBegin, ObjectsIter oEnd,
                               OutputIterator & out) const {
        if (maxValue == ValueType()) {
            return;
        }

        auto objNr = std::distance(oBegin, oEnd);
        assert(objNr);

        // boundary case only one object left
        if (objNr == 1) {
            assert(m_value(*oBegin) == maxValue);
            *out = *oBegin;
            ++out;
            return;
        }

        // main case, at least 2 objects left
        auto midle = oBegin + objNr / 2;
        fill_table(m_object_on_size, boost::make_iterator_range(oBegin, midle),
                   capacity);
        fill_table(m_object_on_size_rec,
                   boost::make_iterator_range(midle, oEnd), capacity);

        SizeType capacityLeftPartInOptimalSolution{};
        for (auto capacityLeftPart : irange(capacity + 1)) {
            auto left = m_object_on_size[capacityLeftPart];
            auto right = m_object_on_size_rec[capacity - capacityLeftPart];
            if (left && right) {
                if (*left + *right == maxValue) {
                    capacityLeftPartInOptimalSolution = capacityLeftPart;
                    break;
                }
            }
        }
        auto left = m_object_on_size[capacityLeftPartInOptimalSolution];
        auto right =
            m_object_on_size_rec[capacity - capacityLeftPartInOptimalSolution];
        assert(left && right && *left + *right == maxValue);

        retrieve_solution_rec(*left, capacityLeftPartInOptimalSolution, oBegin,
                              midle, out);
        retrieve_solution_rec(
            *right, capacity - capacityLeftPartInOptimalSolution, midle, oEnd,
            out);
    }

    template <typename ObjectsRange>
    void fill_table(ValueOrNullVector &values, ObjectsRange &&objects,
                    SizeType capacity) const {
        fill_knapsack_dynamic_table(
            values.begin(), values.begin() + capacity + 1,
            std::forward<ObjectsRange>(objects), m_size,
            [&](ValueOrNull val,
                typename boost::range_iterator<ObjectsRange>::type obj) {
            return *val + m_value(*obj);
        },
            [&](ValueOrNull left, ValueOrNull right) {
            return m_comparator(*left, *right);
        },
            [](ValueOrNull & val) {
            val = ValueType{};
        },
            Knapsack_0_1_get_position_range{});
    }

    ObjectSizeFunctor m_size;
    ObjectValueFunctor m_value;
    Comparator m_comparator;
    mutable ValueOrNullVector m_object_on_size;
    mutable ValueOrNullVector m_object_on_size_rec;
};

template <typename Objects, typename ObjectSizeFunctor,
          typename ObjectValueFunctor, typename Comparator>
Knapsack_0_1<Objects, ObjectSizeFunctor, ObjectValueFunctor, Comparator>
make_knapsack_0_1(ObjectSizeFunctor size, ObjectValueFunctor value,
                  Comparator comp) {
    return Knapsack_0_1<Objects, ObjectSizeFunctor, ObjectValueFunctor,
                        Comparator>(size, value, comp);
}

template <typename Knapsack, typename IndexType, typename ValueType,
          typename Objects, typename OutputIterator>
void retrieve_solution(const Knapsack &knapsack, ValueType maxValue,
                       IndexType size, Objects &&objects, OutputIterator & out,
                       retrieve_solution_tag) {
    knapsack.retrieve_solution(maxValue, size, objects, out);
}

template <typename Knapsack, typename IndexType, typename ValueType,
          typename Objects, typename OutputIterator>
void retrieve_solution(const Knapsack &knapsack, ValueType maxValue,
                       IndexType size, Objects &&objects, OutputIterator & out,
                       no_retrieve_solution_tag) {}

/**
 * @brief Solution to Knapsack 0/1 problem
 *  overload for integral Size case
 */
template <typename KnapsackData, typename retrieve_solution_tag>
auto knapsack(KnapsackData knap_data, zero_one_tag, integral_size_tag,
         retrieve_solution_tag retrieve_solutionTag) {
    using Value = typename KnapsackData::value;

    auto knapsack = make_knapsack_0_1<typename KnapsackData::objects>(
        knap_data.get_size(), knap_data.get_value(), utils::less{});
    auto value_size =
        knapsack.solve(knap_data.get_objects(), knap_data.get_capacity(),
                       get_max_element_on_capacity_indexed_collection<Value>());
    retrieve_solution(knapsack, value_size.first, value_size.second,
                      knap_data.get_objects(), knap_data.get_output_iter(),
                      retrieve_solutionTag);
    return value_size;
}

/**
 * @brief Solution to Knapsack 0/1 problem
 *  overload for integral Value case
 */
template <typename KnapsackData, typename retrieve_solution_tag>
auto knapsack(KnapsackData knap_data, zero_one_tag, integral_value_tag,
         retrieve_solution_tag retrieve_solutionTag) {
    using Value = typename KnapsackData::value;
    using Size = typename KnapsackData::size;

    auto knapsack = make_knapsack_0_1<typename KnapsackData::objects>(
        knap_data.get_value(), knap_data.get_size(), utils::greater{});
    auto maxValue = get_value_bound(knap_data, zero_one_tag{}, upper_tag{});
    auto value_size = knapsack.solve(
        knap_data.get_objects(), maxValue,
        get_max_element_on_value_indexed_collection<boost::optional<Size>,
                                                    Value>(
            boost::optional<Size>(knap_data.get_capacity() + 1)));
    retrieve_solution(knapsack, value_size.first, value_size.second,
                      knap_data.get_objects(), knap_data.get_output_iter(),
                      retrieve_solutionTag);
    return std::make_pair(value_size.second, value_size.first);
}

} // detail

/**
 * @brief Solution to Knapsack 0/1 problem
 *
 * @tparam Objects
 * @tparam OutputIterator
 * @tparam ObjectSizeFunctor
 * @tparam ObjectValueFunctor
 * @param oBegin given objects
 * @param oEnd
 * @param out the result is returned using output iterator
 * @param size functor that for given object returns its size
 * @param value functor that for given object returns its value
 */
template <typename Objects, typename OutputIterator, typename ObjectSizeFunctor,
          typename ObjectValueFunctor = utils::return_one_functor>
auto knapsack_0_1(Objects &&objects,
             detail::FunctorOnRangePValue<ObjectSizeFunctor, Objects>
                 capacity, // capacity is of size type
             OutputIterator out, ObjectSizeFunctor size,
             ObjectValueFunctor value = ObjectValueFunctor{}) {

    return detail::knapsack_check_integrality(
        detail::make_knapsack_data(std::forward<Objects>(objects), capacity,
                                   size, value, out),
        detail::zero_one_tag{});
}

/**
 * @brief Solution to Knapsack 0/1 problem, without retrieving the objects in
* the solution
 *
 * @tparam Objects
 * @tparam OutputIterator
 * @tparam ObjectSizeFunctor
 * @tparam ObjectValueFunctor
 * @param oBegin given objects
 * @param oEnd
 * @param size functor that for given object returns its size
 * @param value functor that for given object returns its value
 */
template <typename Objects, typename ObjectSizeFunctor,
          typename ObjectValueFunctor = utils::return_one_functor>
auto knapsack_0_1_no_output(Objects &&objects,
                       detail::FunctorOnRangePValue<ObjectSizeFunctor, Objects>
                           capacity, // capacity is of size type
                       ObjectSizeFunctor size,
                       ObjectValueFunctor value = ObjectValueFunctor{}) {
    auto out = boost::make_function_output_iterator(utils::skip_functor{});
    return detail::knapsack_check_integrality(
        detail::make_knapsack_data(
            std::forward<Objects>(objects), capacity, size, value, out),
        detail::zero_one_tag{}, detail::no_retrieve_solution_tag{});
}

} // paal

#endif // PAAL_KNAPSACK_0_1_HPP

ext: hpp

max_stars_repo_name: Kommeren/AA

max_issues_repo_name: Kommeren/AA

max_forks_repo_name: Kommeren/AA


text:
// Copyright (c) 2015-2018 LG Electronics, Inc.
//
// 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.
//
// SPDX-License-Identifier: Apache-2.0

#include "PermissionManager.h"

#include <glib.h>
#include <luna/MojLunaMessage.h>
#include <boost/algorithm/string.hpp>

#include "activity/ActivityManager.h"
#include "service/BusConnection.h"
#include "util/Logging.h"

static const char* bus_service_name = "com.webos.service.bus";
static const char* bus_service_method = "isCallAllowed";
static const unsigned CallTimeoutSec = 5;

PermissionManager::PermissionManager()
{
    LOG_AM_TRACE("Entering function %s", __FUNCTION__);
}

PermissionManager::~PermissionManager()
{
    LOG_AM_TRACE("Entering function %s", __FUNCTION__);
}

MojErr PermissionManager::syncCheck(const std::string& requester, const std::string& url)
{
    MojRefCountedPtr<PermissionManager::SyncChecker> checker(
            new PermissionManager::SyncChecker());
    return checker->check(requester, url);
}

std::string PermissionManager::getRequester(MojRefCountedPtr<MojServiceMessage> msg)
{
    MojLunaMessage *lunaMsg = dynamic_cast<MojLunaMessage *>(msg.get());
    if (!lunaMsg) {
        throw std::runtime_error("Can't generate requester string from non-Luna message");
    }

    const char *appId = lunaMsg->appId();
    const char *serviceId = lunaMsg->senderId();
    const char *requester = appId;
    if (!requester)
        requester = serviceId;
    if (!requester)
        return lunaMsg->senderAddress();

    if (appId && serviceId && boost::algorithm::starts_with(serviceId, appId))
        requester = serviceId;

    return requester;
}

PermissionManager::SyncChecker::SyncChecker()
        : m_slot(this, &SyncChecker::receiveResponse)
        , m_received(false)
        , m_timerId(0)
{
}

PermissionManager::SyncChecker::~SyncChecker()
{
}

MojErr PermissionManager::SyncChecker::check(const std::string& requester,
                                             const std::string& url)
{
    MojErr err;
    MojObject payload;

    err = payload.putString("uri", url.c_str());
    MojErrCheck(err);
    err = payload.putString("requester", requester.c_str());
    MojErrCheck(err);

    MojRefCountedPtr<MojServiceRequest> req;
    err = BusConnection::getInstance().getService().createRequest(req);
    MojErrCheck(err);

    err = req->send(m_slot, bus_service_name, bus_service_method, payload);
    MojErrCheck(err);

    m_timerId = g_timeout_add_seconds(CallTimeoutSec, &PermissionManager::SyncChecker::timeout, this);

    while (!m_received) {
        g_main_context_iteration(g_main_context_default(), true);
    }

    bool returnValue = false;
    bool allowed = false;

    err = m_response.getRequired("returnValue", returnValue);
    MojErrCheck(err);
    err = m_response.getRequired("allowed", allowed);
    MojErrCheck(err);

    if (!returnValue) {
        return MojErrLuna;
    }
    if (!allowed) {
        return MojErrAccessDenied;
    }

    return MojErrNone;
}

MojErr PermissionManager::SyncChecker::receiveResponse(MojServiceMessage *,
                                                       MojObject& response,
                                                       MojErr err)
{
    m_response = response;
    m_received = true;
    g_source_remove(m_timerId);

    return MojErrNone;
}

int PermissionManager::SyncChecker::timeout(void* ctx)
{
    PermissionManager::SyncChecker *manager = (PermissionManager::SyncChecker *) ctx;
    manager->m_received = true;

    return G_SOURCE_REMOVE;
}

void PermissionManager::checkAccessRight(
        std::string requester, std::vector<std::string> urls, PermissionCallback callback)
{
    m_queue.push_back(std::make_tuple(requester, urls, callback));

    g_timeout_add(0, &PermissionManager::processQueue, this);
}

int PermissionManager::processQueue(void* ctx)
{
    static bool isWorking = false;

    PermissionManager* self = static_cast<PermissionManager*>(ctx);
    if (!self) {
        LOG_AM_WARNING("ACG_CHECK_ERR", 0, "PermissionManager is is null");
        return G_SOURCE_REMOVE;
    }

    if (isWorking || self->m_queue.empty()) {
        return G_SOURCE_REMOVE;
    }

    isWorking = true;
    auto& item = self->m_queue.front();

    std::string& requester = std::get<0>(item);
    std::vector<std::string>& vec = std::get<1>(item);
    PermissionCallback& callback = std::get<2>(item);
    MojErr err = MojErrNone;
    std::string errorText = "' doesn't have rights to call callback/trigger";

    for (const std::string& method : vec) {
        if ((err = self->syncCheck(requester, method)) != MojErrNone) {
            callback(err, "'" + requester + errorText);
            goto Exit;
        }
    }

    for (const std::string& method : vec) {
        if ((err = self->syncCheck(ActivityManager::kServiceName, method)) != MojErrNone) {
            callback(err, "'" + (ActivityManager::kServiceName + errorText));
            goto Exit;
        }
    }

    callback(MojErrNone, "");

Exit:
    self->m_queue.pop_front();
    isWorking = false;

    return G_SOURCE_CONTINUE;
}

max_stars_repo_name: webosose/activitymanager

max_issues_repo_name: webosose/activitymanager

max_forks_repo_name: webosose/activitymanager


text:
/*
 * Copyright 2013 Matthew Harvey
 *
 * 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.
 */

#include "amalgamated_budget.hpp"
#include "account.hpp"
#include "account_type.hpp"
#include "budget_item.hpp"
#include "budget_item_table_iterator.hpp"
#include "commodity.hpp"
#include "draft_journal.hpp"
#include "entry.hpp"
#include "frequency.hpp"
#include "interval_type.hpp"
#include "dcm_exceptions.hpp"
#include "repeater.hpp"
#include "transaction_type.hpp"
#include "visibility.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <jewel/assert.hpp>
#include <jewel/decimal.hpp>
#include <jewel/log.hpp>
#include <sqloxx/handle.hpp>
#include <sqloxx/id.hpp>
#include <sqloxx/sql_statement.hpp>
#include <algorithm>
#include <ostream>
#include <utility>
#include <vector>

using jewel::Decimal;
using sqloxx::Handle;
using sqloxx::Id;
using sqloxx::SQLStatement;
using std::ostream;
using std::pair;
using std::unique_ptr;
using std::vector;

namespace gregorian = boost::gregorian;

namespace dcm
{

namespace
{
    // Identifies which (if any) is the balancing Entry, in the instrument.
    wxString balancing_entry_comment()
    {
        return wxString("Balancing entry");
    }

}  // end anonymous namespace

void
AmalgamatedBudget::setup_tables(DcmDatabaseConnection& dbc)
{
    JEWEL_LOG_TRACE();
    dbc.execute_sql
    (   "create index budget_item_account_index on budget_items(account_id)"
    );
    // NOTE UserDraftJournalTableIterator has knowledge of this schema. Ensure
    // any changes to the schema are also reflected there, as appropriate.
    dbc.execute_sql
    (   "create table amalgamated_budget_data"
        "("
            "journal_id integer unique not null "
            "references draft_journal_detail, "
            "balancing_account_id integer unique not null "
            "references accounts"
        ")"
    );
    Handle<DraftJournal> const instrument(dbc);
    instrument->set_name("AMALGAMATED BUDGET JOURNAL");
    instrument->set_comment("");
    instrument->set_transaction_type(TransactionType::envelope);
    Handle<Repeater> const repeater(dbc);
    repeater->set_frequency(Frequency(1, IntervalType::days));
    repeater->set_next_date(gregorian::day_clock::local_day());
    instrument->push_repeater(repeater);
    instrument->save();

    Handle<Account> const balancing_account(dbc);
    balancing_account->set_account_type(AccountType::pure_envelope);
    balancing_account->set_name("Unallocated");
    balancing_account->set_description("");
    balancing_account->set_visibility(Visibility::visible);
    Handle<Commodity> const balancing_account_commodity =
        dbc.default_commodity();
    balancing_account->set_commodity(balancing_account_commodity);
    balancing_account->save();

    SQLStatement statement
    (   dbc,
        "insert into amalgamated_budget_data"
        "(journal_id, balancing_account_id) "
        "values(:journal_id, :balancing_account_id)"
    );
    statement.bind(":journal_id", instrument->id());
    statement.bind(":balancing_account_id", balancing_account->id());
    statement.step_final();

    JEWEL_LOG_TRACE();
    return;
}

AmalgamatedBudget::AmalgamatedBudget
(   DcmDatabaseConnection& p_database_connection
):
    m_is_loaded(false),
    m_database_connection(p_database_connection),
    m_frequency(1, IntervalType::days),
    m_map(new Map)
{
    JEWEL_LOG_TRACE();
    JEWEL_ASSERT (!m_instrument);
    JEWEL_ASSERT (!m_balancing_account);
    JEWEL_LOG_TRACE();
}

AmalgamatedBudget::~AmalgamatedBudget()
{
    JEWEL_LOG_TRACE();
}

void
AmalgamatedBudget::load() const
{
    if (m_is_loaded)
    {
        return;
    }
    JEWEL_ASSERT (!m_is_loaded);
    load_balancing_account();
    load_instrument();
    load_map();
    m_is_loaded = true;
    return;
}

Frequency
AmalgamatedBudget::frequency() const
{
    load();
    JEWEL_ASSERT (m_frequency.num_steps() == 1);
    return m_frequency;
}

void
AmalgamatedBudget::set_frequency(Frequency const& p_frequency)
{
    load();
    m_frequency = p_frequency;
    regenerate();
    return;
}

Decimal
AmalgamatedBudget::budget(sqloxx::Id p_account_id) const
{
    load();
    Map::const_iterator it = m_map->find(p_account_id);
    JEWEL_ASSERT (it != m_map->end());
    Decimal ret = it->second;
    if (p_account_id == balancing_account()->id())
    {
        ret += instrument_balancing_amount();
    }
    return ret;
}

void
AmalgamatedBudget::generate_supported_frequencies(vector<Frequency>& vec)
{
    // NOTE This is co-dependent with the function
    // AmalgamatedBudget::supports_frequency. If this
    // changes, that must change too.
    vec.reserve(10);
    vec.push_back(Frequency(1, IntervalType::days));
    vec.push_back(Frequency(1, IntervalType::weeks));
    vec.push_back(Frequency(2, IntervalType::weeks));
    vec.push_back(Frequency(4, IntervalType::weeks));
    vec.push_back(Frequency(1, IntervalType::months));
    vec.push_back(Frequency(2, IntervalType::months));
    vec.push_back(Frequency(3, IntervalType::months));
    vec.push_back(Frequency(4, IntervalType::months));
    vec.push_back(Frequency(6, IntervalType::months));
    vec.push_back(Frequency(12, IntervalType::months));
    return;
}

bool
AmalgamatedBudget::supports_frequency(Frequency const& p_frequency)
{
    // NOTE This is co-dependent with the function
    // AmalgamatedBudget::supported_frequencies. If this changes,
    // that must change too.
    switch (p_frequency.step_type())
    {
    case IntervalType::days:
        return p_frequency.num_steps() == 1;
    case IntervalType::weeks:
        switch (p_frequency.num_steps())
        {
        case 1: case 2:    return true;
        case 3:            return false;
        case 4:            return true;
        default:         return false;
        }
    case IntervalType::months:
        switch (p_frequency.num_steps())
        {
        case 1: case 2: case 3: case 4:                return true;
        case 5:                                        return false;
        case 6:                                        return true;
        case 7: case 8: case 9: case 10: case 11:    return false;
        case 12:                                    return true;
        default:                                    return false;
        }
    case IntervalType::month_ends:
        return false;
    default:
        JEWEL_HARD_ASSERT (false);
    }
}

Handle<Account>
AmalgamatedBudget::balancing_account() const
{
    load();
    JEWEL_ASSERT (m_balancing_account);
    return m_balancing_account;
}

Handle<DraftJournal>
AmalgamatedBudget::instrument() const
{
    load();
    return m_instrument;
}

void
AmalgamatedBudget::regenerate()
{
    JEWEL_LOG_TRACE();
    // If amalgamated_budget_data has not yet been populated, then
    // proceeding here would cause the program to crash, as
    // we wouldn't be able to load the balancing account id, etc..
    // So if amalgamated_budget_data has not been created yet,
    // we simply return. It is expected this will only happen on
    // initial setup of the database (due to calling of
    // regenerate() by hook in Account saving method, when
    // balancing account is first saved).
    SQLStatement statement
    (   m_database_connection,
        "select * from amalgamated_budget_data"
    );
    if (statement.step())
    {
        load();
        regenerate_map();
        regenerate_instrument();
        statement.step_final();
    }
    JEWEL_LOG_TRACE();
    return;
}

void
AmalgamatedBudget::load_map() const
{
    JEWEL_ASSERT (!m_is_loaded);
    JEWEL_ASSERT (m_map->empty());
    generate_map();
    return;
}

void
AmalgamatedBudget::generate_map() const
{
    unique_ptr<Map> map_elect(new Map);
    JEWEL_ASSERT (map_elect->empty());
    SQLStatement account_selector
    (   m_database_connection,
        "select account_id from accounts"
    );
    while (account_selector.step())
    {
        Id const account_id = account_selector.extract<Id>(0);
        Handle<Account> const account(m_database_connection, account_id);
        (*map_elect)[account_id] =
            Decimal(0, account->commodity()->precision());
    }
    // First we calculate budgets amalgamated on the basis of
    // the canonical frequency
    // TODO MEDIUM PRIORITY We should read the BudgetItems from a container that
    // orders them by Account. Then we could use BudgetItem::normalized_total.
    // on subsections of the container. This would decrease code duplication
    // between here and BudgetItem::normalized_total.
    BudgetItemTableIterator it(m_database_connection);
    BudgetItemTableIterator const end;
    for ( ; it != end; ++it)
    {
        Handle<BudgetItem> const& budget_item = *it;
        Frequency const raw_frequency = budget_item->frequency();
        if (!AmalgamatedBudget::supports_frequency(raw_frequency))
        {
            JEWEL_THROW
            (   InvalidFrequencyException,
                "Frequency not supported by AmalgamatedBudget."
            );
        }
        Id const account_id = budget_item->account()->id();
        jewel::Decimal const raw_amount = budget_item->amount();
        jewel::Decimal const canonical_amount = convert_to_canonical
        (   raw_frequency,
            raw_amount
        );
        Map::iterator tmit = map_elect->find(account_id);
        JEWEL_ASSERT (tmit != map_elect->end());
        tmit->second += canonical_amount;
    }
    // Now convert to desired frequency
    for (auto& slot: *map_elect)
    {
        slot.second = round
        (   convert_from_canonical(m_frequency, slot.second),
            Handle<Account>(m_database_connection, slot.first)->
                commodity()->precision()
        );
    }
    using std::swap;
    swap(m_map, map_elect);
    return;
}

void
AmalgamatedBudget::regenerate_map()
{
    JEWEL_LOG_TRACE();
    load();
    generate_map();
    JEWEL_LOG_TRACE();
    return;
}

void
AmalgamatedBudget::regenerate_instrument()
{
    JEWEL_LOG_TRACE();
    load();

    Handle<DraftJournal> const fresh_journal(m_database_connection);
    fresh_journal->mimic(*m_instrument);
    reflect_entries(fresh_journal);
    reflect_repeater(fresh_journal);

    // Deal with imbalance
    Decimal const imbalance = fresh_journal->balance();
    if (imbalance != Decimal(0, 0))
    {
        Handle<Account> const ba = balancing_account();
        Handle<Entry> const balancing_entry(m_database_connection);
        balancing_entry->set_account(ba);
        balancing_entry->set_comment(balancing_entry_comment());
        balancing_entry->set_whether_reconciled(false);
        balancing_entry->set_amount
        (   -round(imbalance, ba->commodity()->precision())
        );
        balancing_entry->set_transaction_side(TransactionSide::destination);
        fresh_journal->push_entry(balancing_entry);
        JEWEL_ASSERT (fresh_journal->is_balanced());
    }
    // WARNING LOW PRIORITY the source and destination are the opposite way
    // round to usual here. But it probably doesn't matter, as
    // the user won't be seeing this Journal anyway.
    m_instrument->mimic(*fresh_journal);
    m_instrument->save();

    JEWEL_LOG_TRACE();
    return;
}

void
AmalgamatedBudget::load_balancing_account() const
{
    SQLStatement statement
    (   m_database_connection,
        "select balancing_account_id from amalgamated_budget_data"
    );
    bool check = statement.step();
    JEWEL_ASSERT (check);
    m_balancing_account = Handle<Account>
    (   m_database_connection,
        statement.extract<Id>(0)
    );
    statement.step_final();
    return;
}

void
AmalgamatedBudget::load_instrument() const
{
    // Set the instrument (the DraftJournal that carries out
    // the AmalgamatedBudget)
    SQLStatement statement
    (   m_database_connection,
        "select journal_id from amalgamated_budget_data"
    );
    statement.step();
    m_instrument =
        Handle<DraftJournal>(m_database_connection, statement.extract<Id>(0));
    statement.step_final();
    return;
}

void
AmalgamatedBudget::reflect_entries(Handle<DraftJournal> const& p_journal)
{
    load();
    p_journal->clear_entries();
    for (auto const& elem: *m_map)
    {
        if (elem.second != Decimal(0, 0))
        {
            Handle<Entry> const entry(m_database_connection);
            entry->set_account
            (   Handle<Account>(m_database_connection, elem.first)
            );
            entry->set_comment("");
            entry->set_amount(-(elem.second));
            entry->set_whether_reconciled(false);
            entry->set_transaction_side(TransactionSide::source);
            p_journal->push_entry(entry);
        }
    }
    return;
}

void
AmalgamatedBudget::reflect_repeater(Handle<DraftJournal> const& p_journal)
{
    load();
    vector<Handle<Repeater> > const& old_repeaters = p_journal->repeaters();
    if (old_repeaters.size() == 1)
    {
        Frequency const old_frequency = old_repeaters[0]->frequency();
        if
        (   old_frequency.step_type() == m_frequency.step_type() &&
            old_frequency.num_steps() == m_frequency.num_steps()
        )
        {
            return;
        }
    }
    p_journal->clear_repeaters();
    Handle<Repeater> const new_repeater(m_database_connection);
    new_repeater->set_frequency(m_frequency);
    new_repeater->set_next_date(gregorian::day_clock::local_day());
    JEWEL_ASSERT (p_journal->repeaters().empty());
    p_journal->push_repeater(new_repeater);
    return;
}

Decimal
AmalgamatedBudget::instrument_balancing_amount() const
{
    load();
    JEWEL_ASSERT (m_instrument);
    Decimal ret(0, m_database_connection.default_commodity()->precision());
    wxString const balancing_entry_marker = balancing_entry_comment();
    auto const& entries = m_instrument->entries();
    for (auto const& entry: entries)
    {
        if (entry->comment() == balancing_entry_marker)
        {
            ret -= entry->amount();
        }
    }
#   ifndef NDEBUG
        if (!entries.empty())
        {
            JEWEL_ASSERT (m_instrument->repeaters().size() == 1);
            Handle<Repeater> const repeater = m_instrument->repeaters()[0];
            JEWEL_ASSERT (repeater->frequency() == frequency());
        }
#   endif
    return ret;
}

}  // namespace dcm

max_stars_repo_name: skybaboon/dailycashmanager

max_issues_repo_name: skybaboon/dailycashmanager

max_forks_repo_name: skybaboon/dailycashmanager