IpfixCollectorCfg::IpfixCollectorCfg(XMLElement* elem)
	: CfgHelper<IpfixCollector, IpfixCollectorCfg>(elem, "ipfixCollector"),
	listener(NULL),
	ipfixCollector(NULL)
{
	if (!elem)
		return;

	msg(MSG_INFO, "IpfixCollectorCfg: Start reading ipfixCollector section");
	udpTemplateLifetime = getInt("udpTemplateLifetime", -1);

	// Config for DTLS
	certificateChainFile = getOptional("cert");
	privateKeyFile = getOptional("key");
	caFile = getOptional("CAfile");
	caPath = getOptional("CApath");
	// observationDomainId = getInt("observationDomainId", 0);
	
	XMLNode::XMLSet<XMLElement*> set = elem->getElementChildren();
	for (XMLNode::XMLSet<XMLElement*>::iterator it = set.begin();
	     it != set.end();
	     it++) {
		XMLElement* e = *it;

		if (e->matches("listener")) {
			if (listener)
				THROWEXCEPTION("listener already set. There can only be one <listener> Element per Collector.");
			listener = new CollectorCfg(e);
			if (listener->getMtu() != 0) {
				delete listener;
				THROWEXCEPTION("You can not set the MTU for a listener.");
			}
		} else if (e->matches("udpTemplateLifetime")) { // already done
		} else if (e->matches("next")) { // ignore next
		} else if (e->matches("cert") || e->matches("key") ||
				e->matches("CAfile") || e->matches("CApath")) {
			// already done!
		} else {
			msg(MSG_FATAL, "Unkown collector config statement %s", e->getName().c_str());
			continue;
		}
	}

	if (listener == NULL)
		THROWEXCEPTION("collectingProcess has to listen on one address!");

	if (listener->getProtocol() != UDP &&
			listener->getProtocol() != SCTP &&
			listener->getProtocol() != DTLS_OVER_UDP &&
			listener->getProtocol() != DTLS_OVER_SCTP)
		THROWEXCEPTION("collectingProcess can handle only UDP or SCTP!");
	
	msg(MSG_INFO, "IpfixCollectorCfg: Successfully parsed collectingProcess section");
}
void ComplexXMLParser10x::parseWeightTypeFromXML(
    const XMLElem gridRowColXML,
    mem::ScopedCopyablePtr<WeightType>& obj) const
{
    const XMLElem weightType = getOptional(gridRowColXML, "WgtType");
    if (weightType)
    {
        obj.reset(new WeightType());
        parseString(getFirstAndOnly(weightType, "WindowName"),
                    obj->windowName);
        common().parseParameters(weightType, "Parameter", obj->parameters);
    }
    else
    {
        obj.reset();
    }
}
void ComplexXMLParser10x::parseRadarCollectionFromXML(
        const XMLElem radarCollectionXML,
        RadarCollection* radarCollection) const
{
    XMLElem tmpElem = getFirstAndOnly(radarCollectionXML, "TxFrequency");
    parseDouble(getFirstAndOnly(tmpElem, "Min"),
                radarCollection->txFrequencyMin);
    parseDouble(getFirstAndOnly(tmpElem, "Max"),
                radarCollection->txFrequencyMax);

    tmpElem = getOptional(radarCollectionXML, "RefFreqIndex");
    if (tmpElem)
    {
        //optional
        parseInt(tmpElem, radarCollection->refFrequencyIndex);
    }

    tmpElem = getOptional(radarCollectionXML, "Waveform");
    if (tmpElem)
    {
        //optional
        parseWaveformFromXML(tmpElem, radarCollection->waveform);
    }

    tmpElem = getFirstAndOnly(radarCollectionXML, "TxPolarization");
    radarCollection->txPolarization = six::toType<PolarizationSequenceType>(
            tmpElem->getCharacterData());

    tmpElem = getOptional(radarCollectionXML, "TxSequence");
    if (tmpElem)
    {
        //optional
        parseTxSequenceFromXML(tmpElem, radarCollection->txSequence);
    }

    tmpElem = getFirstAndOnly(radarCollectionXML, "RcvChannels");

    std::vector<XMLElem> channelsXML;
    tmpElem->getElementsByTagName("ChanParameters", channelsXML);
    if (channelsXML.empty())
    {
        throw except::Exception(Ctxt(
                "Expected at least one ChanParameters element"));
    }

    for (std::vector<XMLElem>::const_iterator it = channelsXML.begin();
         it != channelsXML.end();
         ++it)
    {
        radarCollection->rcvChannels.resize(
                radarCollection->rcvChannels.size() + 1);
        mem::ScopedCloneablePtr<ChannelParameters>& chanParams =
                radarCollection->rcvChannels.back();
        chanParams.reset(new ChannelParameters());

        XMLElem childXML = getFirstAndOnly(*it, "TxRcvPolarization");
        chanParams->txRcvPolarization = six::toType<DualPolarizationType>(
                childXML->getCharacterData());

        childXML = getOptional(*it, "RcvAPCIndex");
        if (childXML)
        {
            parseInt(childXML, chanParams->rcvAPCIndex);
        }
    }

    XMLElem areaXML = getOptional(radarCollectionXML, "Area");
    if (areaXML)
    {
        //optional
        parseAreaFromXML(areaXML, true, false, radarCollection->area);
    }

    common().parseParameters(radarCollectionXML, "Parameter",
                    radarCollection->parameters);
}
void ComplexXMLParser10x::parseMatchInformationFromXML(
    const XMLElem matchInfoXML, 
    MatchInformation* matchInfo) const
{
    int numMatchTypes = 0;
    parseInt(getFirstAndOnly(matchInfoXML, "NumMatchTypes"), numMatchTypes);

    //TODO make sure there is at least one
    std::vector < XMLElem > typesXML;
    matchInfoXML->getElementsByTagName("MatchType", typesXML);

    //! validate the numMatchTypes
    if (typesXML.size() != (size_t)numMatchTypes)
    {
        throw except::Exception(
            Ctxt("NumMatchTypes does not match number of MatchType fields"));
    }

    for (size_t i = 0; i < typesXML.size(); i++)
    {
        // The MatchInformation object was given a MatchType when
        // it was instantiated.  The first time through, just populate it.
        if (i != 0)
        {
            matchInfo->types.push_back(
                mem::ScopedCopyablePtr<MatchType>(new MatchType()));
        }
        MatchType* type = matchInfo->types[i].get();

        parseString(getFirstAndOnly(typesXML[i], "TypeID"), type->typeID);

        XMLElem curIndexElem = getOptional(typesXML[i], "CurrentIndex");
        if (curIndexElem)
        {
            //optional
            parseInt(curIndexElem, type->currentIndex);
        }

        int numMatchCollections = 0;
        parseInt(getFirstAndOnly(typesXML[i], "NumMatchCollections"), 
                 numMatchCollections);

        std::vector < XMLElem > matchCollectionsXML;
        typesXML[i]->getElementsByTagName("MatchCollection", matchCollectionsXML);

        //! validate the numMatchTypes
        if (matchCollectionsXML.size() !=
            static_cast<size_t>(numMatchCollections))
        {
            throw except::Exception(
                Ctxt("NumMatchCollections does not match number of " \
                     "MatchCollect fields"));
        }

        // Need to make sure this is resized properly - at MatchType
        // construction time, matchCollects is initialized to size 1, but in
        // SICD 1.1 this entire block may be missing.
        type->matchCollects.resize(matchCollectionsXML.size());
        for (size_t jj = 0; jj < matchCollectionsXML.size(); jj++)
        {
            MatchCollect& collect(type->matchCollects[jj]);

            parseString(getFirstAndOnly(
                matchCollectionsXML[jj], "CoreName"), collect.coreName);

            XMLElem matchIndexXML = 
                getOptional(matchCollectionsXML[jj], "MatchIndex");
            if (matchIndexXML)
            {
                parseInt(matchIndexXML, collect.matchIndex);
            }

            common().parseParameters(
                matchCollectionsXML[jj], "Parameter", collect.parameters);
        }
    }
}