AddDelServerLoggingCommand::AddDelServerLoggingCommand(
        const QString& name, const QString& type,
        QMap<QString,QString> props,
        ProjectWindow* pw, MainWindow* mw ) :
    Command(pw, mw,
            qApp->translate("AddDelServerLoggingCommand", "Add ServerLogging")),
    d(new AddDelServerLoggingCommandPrivate)
{
    Q_CHECK_PTR(d);

    d->mode = AddDelServerLoggingCommandPrivate::Add;
    d->cn = name;
    d->ct = type;
    d->props = props;

    PropertyDict pd;
    for(QMap<QString,QString>::const_iterator it = d->props.begin();
            it != d->props.end(); ++it) {

        Property* p = new Property(it.key(), "string", it.data());
        Q_CHECK_PTR(p);
        pd.insert(it.key(), p);
    }
    d->sl = new ServerLogging(d->ct, pd);
    Q_CHECK_PTR(d->sl);

    d->canDelete = true;
}
void
PropertiesAdminI::setProperties_async(const AMD_PropertiesAdmin_setPropertiesPtr& cb, const PropertyDict& props,
                                           const Current&)
{
    Lock sync(*this);

    PropertyDict old = _properties->getPropertiesForPrefix("");
    PropertyDict::const_iterator p;
    const int traceLevel = _properties->getPropertyAsInt("Ice.Trace.Admin.Properties");

    //
    // Compute the difference between the new property set and the existing property set:
    //
    // 1) Any properties in the new set that were not defined in the existing set.
    //
    // 2) Any properties that appear in both sets but with different values.
    //
    // 3) Any properties not present in the new set but present in the existing set.
    //    In other words, the property has been removed.
    //
    PropertyDict added, changed, removed;
    for(p = props.begin(); p != props.end(); ++p)
    {
        PropertyDict::iterator q = old.find(p->first);
        if(q == old.end())
        {
            if(!p->second.empty())
            {
                //
                // This property is new.
                //
                added.insert(*p);
            }
        }
        else
        {
            if(p->second != q->second)
            {
                if(p->second.empty())
                {
                    //
                    // This property was removed.
                    //
                    removed.insert(*p);
                }
                else
                {
                    //
                    // This property has changed.
                    //
                    changed.insert(*p);
                }
            }
        }
    }

    if(traceLevel > 0 && (!added.empty() || !changed.empty() || !removed.empty()))
    {
        Trace out(_logger, traceCategory);

        out << "Summary of property changes";

        if(!added.empty())
        {
            out << "\nNew properties:";
            for(p = added.begin(); p != added.end(); ++p)
            {
                out << "\n  " << p->first;
                if(traceLevel > 1)
                {
                    out << " = " << p->second;
                }
            }
        }

        if(!changed.empty())
        {
            out << "\nChanged properties:";
            for(p = changed.begin(); p != changed.end(); ++p)
            {
                out << "\n  " << p->first;
                if(traceLevel > 1)
                {
                    out << " = " << p->second << " (old value = " << _properties->getProperty(p->first) << ")";
                }
            }
        }

        if(!removed.empty())
        {
            out << "\nRemoved properties:";
            for(p = removed.begin(); p != removed.end(); ++p)
            {
                out << "\n  " << p->first;
            }
        }
    }

    //
    // Update the property set.
    //

    for(p = added.begin(); p != added.end(); ++p)
    {
        _properties->setProperty(p->first, p->second);
    }

    for(p = changed.begin(); p != changed.end(); ++p)
    {
        _properties->setProperty(p->first, p->second);
    }

    for(p = removed.begin(); p != removed.end(); ++p)
    {
        _properties->setProperty(p->first, "");
    }

    //
    // Send the response now so that we do not block the client during
    // the call to the update callback.
    //
    cb->ice_response();

    //
    // Copy the callbacks to allow callbacks to update the callbacks.
    //
    vector<PropertiesAdminUpdateCallbackPtr> callbacks = _updateCallbacks;
    if(!callbacks.empty())
    {
        PropertyDict changes = added;
        changes.insert(changed.begin(), changed.end());
        changes.insert(removed.begin(), removed.end());
        for(vector<PropertiesAdminUpdateCallbackPtr>::const_iterator p = callbacks.begin(); p != callbacks.end(); ++p)
        {
            try
            {
                (*p)->updated(changes);
            }
            catch(...)
            {
                // Ignore.
            }
        }
    }
}