bool CoverageConnector::storeMetaData(IlwisObject *obj, IlwisTypes type, const DataDefinition& datadef)
{
    bool ok = Ilwis3Connector::storeMetaData(obj, type);
    if ( !ok)
        return false;

    Coverage *coverage = static_cast<Coverage *>(obj);

    const ICoordinateSystem csy = coverage->coordinateSystem();
    if (!csy.isValid())
        return ERROR2(ERR_NO_INITIALIZED_2, "CoordinateSystem", coverage->name());

    QString localName = Resource::toLocalFile(csy->source().url(),true);
    if ( localName == sUNDEF) {
        localName = CoordinateSystemConnector::createCsyFromCode(csy->code());
    }
    if ( localName == sUNDEF) {
        return ERROR2(ERR_NO_INITIALIZED_2, "CoordinateSystem", coverage->name());
    }
    _odf->setKeyValue("BaseMap","CoordSystem", localName);
    Box2D<double> bounds = coverage->envelope();
    if(!bounds.isValid())
        return ERROR2(ERR_NO_INITIALIZED_2, "Bounds", coverage->name());

    _odf->setKeyValue("BaseMap","CoordBounds",QString("%1 %2 %3 %4").
                      arg(bounds.min_corner().x(),10,'f').
                      arg(bounds.min_corner().y(),10,'f').
                      arg(bounds.max_corner().x(),10,'f').
                      arg(bounds.max_corner().y(),10,'f'));

    const IDomain dom = datadef.domain();
    if (!dom.isValid())
        return ERROR2(ERR_NO_INITIALIZED_2, "Domain", coverage->name());

    calcStatics(obj,NumericStatistics::pBASIC);
    if ( dom->ilwisType() == itNUMERICDOMAIN) {

        quint16 digits = coverage->statistics().significantDigits();
        qint32 delta = coverage->statistics()[NumericStatistics::pDELTA];
        if ( delta >= 0 && delta < 256 && digits == 0){
            if ( delta >= 0 && delta < 256 && digits == 0){
                if ( datadef.domain()->code() == "boolean"){
                    QString domInfo = QString("bool.dom;Byte;bool;0;;");
                    _odf->setKeyValue("BaseMap","DomainInfo",domInfo);
                    _odf->setKeyValue("BaseMap","Range","0:1:offset=-1");
                    _odf->setKeyValue("BaseMap","Domain","bool.dom");
                }
                else{
                    QString domInfo = QString("Image.dom;Byte;image;0;;");
                    _odf->setKeyValue("BaseMap","DomainInfo",domInfo);
                    _odf->setKeyValue("BaseMap","Range","0:255:offset=0");
                    _odf->setKeyValue("BaseMap","MinMax","0:255");
                    _odf->setKeyValue("BaseMap","Domain","Image.dom");
                }
            }
        }
        else {
            const NumericStatistics& stats = coverage->statistics();
            int digits = stats.significantDigits();
            RawConverter conv(stats[NumericStatistics::pMIN], stats[NumericStatistics::pMAX],pow(10, - digits));
            QString rangeString = QString("%1:%2:%3:offset=%4").arg(stats[NumericStatistics::pMIN]).arg(stats[NumericStatistics::pMAX]).arg(conv.scale()).arg(conv.offset());
            _odf->setKeyValue("BaseMap","Range",rangeString);
            _odf->setKeyValue("BaseMap","Domain","value.dom");

            _odf->setKeyValue("BaseMap","MinMax",QString("%1:%2").arg(stats[NumericStatistics::pMIN]).arg(stats[NumericStatistics::pMAX]));
            QString domInfo = QString("value.dom;Long;value;0;-9999999.9:9999999.9:0.1:offset=0");
            _odf->setKeyValue("BaseMap","DomainInfo",domInfo);
        }
    } if ( dom->ilwisType() == itITEMDOMAIN) {
        QString source = Resource::toLocalFile(dom->source().url(), true);
        if ( dom->valueType() == itTHEMATICITEM && coverage->ilwisType() == itRASTER) {
            IThematicDomain themdom = dom.get<ThematicDomain>();
            if ( themdom.isValid()) {
                QString domInfo = QString("%1;Byte;class;%2;;").arg(source).arg(themdom->count());
                _odf->setKeyValue("BaseMap","DomainInfo",domInfo);
                _odf->setKeyValue("BaseMap","Domain",source);
            }
        } else if(dom->valueType() == itINDEXEDITEM) {
            QString domName = _odf->fileinfo().fileName();
            QString domInfo = QString("%1;Long;UniqueID;0;;").arg(domName);
            _odf->setKeyValue("BaseMap","DomainInfo",domInfo);
            _odf->setKeyValue("BaseMap","Domain",domName);
        } else if ( dom->valueType() == itNAMEDITEM) {
            INamedIdDomain iddom = dom.get<NamedIdDomain>();
            QString domName = _odf->fileinfo().fileName();
            int index;
            if ( (index=domName.lastIndexOf("."))!= -1)             {
                domName = domName.left(index);
            }
            QString domInfo = QString("%1;;Int;id;%2;;").arg(domName).arg(iddom->count());
            _odf->setKeyValue("BaseMap","DomainInfo",domInfo);
            _odf->setKeyValue("BaseMap","Domain",domName);
            iddom->connectTo(QUrl(),"domain","ilwis3", IlwisObject::cmOUTPUT);
            iddom->store(Ilwis::IlwisObject::smMETADATA | Ilwis::IlwisObject::smBINARYDATA);
        }
    }

    ITable attTable = coverage->attributeTable();
    if ( attTable.isValid()) {
        QScopedPointer<TableConnector> conn(createTableConnector(attTable, coverage, type));
        conn->storeMetaData(attTable.ptr());
    }
    return true;
}
Ilwis::OperationImplementation::State CreateRasterCoverage::prepare(ExecutionContext *ctx, const SymbolTable &st)
{
    OperationImplementation::prepare(ctx,st);
    auto CreateStackDomain = [&](const QString& dom)-> Ilwis::OperationImplementation::State{
        _stackDomain.prepare(dom);
        if ( !_stackDomain.isValid()){
            kernel()->issues()->log(QString(TR("%1 is and invalid stack domain")).arg(dom));
            return sPREPAREFAILED;
        }
        return sPREPARED;
    };

    QString grf = _expression.input<QString>(0);
    _grf.prepare(grf);
    if ( !_grf.isValid()){
        kernel()->issues()->log(QString(TR("%1 is and invalid georeference")).arg(grf));
        return sPREPAREFAILED;
    }
    QString maps = _expression.input<QString>(2);
    if ( maps != sUNDEF && (maps.indexOf("?") != -1 || maps.indexOf("*") != -1)){
        maps = OperationHelper::expandWildCards(maps);
    }
    if (maps != "" && maps != sUNDEF && maps != "default"){
        QStringList bands = maps.split(",");
        for(QString band : bands){
            IRasterCoverage raster(band);
            if ( raster.isValid() && ( raster->georeference()->isCompatible(_grf) || _autoresample)){
                _bands.push_back(raster);
                _ranges.push_back(raster->datadef().range()->clone());
            }else{
                kernel()->issues()->log(QString(TR("%1 is and invalid band; raster can not be build")).arg(raster->name()));
                return sPREPAREFAILED;
            }
        }
    }

    QString dom = _expression.input<QString>(1);
    if ( dom == "as bands"){
        if (_bands.size() > 0)
            dom = _bands[0]->datadef().domain()->resource().url().toString();
        else
            dom = "value";
    }
    _domain.prepare(dom);
    if ( !_domain.isValid()){
        kernel()->issues()->log(QString(TR("%1 is and invalid domain")).arg(dom));
        return sPREPAREFAILED;
    }
    QString potentialCatalog = _expression.input<QString>(4);
    ICatalog cat;
    if (cat.prepare(potentialCatalog, { "mustexist", true })) {
        auto resources = cat->items();
        QString domainName = _expression.input<QString>(3);
        QString path = cat->resource().container().toString();
        INamedIdDomain dom;
        if (dom.prepare(domainName, { "extendedtype",itNAMEDITEM})) {
            for (auto resource : resources) {
                NamedIdentifier *item = new NamedIdentifier(resource.name());
                dom->addItem(item);
            }
            dom->connectTo(path + "/" + domainName, "domain", "stream", IlwisObject::cmOUTPUT);
            dom->store();
            _stackDomain = dom;
            for (auto band : _bands)
                _stackValueStrings.push_back(band->name());
        }
    }
    else {
        _stackDomain = IDomain("positiveInteger");
        _stackValueStrings = { "1" };
        _stackValueNumbers = { 1 };
    }
    if ( _expression.parameterCount() >= 4){
        for(int i=3; i < _expression.parameterCount(); ++i){
            if ( hasType(_expression.parm(i).valuetype(),itSTRING|itINTEGER)){
				ParseStackDefinition parser;
                parser.parseStackDefintion(_expression.input<QString>(i), _bands.size(), _stackDomain,_stackValueStrings, _stackValueNumbers);
            }
            else if ( hasType(_expression.parm(i).valuetype(),itDOMAIN)){
                if (CreateStackDomain(_expression.input<QString>(i)) == sPREPAREFAILED)
                    return sPREPAREFAILED;
            }
            else if ( hasType(_expression.parm(i).valuetype(),itBOOL) && maps.size() != 0){
                _autoresample = _expression.input<bool>(i);
            }
        }
    }


    _outputRaster.prepare();
    _outputRaster->georeference(_grf);
    _outputRaster->size( Size<>(_grf->size().xsize(), _grf->size().ysize(), std::max(_stackValueNumbers.size(), _stackValueStrings.size())));
    if ( _stackDomain->ilwisType() == itNUMERICDOMAIN)
        _outputRaster->setDataDefintions(_domain, _stackValueNumbers , _stackDomain);
    else
         _outputRaster->setDataDefintions(_domain, _stackValueStrings, _stackDomain);

    for(quint32 i=0; i < _ranges.size(); ++i){
        if ( i < _outputRaster->size().zsize()){
           _outputRaster->datadefRef(i).range(_ranges[i]);
        }

    }
    initialize(_outputRaster->size().linearSize());
    return sPREPARED;
}
bool FeatureConnector::storeMetaData(FeatureCoverage *fcov, IlwisTypes type) {
    if ( type == itUNKNOWN)
        return true;//if type is itUNKNOWN we dont store
    DataDefinition datadef;

    ITable attTable = fcov->attributeTable();
    QString primkey = attTable->primaryKey();
    if (primkey == sUNDEF)
        primkey = COVERAGEKEYCOLUMN;
    int index = attTable->columnIndex(primkey);
    if ( index != iUNDEF ) {
        const ColumnDefinition& coldef = attTable->columndefinitionRef(index);
        if ( coldef.datadef().domain<>()->ilwisType() == itITEMDOMAIN)
            datadef = DataDefinition(coldef.datadef().domain(),coldef.datadef().range()->clone());
    }
    if ( !datadef.isValid()) {
        INamedIdDomain indexdom;
        indexdom.prepare();
        indexdom->name(fcov->name());
        NamedIdentifierRange range;
        for(quint32 i=0; i < fcov->featureCount(type); ++i){
            QStringList parts = Ilwis3Connector::ilwis3ClassName(type).split(" ");
            QString itemname = QString("%1_%2").arg(parts[0]).arg(i);
            range << itemname;
        }
        indexdom->setRange(range);
        datadef.domain(indexdom);
        QFileInfo inf ( _resource.url(true).toLocalFile());
        QString filename = context()->workingCatalog()->filesystemLocation().toLocalFile() + "/" + inf.baseName() + ".dom";
        indexdom->connectTo(filename,"domain","ilwis3", Ilwis::IlwisObject::cmOUTPUT);
        indexdom->store();
    }
    bool isMulti = (fcov->featureTypes() & (fcov->featureTypes() - 1)) != 0;
    QString baseName = Ilwis3Connector::outputNameFor(fcov, isMulti, type);
    index = baseName.lastIndexOf(".");
    if ( index != -1) {
        baseName = baseName.left(index);
    }

    bool ok = CoverageConnector::storeMetaData(fcov, type, datadef, baseName);
    if ( !ok)
        return false;

    if ( datadef.domain()->valueType() == itINDEXEDITEM) {
        _odf->setKeyValue("Domain","Type","DomainUniqueID");
        _odf->setKeyValue("DomainSort","Sorting","AlphaNumeric");
        _odf->setKeyValue("DomainSort","Prefix","feature");
        _odf->setKeyValue("DomainSort","Class","Domain UniqueID");
        _odf->setKeyValue("DomainIdentifier","Nr",IniFile::FormatElement(fcov->featureCount(type)));
    }

    Envelope bounds = fcov->envelope();
    if ( bounds.isNull() || !bounds.isValid())
        bounds = fcov->coordinateSystem()->envelope();

    _odf->setKeyValue("BaseMap","CoordBounds",QString("%1 %2 %3 %4").
                      arg(bounds.min_corner().x,0,'f',10).
                      arg(bounds.max_corner().y,0,'f',10).
                      arg(bounds.max_corner().x,0,'f',10).
                      arg(bounds.min_corner().y,0,'f',10));

    QString ext = "mpa";
    if ( hasType(type, itPOLYGON)){
        ok = storeMetaPolygon(fcov, baseName);
    }
    if ( hasType(type, itLINE)){
        ok = storeMetaLine(fcov, baseName);
        ext = "mps";
    }
    if ( hasType(type, itPOINT)){
        ok = storeMetaPoint(fcov, baseName);
        ext = "mpp";
    }
    if ( attTable.isValid() && attTable->columnCount() > 0) {
        QFileInfo basename (baseName);
        QScopedPointer<TableConnector> conn(createTableStoreConnector(attTable, fcov, type, basename.baseName()));
        std::vector<quint32> recs(_itemCount);
        conn->selectedRecords(recs);
        conn->storeMetaData(attTable.ptr());
    }

    _odf->store(ext, QFileInfo(baseName));
    return ok;
}