blob: ec65c5143ed9d9a98044adc33a8bef011cd68179 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 23 nov. 2011
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "SerializerFeature.h"
#include <fml/workflow/Query.h>
#include <fml/workflow/WObject.h>
#include <util/avm_vfs.h>
#include <boost/tokenizer.hpp>
namespace sep
{
/**
*******************************************************************************
prototype filter::filter_ufid as avm::core.filter.filter_type is
section PROPERTY
...
endsection PROPERTY
section REPORT
@uri = std ":" ( "cout" | "cerr" )
| avm ":" ( "log" | "trace" )
| folder ":" path
| file ":" path
| filename ":" path
| socket ":" host ":" port
;
@uri = ...;
@when = [ init ][:]
[ otf | (every | after | before) ? value#unit][:][ exit ];
endsection REPORT
endprototype
*******************************************************************************
*/
static bool scanPeriod(std::string period,
avm_delay_value_t & value, avm_unit_t & unit)
{
if( ::isdigit(period[0]) )
{
std::string::size_type pos = period.find('#');
if( pos != std::string::npos )
{
if( not sep::from_string<avm_delay_value_t>(
period.substr(0, pos), value, std::dec) )
{
return false;
}
period = period.substr(pos+1);
if( period == "ns" )
{
unit = AVM_NANO_SECOND_UNIT;
}
else if( period == "┬Ás" )
{
unit = AVM_MICRO_SECOND_UNIT;
}
else if( period == "ms" )
{
unit = AVM_MILLI_SECOND_UNIT;
}
else if( period == "s" )
{
unit = AVM_SECOND_UNIT;
}
else if( period == "min" )
{
unit = AVM_MINUTE_UNIT;
}
else if( period == "h" )
{
unit = AVM_HOUR_UNIT;
}
else if( period == "step" )
{
unit = AVM_STEP_UNIT;
}
else if( REGEX_MATCH(period , CONS_WID2("micro", "step")) )
{
unit = AVM_MICRO_STEP_UNIT;
}
else if( REGEX_MATCH(period , CONS_WID2("macro", "step")) )
{
unit = AVM_MACRO_STEP_UNIT;
}
else
{
return false;
}
return true;
}
}
return false;
}
bool SerializerFeature::configure(WObject * wfParameterObject)
{
bool isConfigOK = true;
WObject * theVFS = Query::getRegexWSequence(
wfParameterObject, OR_WID2("vfs", "VFS"));
if( theVFS == WObject::_NULL_ )
{
theVFS = Query::getRegexWSequence(
wfParameterObject, OR_WID2("report", "REPORT"));
}
if( theVFS != WObject::_NULL_ )
{
mReportDetailsFlag =
Query::getWPropertyBoolean(theVFS, "details", false);
////////////////////////////////////////////////////////////////////////
// The report mTableOfURI Attributes
////////////////////////////////////////////////////////////////////////
lastFolder.location = VFS::ProjectOutputPath;
std::string::size_type pos;
std::string scheme;
std::string attrID;
WObject::const_iterator itWfO = theVFS->owned_begin();
WObject::const_iterator endWfO = theVFS->owned_end();
for( ; itWfO != endWfO ; ++itWfO )
{
if( (*itWfO)->isWProperty() )
{
scheme = attrID = (*itWfO)->getNameID();
AvmUri & uri = appendUri( (*itWfO)->toStringValue() );
if( StringTools::startsWith(scheme, "uri") )
{
pos = uri.raw.find(':');
if( pos != std::string::npos )
{
scheme = uri.raw.substr(0, pos);
uri.location = uri.raw.substr(pos+1);
}
}
else
{
pos = scheme.find('#');
if( pos != std::string::npos )
{
scheme = scheme.substr(0, pos);
}
uri.location = uri.raw;
}
if( scheme.empty() )
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected an uri like:> "
<< "std:stream | file:path | socket:host:port !!!"
<< std::endl;
destroyLastUri();
isConfigOK = false;
continue;
}
if( StringTools::startsWith(scheme, "stream") )
{
if( configureStream(theVFS, uri) )
{
mapUri(attrID, uri);
}
else
{
destroyLastUri();
isConfigOK = false;
}
}
else if( StringTools::startsWith(scheme, "folder") )
{
if( configureFolder(theVFS, uri) )
{
mapUri(attrID, uri);
}
else
{
destroyLastUri();
isConfigOK = false;
}
}
else if( StringTools::startsWith(scheme, "file") )
{
if( configureFile(theVFS, uri) )
{
mapUri(attrID, uri);
}
else
{
destroyLastUri();
isConfigOK = false;
}
}
else if( StringTools::startsWith(scheme, "filename") )
{
if( configureFilename(theVFS, uri) )
{
mapUri(attrID, uri);
}
else
{
destroyLastUri();
isConfigOK = false;
}
}
else if( StringTools::startsWith(scheme, "socket") )
{
if( configureSocket(theVFS, uri) )
{
mapUri(attrID, uri);
}
else
{
destroyLastUri();
isConfigOK = false;
}
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected an uri like:> "
<< "std:stream | file:path | socket:host:port !!!"
<< std::endl;
destroyLastUri();
isConfigOK = false;
}
}
}
////////////////////////////////////////////////////////////////////////
// The report PERIOD Attribute
////////////////////////////////////////////////////////////////////////
std::string strPeriod = Query::getWPropertyString(theVFS, "when", "");
if( not strPeriod.empty() )
{
isConfigOK = configurePeriod(theVFS, strPeriod)
&& isConfigOK;
}
if( mReportDetailsFlag )
{
SerializerFeature::toStream(AVM_OS_COUT);
}
}
else
{
// theVFS->errorLocation(AVM_OS_WARN)
// << "Expected a REPORT section !!!" << std::endl;
}
return( true );
}
bool SerializerFeature::configureStream(WObject * theVFS, AvmUri & uri)
{
if( uri.location.find("std:") == 0 )
{
if( uri.location == "std:cout" )
{
uri.kind |= AVM_URI_STREAM_STD_COUT_KIND;
uri.outStream.OS = AVM_OS_COUT.OS;
}
else if( uri.location == "std:cerr" )
{
uri.kind |= AVM_URI_STREAM_STD_CERR_KIND;
uri.outStream.OS = AVM_OS_CERR.OS;
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected an uri like:> "
<< "std:( cout | cerr ) !!!" << std::endl;
return false;
}
}
else if( uri.location.find("avm:") == 0 )
{
if( uri.location == "avm:log" )
{
uri.kind |= AVM_URI_STREAM_AVM_LOG_KIND;
uri.outStream.OS = AVM_OS_LOG.OS;
}
else if( uri.location == "avm:trace" )
{
uri.kind |= AVM_URI_STREAM_AVM_TRACE_KIND;
uri.outStream.OS = AVM_OS_TRACE.OS;
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected an uri like:> "
<< "avm:( log | trace ) !!!" << std::endl;
return false;
}
}
return( true );
}
bool SerializerFeature::configureFolder(WObject * theVFS, AvmUri & uri)
{
uri.kind |= AVM_URI_FOLDER_KIND;
if( uri.location == "avm:project" )
{
lastFolder.location = uri.location = VFS::ProjectPath;
}
else if( uri.location == "avm:output" )
{
lastFolder.location = uri.location = VFS::ProjectOutputPath;
}
else if( uri.location == "avm:source" )
{
lastFolder.location = uri.location = VFS::ProjectSourcePath;
}
else if( uri.location == "avm:log" )
{
lastFolder.location = uri.location = VFS::ProjectLogPath;
}
else
{
lastFolder.location = uri.location =
VFS::native_path(uri.location, lastFolder.location);
if ( not VFS::checkWritingFolder(uri.location) )
{
theVFS->errorLocation(AVM_OS_WARN)
<< "The folder `" << uri.location
<< "' ---> doesn't exist or "
"is not writable !!!" << std::endl;
return( false );
}
}
return( true );
}
bool SerializerFeature::configureFile(WObject * theVFS, AvmUri & uri)
{
uri.kind |= AVM_URI_FILE_KIND;
uri.location = VFS::native_path(uri.location, lastFolder.location);
uri.outStream = new std::ofstream(uri.location.c_str(), uri.mode);
if( uri.outStream.good() )
{
uri.isAllocated = true;
lastFile.location = uri.location;
return( true );
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Failed to open < " << uri.location
<< " > file in write mode !!!" << std::endl;
return( false );
}
}
bool SerializerFeature::configureFilename(WObject * theVFS, AvmUri & uri)
{
uri.kind |= AVM_URI_FILENAME_KIND;
uri.location = VFS::native_path(uri.location, lastFolder.location);
uri.outStream = new std::ofstream(uri.location.c_str(), uri.mode);
if( uri.outStream.good() )
{
uri.isAllocated = true;
lastFilename.location = uri.location;
return( true );
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Failed to open < " << uri.location
<< " > filename in write mode !!!" << std::endl;
return( false );
}
}
bool SerializerFeature::configureSocket(WObject * theVFS, AvmUri & uri)
{
uri.kind |= AVM_URI_SOCKET_KIND;
std::string::size_type pos = uri.location.find(':');
if( pos != std::string::npos )
{
if( not sep::from_string<avm_uint64_t>(
uri.location.substr(pos+1), uri.port, std::dec) )
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected an uri<socket> with valid port number like:> "
<< "socket:host:port !!!" << std::endl;
return false;
}
uri.location = uri.location.substr(0, pos);
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected an uri like:> "
<< "socket:host:port !!!" << std::endl;
return false;
}
return( true );
}
bool SerializerFeature::configurePeriod(
WObject * theVFS, const std::string & strPeriod)
{
std::string period;
std::string::size_type pos;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(":");
tokenizer tokens(strPeriod, sep);
tokenizer::iterator endIt = tokens.end();
for( tokenizer::iterator it = tokens.begin() ; it != endIt ; ++it )
{
period = *it;
if( period == "init" )
{
mPeriodKind |= AVM_PERIOD_INIT_KIND;
}
else if( period == "exit" )
{
mPeriodKind |= AVM_PERIOD_EXIT_KIND;
}
else if( period == "preprocess" )
{
mPeriodKind |= AVM_PERIOD_PREPROCESS_KIND;
}
else if( period == "postprocess" )
{
mPeriodKind |= AVM_PERIOD_POSTPROCESS_KIND;
}
else if( period == "prefilter" )
{
mPeriodKind |= AVM_PERIOD_PREFILTER_KIND;
}
else if( period == "postfilter" )
{
mPeriodKind |= AVM_PERIOD_POSTFILTER_KIND;
}
else if( period == "otf" )
{
mPeriodKind |= AVM_PERIOD_OTF_KIND;
}
else if( period.find("every") == 0 )
{
mPeriodKind |= AVM_PERIOD_EVERY_KIND;
pos = period.find('?');
if( (pos != std::string::npos) &&
(not scanPeriod(period.substr(pos+1),
mPeriodEveryValue, mPeriodEveryUnit)) )
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected a period like:> "
<< "every?delay#unit !!!" << std::endl;
return false;
}
}
else if( period.find("after") == 0 )
{
mPeriodKind |= AVM_PERIOD_AFTER_KIND;
pos = period.find('?');
if( (pos != std::string::npos) &&
(not scanPeriod(period.substr(pos+1),
mPeriodAfterValue, mPeriodAfterUnit)) )
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected a period like:> "
<< "after?delay#unit !!!" << std::endl;
return false;
}
}
else if( period.find("before") == 0 )
{
mPeriodKind |= AVM_PERIOD_BEFORE_KIND;
pos = period.find('?');
if( (pos != std::string::npos) &&
(not scanPeriod(period.substr(pos+1),
mPeriodBeforeValue, mPeriodBeforeUnit)) )
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected a period like:> "
<< "before?delay#unit !!!" << std::endl;
return false;
}
}
else
{
theVFS->errorLocation(AVM_OS_WARN)
<< "Expected a period like:> "
<< "[ init ][:][ otf | (every | after | before)?"
"value#unit][:][ exit ] !!!" << std::endl;
return false;
}
}
return( true );
}
/**
*******************************************************************************
* SERIALIZATION
*******************************************************************************
*/
std::string SerializerFeature::strPeriodKind(avm_period_kind_t kind)
{
switch ( kind )
{
case AVM_PERIOD_INIT_KIND : return( "init");
case AVM_PERIOD_EXIT_KIND : return( "exit");
case AVM_PERIOD_OTF_KIND : return( "otf");
case AVM_PERIOD_EVERY_KIND : return( "every");
case AVM_PERIOD_AFTER_KIND : return( "after");
case AVM_PERIOD_BEFORE_KIND : return( "before");
case AVM_PERIOD_UNDEFINED_KIND : return( "undefined<period#kind>");
default : return( "unknown<period#kind>" );
}
}
void SerializerFeature::toStream(OutStream & os) const
{
os << TAB << "report:" << EOL;
os << TAB2 << "details = "
<< (mReportDetailsFlag ? "true" : "false") << ";"
<< EOL_INCR_INDENT;
VectorOfAvmUri::const_iterator it = mTableOfURI.begin();
VectorOfAvmUri::const_iterator endIt = mTableOfURI.end();
for( ; it != endIt ; ++it )
{
(*it).toStream(os);
}
std::string sep = "";
os << DECR_INDENT_TAB2 << "when = ";
if( IS_PERIOD_INIT_KIND(mPeriodKind) )
{
os << "init";
sep = ":";
}
if( IS_PERIOD_AFTER_KIND(mPeriodKind) )
{
os << (sep = ":") << "after?" << mPeriodAfterValue
<< "#" << strUnit(mPeriodAfterUnit);
;
}
if( IS_PERIOD_OTF_KIND(mPeriodKind) )
{
os << (sep = ":") << "otf";
}
if( IS_PERIOD_EVERY_KIND(mPeriodKind) )
{
os << (sep = ":") << "every?" << mPeriodEveryValue
<< "#" << strUnit(mPeriodEveryUnit);
}
if( IS_PERIOD_BEFORE_KIND(mPeriodKind) )
{
os << (sep = ":") << "before?" << mPeriodBeforeValue
<< "#" << strUnit(mPeriodBeforeUnit);
}
if( IS_PERIOD_EXIT_KIND(mPeriodKind) )
{
os << (sep = ":") << "exit";
}
os << ";" << EOL;
}
} /* namespace sep */