<commit_before>

//
// Copyright (c) 2011 Limit Point Systems, Inc.
//

/// @file
/// Implementation for class hub_index_space_iterator

#include "hub_index_space_iterator.h"

#include "assert_contract.h"
#include "explicit_index_space_handle.h"
#include "index_space_family.h"
#include "interval_set_iterator.h"
#include "primary_sum_index_space_state.h"

// ===========================================================
// HUB_INDEX_SPACE_ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

sheaf::hub_index_space_iterator::
hub_index_space_iterator()
{
  // Preconditions:

  // Body:

  _mbr_itr = 0;

  // Postconditions:

  ensure(invariant());
  ensure(!is_attached());

  // Exit:

  return;
}

sheaf::hub_index_space_iterator::
hub_index_space_iterator(const hub_index_space_iterator& xother)
{
  // Preconditions:

  // Body:

  *this = xother;

  // Postconditions:

  ensure(invariant());
  ensure((*this) == xother);

  // Exit:

  return;
}

sheaf::hub_index_space_iterator::
hub_index_space_iterator(const index_space_family& xid_spaces,
			 pod_type xindex)
{
  // Preconditions:

  require(conforms_to_state(xid_spaces, xindex));

  // Body:

  attach_to(xid_spaces, xindex);

  // Postconditions:

  ensure(invariant());
  ensure(is_attached());
  ensure(&id_spaces() == &xid_spaces);
  ensure(index() == xindex);

  // Exit:

  return;
}

sheaf::hub_index_space_iterator::
hub_index_space_iterator(const index_space_family& xid_spaces,
			 const string& xname)
{
  // Preconditions:

  require(conforms_to_state(xid_spaces, xname));

  // Body:

  attach_to(xid_spaces, xname);

  // Postconditions:

  ensure(invariant());
  ensure(is_attached());
  ensure(&id_spaces() == &xid_spaces);
  ensure(name() == xname);

  // Exit:

  return;
}

sheaf::hub_index_space_iterator&
sheaf::hub_index_space_iterator::
operator=(const hub_index_space_iterator& xother)
{
  // Preconditions:

  // Body:

  _mbr_itr = new interval_set_iterator(*xother._mbr_itr);
  _rem     = xother._rem;

  (void) explicit_index_space_iterator::operator=(xother);

  // Postconditions:

  ensure(invariant());
  ensure((*this) == xother);

  // Exit

  return *this;
}

sheaf::hub_index_space_iterator::
~hub_index_space_iterator()
{
  // Preconditions:

  // Body:

  if(_mbr_itr != 0)
  {
    delete _mbr_itr;
  }

  // Postconditions:

  // Exit:

  return;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MEMBER FUNCTIONS

// ===========================================================
// EXPLICIT_INDEX_SPACE_ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MAMBER FUNCTIONS

// ===========================================================
// INDEX_SPACE_ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

sheaf::hub_index_space_iterator&
sheaf::hub_index_space_iterator::
operator=(const index_space_iterator& xother)
{
  // Preconditions:

  require(is_ancestor_of(&xother));

  // Body:

  const hub_index_space_iterator& lother =
    dynamic_cast<const hub_index_space_iterator&>(xother);

  (void) this->operator=(lother);

  // Postconditions:

  ensure(invariant());
  ensure((*this) == xother);

  // Exit

  return *this;
}

bool
sheaf::hub_index_space_iterator::
operator==(const index_space_iterator& xother) const
{
  // Preconditions:

  require(is_ancestor_of(&xother));

  // Body:

  bool result = explicit_index_space_iterator::operator==(xother);
  if(result && is_attached())
  {
    const hub_index_space_iterator& lother =
      dynamic_cast<const hub_index_space_iterator&>(xother);

    result = result && (*_mbr_itr == *lother._mbr_itr);
    result = result && (_rem == lother._rem);
  }

  // Postconditions:

  ensure(invariant());

  // Exit

  return result;
}

sheaf::hub_index_space_iterator*
sheaf::hub_index_space_iterator::
clone() const
{
  hub_index_space_iterator* result;

  // Preconditions:

  // Body:

  result = new hub_index_space_iterator(*this);

  // Postconditions:

  ensure(result != 0);
  ensure(is_same_type(result));
  ensure(*result == *this);

  // Exit:

  return result;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MAMBER FUNCTIONS

// ===========================================================
// ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

void
sheaf::hub_index_space_iterator::
next()
{
  // Preconditions:

  require(is_attached());
  require(!is_done());

  // Body:

  define_old_variable(pod_type old_pod = pod());
  define_old_variable(pod_type old_hub_pod = hub_pod());

  // Iterate to the next member.

  _mbr_itr->next();

  if(_mbr_itr->is_done())
  {
    // The iteration is done.

    invalidate_ids();
  }
  else
  {
    // Still iterating over member ids;
    // set the ids.

    _pod = _mbr_itr->item();
    _hub_pod = _pod;
  }

  // Postconditions:

  ensure(invariant());
  ensure(is_done() || pod() > old_pod);
  ensure(is_done() || hub_pod() > old_hub_pod);

  // Exit:

  return;
}

void
sheaf::hub_index_space_iterator::
reset()
{
  // Preconditions:

  require(is_attached());

  // Body:

  _mbr_itr->reset();

  if(_mbr_itr->is_done())
  {
    // The member set is empty, the iteration is done.

    invalidate_ids();
  }
  else
  {
    // There's at least one entry, the iteration is not done.

    _is_done = false;
    _pod = _mbr_itr->item();
    _hub_pod = _pod;
  }

  // Postconditions:

  ensure(invariant());

  // Exit:

  return;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MEMBER FUNCTIONS

// ===========================================================
// HANDLE FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

void
sheaf::hub_index_space_iterator::
attach_to(explicit_index_space_state* xstate)
{
  // Preconditions:

  require(xstate != 0);
  require(conforms_to_state(xstate));

  // Body:

  // Assign the state information.

  primary_sum_index_space_state* lstate =
    reinterpret_cast<primary_sum_index_space_state*>(xstate);

  _state   = xstate;
  _mbr_itr = lstate->_members.iterator(true);
  _rem     = &lstate->_rem;

  // Start at the first id.

  reset();

  // Postconditions:

  ensure(invariant());
  ensure(is_attached());
  ensure(&state() == xstate);

  // Exit:

  return;
}

bool
sheaf::hub_index_space_iterator::
conforms_to_state(explicit_index_space_state* xstate) const
{
  // Preconditions:

  // Body:

  bool result = (dynamic_cast<primary_sum_index_space_state*>(xstate) != 0);

  // Postconditions:

  ensure(is_basic_query);

  // Exit:

  return result;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MAMBER FUNCTIONS

// ===========================================================
// ANY FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

bool
sheaf::hub_index_space_iterator::
is_ancestor_of(const any *other) const
{
  // Preconditions:

  require(other != 0);

  // Body:

  // True if other conforms to this

  bool result =
    dynamic_cast<const hub_index_space_iterator*>(other) != 0;

  // Postconditions:

  return result;
}

bool
sheaf::hub_index_space_iterator::
invariant() const
{
  bool result = true;

  if(invariant_check())
  {
    // Must satisfy base class invariant

    invariance(explicit_index_space_iterator::invariant());

    // Prevent recursive calls to invariant

    disable_invariant_check();

    // Invariances for this class:

    invariance(is_done() || pod() == hub_pod());

    // Finished, turn invariant checking back on.

    enable_invariant_check();
  }

  // Exit

  return result;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MEMBER FUNCTIONS

// ===========================================================
//  NON-MEMBER FUNCTIONS
// ===========================================================

<commit_msg>Fixed memory leak in hub_index_space_iterator.  Was not deleting _mbr_itr when attaching to a new state.  This has nothing to do with the current crash on Windows but was found during the valgrind tests.<commit_after>

//
// Copyright (c) 2011 Limit Point Systems, Inc.
//

/// @file
/// Implementation for class hub_index_space_iterator

#include "hub_index_space_iterator.h"

#include "assert_contract.h"
#include "explicit_index_space_handle.h"
#include "index_space_family.h"
#include "interval_set_iterator.h"
#include "primary_sum_index_space_state.h"

// ===========================================================
// HUB_INDEX_SPACE_ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

sheaf::hub_index_space_iterator::
hub_index_space_iterator()
  : _mbr_itr(0)
{
  // Preconditions:

  // Body:

  // Postconditions:

  ensure(invariant());
  ensure(!is_attached());

  // Exit:

  return;
}

sheaf::hub_index_space_iterator::
hub_index_space_iterator(const hub_index_space_iterator& xother)
{
  // Preconditions:

  // Body:

  *this = xother;

  // Postconditions:

  ensure(invariant());
  ensure((*this) == xother);

  // Exit:

  return;
}

sheaf::hub_index_space_iterator::
hub_index_space_iterator(const index_space_family& xid_spaces,
			 pod_type xindex)
  : _mbr_itr(0)
{
  // Preconditions:

  require(conforms_to_state(xid_spaces, xindex));

  // Body:

  attach_to(xid_spaces, xindex);

  // Postconditions:

  ensure(invariant());
  ensure(is_attached());
  ensure(&id_spaces() == &xid_spaces);
  ensure(index() == xindex);

  // Exit:

  return;
}

sheaf::hub_index_space_iterator::
hub_index_space_iterator(const index_space_family& xid_spaces,
			 const string& xname)
  : _mbr_itr(0)
{
  // Preconditions:

  require(conforms_to_state(xid_spaces, xname));

  // Body:

  attach_to(xid_spaces, xname);

  // Postconditions:

  ensure(invariant());
  ensure(is_attached());
  ensure(&id_spaces() == &xid_spaces);
  ensure(name() == xname);

  // Exit:

  return;
}

sheaf::hub_index_space_iterator&
sheaf::hub_index_space_iterator::
operator=(const hub_index_space_iterator& xother)
{
  // Preconditions:

  // Body:

  _mbr_itr = new interval_set_iterator(*xother._mbr_itr);
  _rem     = xother._rem;

  (void) explicit_index_space_iterator::operator=(xother);

  // Postconditions:

  ensure(invariant());
  ensure((*this) == xother);

  // Exit

  return *this;
}

sheaf::hub_index_space_iterator::
~hub_index_space_iterator()
{
  // Preconditions:

  // Body:

  if(_mbr_itr != 0)
  {
    delete _mbr_itr;
  }

  // Postconditions:

  // Exit:

  return;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MEMBER FUNCTIONS

// ===========================================================
// EXPLICIT_INDEX_SPACE_ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MAMBER FUNCTIONS

// ===========================================================
// INDEX_SPACE_ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

sheaf::hub_index_space_iterator&
sheaf::hub_index_space_iterator::
operator=(const index_space_iterator& xother)
{
  // Preconditions:

  require(is_ancestor_of(&xother));

  // Body:

  const hub_index_space_iterator& lother =
    dynamic_cast<const hub_index_space_iterator&>(xother);

  (void) this->operator=(lother);

  // Postconditions:

  ensure(invariant());
  ensure((*this) == xother);

  // Exit

  return *this;
}

bool
sheaf::hub_index_space_iterator::
operator==(const index_space_iterator& xother) const
{
  // Preconditions:

  require(is_ancestor_of(&xother));

  // Body:

  bool result = explicit_index_space_iterator::operator==(xother);
  if(result && is_attached())
  {
    const hub_index_space_iterator& lother =
      dynamic_cast<const hub_index_space_iterator&>(xother);

    result = result && (*_mbr_itr == *lother._mbr_itr);
    result = result && (_rem == lother._rem);
  }

  // Postconditions:

  ensure(invariant());

  // Exit

  return result;
}

sheaf::hub_index_space_iterator*
sheaf::hub_index_space_iterator::
clone() const
{
  hub_index_space_iterator* result;

  // Preconditions:

  // Body:

  result = new hub_index_space_iterator(*this);

  // Postconditions:

  ensure(result != 0);
  ensure(is_same_type(result));
  ensure(*result == *this);

  // Exit:

  return result;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MAMBER FUNCTIONS

// ===========================================================
// ITERATOR FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

void
sheaf::hub_index_space_iterator::
next()
{
  // Preconditions:

  require(is_attached());
  require(!is_done());

  // Body:

  define_old_variable(pod_type old_pod = pod());
  define_old_variable(pod_type old_hub_pod = hub_pod());

  // Iterate to the next member.

  _mbr_itr->next();

  if(_mbr_itr->is_done())
  {
    // The iteration is done.

    invalidate_ids();
  }
  else
  {
    // Still iterating over member ids;
    // set the ids.

    _pod = _mbr_itr->item();
    _hub_pod = _pod;
  }

  // Postconditions:

  ensure(invariant());
  ensure(is_done() || pod() > old_pod);
  ensure(is_done() || hub_pod() > old_hub_pod);

  // Exit:

  return;
}

void
sheaf::hub_index_space_iterator::
reset()
{
  // Preconditions:

  require(is_attached());

  // Body:

  _mbr_itr->reset();

  if(_mbr_itr->is_done())
  {
    // The member set is empty, the iteration is done.

    invalidate_ids();
  }
  else
  {
    // There's at least one entry, the iteration is not done.

    _is_done = false;
    _pod = _mbr_itr->item();
    _hub_pod = _pod;
  }

  // Postconditions:

  ensure(invariant());

  // Exit:

  return;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MEMBER FUNCTIONS

// ===========================================================
// HANDLE FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

void
sheaf::hub_index_space_iterator::
attach_to(explicit_index_space_state* xstate)
{
  // Preconditions:

  require(xstate != 0);
  require(conforms_to_state(xstate));

  // Body:

  // Assign the state information.

  primary_sum_index_space_state* lstate =
    reinterpret_cast<primary_sum_index_space_state*>(xstate);

  if(_mbr_itr != 0)
  {
    delete _mbr_itr;
  }

  _state   = xstate;
  _mbr_itr = lstate->_members.iterator(true);
  _rem     = &lstate->_rem;

  // Start at the first id.

  reset();

  // Postconditions:

  ensure(invariant());
  ensure(is_attached());
  ensure(&state() == xstate);

  // Exit:

  return;
}

bool
sheaf::hub_index_space_iterator::
conforms_to_state(explicit_index_space_state* xstate) const
{
  // Preconditions:

  // Body:

  bool result = (dynamic_cast<primary_sum_index_space_state*>(xstate) != 0);

  // Postconditions:

  ensure(is_basic_query);

  // Exit:

  return result;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MAMBER FUNCTIONS

// ===========================================================
// ANY FACET
// ===========================================================

// PUBLIC MEMBER FUNCTIONS

bool
sheaf::hub_index_space_iterator::
is_ancestor_of(const any *other) const
{
  // Preconditions:

  require(other != 0);

  // Body:

  // True if other conforms to this

  bool result =
    dynamic_cast<const hub_index_space_iterator*>(other) != 0;

  // Postconditions:

  return result;
}

bool
sheaf::hub_index_space_iterator::
invariant() const
{
  bool result = true;

  if(invariant_check())
  {
    // Must satisfy base class invariant

    invariance(explicit_index_space_iterator::invariant());

    // Prevent recursive calls to invariant

    disable_invariant_check();

    // Invariances for this class:

    invariance(is_done() || pod() == hub_pod());

    // Finished, turn invariant checking back on.

    enable_invariant_check();
  }

  // Exit

  return result;
}

// PROTECTED MEMBER FUNCTIONS

// PRIVATE MEMBER FUNCTIONS

// ===========================================================
//  NON-MEMBER FUNCTIONS
// ===========================================================

<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/shell/platform/mojo/platform_view_mojo.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/application/connect.h"
#include "sky/shell/gpu/mojo/rasterizer_mojo.h"

namespace sky {
namespace shell {
namespace {

pointer::PointerType GetTypeFromAction(mojo::EventType type) {
  switch (type) {
    case mojo::EventType::POINTER_CANCEL:
      return pointer::PointerType::CANCEL;
    case mojo::EventType::POINTER_DOWN:
      return pointer::PointerType::DOWN;
    case mojo::EventType::POINTER_MOVE:
      return pointer::PointerType::MOVE;
    case mojo::EventType::POINTER_UP:
      return pointer::PointerType::UP;
    default:
      DCHECK(false);
      return pointer::PointerType::CANCEL;
  }
}

pointer::PointerKind GetKindFromKind(mojo::PointerKind kind) {
  switch (kind) {
    case mojo::PointerKind::TOUCH:
      return pointer::PointerKind::TOUCH;
    case mojo::PointerKind::MOUSE:
      return pointer::PointerKind::MOUSE;
  }
  DCHECK(false);
  return pointer::PointerKind::TOUCH;
}

}  // namespace

PlatformView* PlatformView::Create(const Config& config) {
  return new PlatformViewMojo(config);
}

PlatformViewMojo::PlatformViewMojo(const Config& config)
  : PlatformView(config), dispatcher_binding_(this) {
}

PlatformViewMojo::~PlatformViewMojo() {
}

void PlatformViewMojo::Init(mojo::Shell* shell) {
  mojo::ConnectToService(shell, "mojo:native_viewport_service", &viewport_);

  // Grab the application connector so that we can connect to services later
  shell->CreateApplicationConnector(GetProxy(&connector_));

  mojo::NativeViewportEventDispatcherPtr ptr;
  dispatcher_binding_.Bind(GetProxy(&ptr));
  viewport_->SetEventDispatcher(ptr.Pass());

  mojo::SizePtr size = mojo::Size::New();
  size->width = 320;
  size->height = 640;

  viewport_->Create(
      size.Clone(),
      mojo::SurfaceConfiguration::New(),
      [this](mojo::ViewportMetricsPtr metrics) {
        OnMetricsChanged(metrics.Pass());
      });
  viewport_->Show();

  mojo::ContextProviderPtr context_provider;
  viewport_->GetContextProvider(GetProxy(&context_provider));

  mojo::InterfacePtrInfo<mojo::ContextProvider> context_provider_info = context_provider.PassInterface();

  RasterizerMojo* rasterizer = static_cast<RasterizerMojo*>(config_.rasterizer);
  config_.ui_task_runner->PostTask(
      FROM_HERE, base::Bind(&UIDelegate::OnOutputSurfaceCreated,
                            config_.ui_delegate,
                            base::Bind(&RasterizerMojo::OnContextProviderAvailable,
                                       rasterizer->GetWeakPtr(), base::Passed(&context_provider_info))));

  ConnectToEngine(GetProxy(&sky_engine_));

}

void PlatformViewMojo::Run(const mojo::String& url,
                           ServicesDataPtr services,
                           mojo::asset_bundle::AssetBundlePtr bundle) {

  mojo::ServiceProviderPtr services_provided_by_embedder;
  service_provider_.Bind(GetProxy(&services_provided_by_embedder));
  service_provider_.AddService<keyboard::KeyboardService>(this);
  services->services_provided_by_embedder = services_provided_by_embedder.Pass();

  sky_engine_->SetServices(services.Pass());
  sky_engine_->RunFromAssetBundle(url, bundle.Pass());
}

void PlatformViewMojo::OnMetricsChanged(mojo::ViewportMetricsPtr metrics) {
  DCHECK(metrics);
  viewport_->RequestMetrics(
      [this](mojo::ViewportMetricsPtr metrics) {
        OnMetricsChanged(metrics.Pass());
      });

  sky::ViewportMetricsPtr sky_metrics = sky::ViewportMetrics::New();
  sky_metrics->physical_width = metrics->size->width;
  sky_metrics->physical_height = metrics->size->height;
  sky_metrics->device_pixel_ratio = metrics->device_pixel_ratio;
  sky_engine_->OnViewportMetricsChanged(sky_metrics.Pass());
}

void PlatformViewMojo::OnEvent(mojo::EventPtr event,
                               const mojo::Callback<void()>& callback) {
  DCHECK(event);
  switch (event->action) {
    case mojo::EventType::POINTER_CANCEL:
    case mojo::EventType::POINTER_DOWN:
    case mojo::EventType::POINTER_MOVE:
    case mojo::EventType::POINTER_UP: {
      mojo::PointerDataPtr data = event->pointer_data.Pass();
      if (!data)
        break;
      pointer::PointerPacketPtr packet;
      int packetIndex = 0;
      if (pointer_positions_.count(data->pointer_id) > 0) {
        if (event->action == mojo::EventType::POINTER_UP ||
            event->action == mojo::EventType::POINTER_CANCEL) {
          std::pair<float, float> last_position = pointer_positions_[data->pointer_id];
          if (last_position.first != data->x || last_position.second != data->y) {
            packet = pointer::PointerPacket::New();
            packet->pointers = mojo::Array<pointer::PointerPtr>::New(2);
            packet->pointers[packetIndex] = CreateEvent(pointer::PointerType::MOVE, event.get(), data.get());
            packetIndex += 1;
          }
          pointer_positions_.erase(data->pointer_id);
        }
      } else {
        // We don't currently support hover moves.
        // If we want to support those, we have to first implement
        // added/removed events for pointers.
        // See: https://github.com/flutter/flutter/issues/720
        if (event->action != mojo::EventType::POINTER_DOWN)
          break;
      }
      if (packetIndex == 0) {
        packet = pointer::PointerPacket::New();
        packet->pointers = mojo::Array<pointer::PointerPtr>::New(1);
      }
      packet->pointers[packetIndex] = CreateEvent(GetTypeFromAction(event->action), event.get(), data.get());
      sky_engine_->OnPointerPacket(packet.Pass());
      break;
    }
    case mojo::EventType::KEY_PRESSED:
    case mojo::EventType::KEY_RELEASED:
      if (key_event_dispatcher_) {
        key_event_dispatcher_->OnEvent(event.Pass(), callback);
        return; // key_event_dispatcher_ will invoke callback
      }
    default:
      break;
  }

  callback.Run();
}

pointer::PointerPtr PlatformViewMojo::CreateEvent(pointer::PointerType type, mojo::Event* event, mojo::PointerData* data) {
  DCHECK(data);
  pointer::PointerPtr pointer = pointer::Pointer::New();
  pointer->time_stamp = event->time_stamp;
  pointer->pointer = data->pointer_id;
  pointer->type = type;
  pointer->kind = GetKindFromKind(data->kind);
  pointer->x = data->x;
  pointer->y = data->y;
  pointer->buttons = static_cast<int32_t>(event->flags);
  pointer->pressure = data->pressure;
  pointer->radius_major = data->radius_major;
  pointer->radius_minor = data->radius_minor;
  pointer->orientation = data->orientation;
  if (event->action != mojo::EventType::POINTER_UP ||
      event->action != mojo::EventType::POINTER_CANCEL)
    pointer_positions_[data->pointer_id] = { data->x, data->y };
  return pointer.Pass();
}

void PlatformViewMojo::Create(
    mojo::ApplicationConnection* connection,
    mojo::InterfaceRequest<keyboard::KeyboardService> request) {

  mojo::ServiceProviderPtr keyboard_service_provider;
  connector_->ConnectToApplication(
    "mojo:keyboard",
    GetProxy(&keyboard_service_provider),
    nullptr);

#if defined(OS_LINUX)
  keyboard::KeyboardServiceFactoryPtr factory;
  mojo::ConnectToService(keyboard_service_provider.get(), &factory);
  factory->CreateKeyboardService(GetProxy(&key_event_dispatcher_), request.Pass());
#else
  keyboard_service_provider->ConnectToService(
    keyboard::KeyboardService::Name_,
    request.PassMessagePipe());
#endif
}

}  // namespace shell
}  // namespace sky
<commit_msg>Fix mouse on linux.<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/shell/platform/mojo/platform_view_mojo.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/application/connect.h"
#include "sky/shell/gpu/mojo/rasterizer_mojo.h"

namespace sky {
namespace shell {
namespace {

pointer::PointerType GetTypeFromAction(mojo::EventType type) {
  switch (type) {
    case mojo::EventType::POINTER_CANCEL:
      return pointer::PointerType::CANCEL;
    case mojo::EventType::POINTER_DOWN:
      return pointer::PointerType::DOWN;
    case mojo::EventType::POINTER_MOVE:
      return pointer::PointerType::MOVE;
    case mojo::EventType::POINTER_UP:
      return pointer::PointerType::UP;
    default:
      DCHECK(false);
      return pointer::PointerType::CANCEL;
  }
}

pointer::PointerKind GetKindFromKind(mojo::PointerKind kind) {
  switch (kind) {
    case mojo::PointerKind::TOUCH:
      return pointer::PointerKind::TOUCH;
    case mojo::PointerKind::MOUSE:
      return pointer::PointerKind::MOUSE;
  }
  DCHECK(false);
  return pointer::PointerKind::TOUCH;
}

}  // namespace

PlatformView* PlatformView::Create(const Config& config) {
  return new PlatformViewMojo(config);
}

PlatformViewMojo::PlatformViewMojo(const Config& config)
  : PlatformView(config), dispatcher_binding_(this) {
}

PlatformViewMojo::~PlatformViewMojo() {
}

void PlatformViewMojo::Init(mojo::Shell* shell) {
  mojo::ConnectToService(shell, "mojo:native_viewport_service", &viewport_);

  // Grab the application connector so that we can connect to services later
  shell->CreateApplicationConnector(GetProxy(&connector_));

  mojo::NativeViewportEventDispatcherPtr ptr;
  dispatcher_binding_.Bind(GetProxy(&ptr));
  viewport_->SetEventDispatcher(ptr.Pass());

  mojo::SizePtr size = mojo::Size::New();
  size->width = 320;
  size->height = 640;

  viewport_->Create(
      size.Clone(),
      mojo::SurfaceConfiguration::New(),
      [this](mojo::ViewportMetricsPtr metrics) {
        OnMetricsChanged(metrics.Pass());
      });
  viewport_->Show();

  mojo::ContextProviderPtr context_provider;
  viewport_->GetContextProvider(GetProxy(&context_provider));

  mojo::InterfacePtrInfo<mojo::ContextProvider> context_provider_info = context_provider.PassInterface();

  RasterizerMojo* rasterizer = static_cast<RasterizerMojo*>(config_.rasterizer);
  config_.ui_task_runner->PostTask(
      FROM_HERE, base::Bind(&UIDelegate::OnOutputSurfaceCreated,
                            config_.ui_delegate,
                            base::Bind(&RasterizerMojo::OnContextProviderAvailable,
                                       rasterizer->GetWeakPtr(), base::Passed(&context_provider_info))));

  ConnectToEngine(GetProxy(&sky_engine_));

}

void PlatformViewMojo::Run(const mojo::String& url,
                           ServicesDataPtr services,
                           mojo::asset_bundle::AssetBundlePtr bundle) {

  mojo::ServiceProviderPtr services_provided_by_embedder;
  service_provider_.Bind(GetProxy(&services_provided_by_embedder));
  service_provider_.AddService<keyboard::KeyboardService>(this);
  services->services_provided_by_embedder = services_provided_by_embedder.Pass();

  sky_engine_->SetServices(services.Pass());
  sky_engine_->RunFromAssetBundle(url, bundle.Pass());
}

void PlatformViewMojo::OnMetricsChanged(mojo::ViewportMetricsPtr metrics) {
  DCHECK(metrics);
  viewport_->RequestMetrics(
      [this](mojo::ViewportMetricsPtr metrics) {
        OnMetricsChanged(metrics.Pass());
      });

  sky::ViewportMetricsPtr sky_metrics = sky::ViewportMetrics::New();
  sky_metrics->physical_width = metrics->size->width;
  sky_metrics->physical_height = metrics->size->height;
  sky_metrics->device_pixel_ratio = metrics->device_pixel_ratio;
  sky_engine_->OnViewportMetricsChanged(sky_metrics.Pass());
}

void PlatformViewMojo::OnEvent(mojo::EventPtr event,
                               const mojo::Callback<void()>& callback) {
  DCHECK(event);
  switch (event->action) {
    case mojo::EventType::POINTER_CANCEL:
    case mojo::EventType::POINTER_DOWN:
    case mojo::EventType::POINTER_MOVE:
    case mojo::EventType::POINTER_UP: {
      mojo::PointerDataPtr data = event->pointer_data.Pass();
      if (!data)
        break;
      pointer::PointerPacketPtr packet;
      int packetIndex = 0;
      if (pointer_positions_.count(data->pointer_id) > 0) {
        if (event->action == mojo::EventType::POINTER_UP ||
            event->action == mojo::EventType::POINTER_CANCEL) {
          std::pair<float, float> last_position = pointer_positions_[data->pointer_id];
          if (last_position.first != data->x || last_position.second != data->y) {
            packet = pointer::PointerPacket::New();
            packet->pointers = mojo::Array<pointer::PointerPtr>::New(2);
            packet->pointers[packetIndex] = CreateEvent(pointer::PointerType::MOVE, event.get(), data.get());
            packetIndex += 1;
          }
          pointer_positions_.erase(data->pointer_id);
        }
      } else {
        // We don't currently support hover moves.
        // If we want to support those, we have to first implement
        // added/removed events for pointers.
        // See: https://github.com/flutter/flutter/issues/720
        if (event->action != mojo::EventType::POINTER_DOWN)
          break;
      }
      if (packetIndex == 0) {
        packet = pointer::PointerPacket::New();
        packet->pointers = mojo::Array<pointer::PointerPtr>::New(1);
      }
      packet->pointers[packetIndex] = CreateEvent(GetTypeFromAction(event->action), event.get(), data.get());
      sky_engine_->OnPointerPacket(packet.Pass());
      break;
    }
    case mojo::EventType::KEY_PRESSED:
    case mojo::EventType::KEY_RELEASED:
      if (key_event_dispatcher_) {
        key_event_dispatcher_->OnEvent(event.Pass(), callback);
        return; // key_event_dispatcher_ will invoke callback
      }
    default:
      break;
  }

  callback.Run();
}

pointer::PointerPtr PlatformViewMojo::CreateEvent(pointer::PointerType type, mojo::Event* event, mojo::PointerData* data) {
  DCHECK(data);
  pointer::PointerPtr pointer = pointer::Pointer::New();
  pointer->time_stamp = event->time_stamp;
  pointer->pointer = data->pointer_id;
  pointer->type = type;
  pointer->kind = GetKindFromKind(data->kind);
  pointer->x = data->x;
  pointer->y = data->y;
  pointer->buttons = static_cast<int32_t>(event->flags);
  pointer->pressure = data->pressure;
  pointer->radius_major = data->radius_major;
  pointer->radius_minor = data->radius_minor;
  pointer->orientation = data->orientation;
  if (event->action != mojo::EventType::POINTER_UP &&
      event->action != mojo::EventType::POINTER_CANCEL)
    pointer_positions_[data->pointer_id] = { data->x, data->y };
  return pointer.Pass();
}

void PlatformViewMojo::Create(
    mojo::ApplicationConnection* connection,
    mojo::InterfaceRequest<keyboard::KeyboardService> request) {

  mojo::ServiceProviderPtr keyboard_service_provider;
  connector_->ConnectToApplication(
    "mojo:keyboard",
    GetProxy(&keyboard_service_provider),
    nullptr);

#if defined(OS_LINUX)
  keyboard::KeyboardServiceFactoryPtr factory;
  mojo::ConnectToService(keyboard_service_provider.get(), &factory);
  factory->CreateKeyboardService(GetProxy(&key_event_dispatcher_), request.Pass());
#else
  keyboard_service_provider->ConnectToService(
    keyboard::KeyboardService::Name_,
    request.PassMessagePipe());
#endif
}

}  // namespace shell
}  // namespace sky
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/KERNEL/bond.h>
#include <BALL/KERNEL/molecule.h>
#include <BALL/KERNEL/PTE.h>
#include <BALL/KERNEL/selector.h>
#include <BALL/FORMAT/molFileFactory.h>
#include <BALL/FORMAT/dockResultFile.h>
#include <BALL/FORMAT/commandlineParser.h>
#include <BALL/STRUCTURE/molecularSimilarity.h>

#include <boost/unordered_map.hpp>

#include <openbabel/mol.h>
#include <openbabel/builder.h>
#include <openbabel/forcefield.h>
#include "version.h"

using namespace BALL;
using namespace std;

// Check whether the given molecule really contains only one molecule
void checkBonds(const Atom* atom, set<const Atom*>& visited_atoms)
{
	if (visited_atoms.find(atom) != visited_atoms.end())
	{
		return;
	}

	visited_atoms.insert(atom);
	for (Atom::BondConstIterator b_it = atom->beginBond(); +b_it; b_it++)
	{
		checkBonds(b_it->getPartner(*atom), visited_atoms);
	}
}

// Check if a molecule has atoms, is single connected component and has elements defined
bool basicMoleculeCheck(Molecule* mol)
{
	// Check if it molecule has no atoms
	if (mol->countAtoms() == 0)
	{
		return false;
	}

	// Check if molecule is a contains a single fragment
	set<const Atom*> visited_atoms;
	checkBonds(&*mol->beginAtom(), visited_atoms);
	if (visited_atoms.size() != mol->countAtoms())
	{
		return false;
	}

	// Check if there are undefined elements
	for (AtomConstIterator it=mol->beginAtom(); it!=mol->endAtom(); ++it)
	{
		if (it->getElement().getName() == BALL_ELEMENT_NAME_DEFAULT)
		{
			return false;
		}
	}

	return true;
}

// Basic check if a ligand contains a hydrogen and thus can be regarded as "protonated"
bool hasHydrogensCheck(Molecule* mol)
{
	for (AtomConstIterator it = mol->beginAtom(); +it; it++)
	{
		if (it->getElement().getSymbol() == "H")
		{
			return true;
		}
	}

	return false;
}

// Check if a valid molecule is ready for docking
bool advancedMoleculeCheck(Molecule* mol)
{
	bool all_x_zero = true;
	bool all_y_zero = true;
	bool all_z_zero = true;

	for (AtomConstIterator it = mol->beginAtom(); +it; it++)
	{
		if (fabs(it->getCharge()) > 5)
		{
			return false;
		}

		for (Atom::BondConstIterator b_it = it->beginBond(); +b_it; b_it++)
		{
			if (b_it->getLength() < 0.7 || b_it->getLength() > 2.5)
			{
				return false;
			}
		}

		const TVector3<float>& pos = it->getPosition();
		if (all_x_zero)
		{
			if (fabs(pos[0]) > 0.001)
			{
				all_x_zero = false;
			}
		}
		if (all_y_zero)
		{
			if (fabs(pos[1]) > 0.001)
			{
				all_y_zero = false;
			}
		}
		if (all_z_zero)
		{
			if (fabs(pos[2]) > 0.001)
			{
				all_z_zero = false;
			}
		}
	}

	if (all_x_zero || all_y_zero || all_z_zero)
	{
		return false;
	}
	else
	{
		return true;
	}
}

int main(int argc, char* argv[])
{
	CommandlineParser parpars("Ligand3DGenerator", "generate 3D coordinates for small molecules", VERSION, String(__DATE__), "Preparation");
	parpars.registerParameter("i", "input file", INFILE, true);
	parpars.registerParameter("o", "output file", OUTFILE, true);
	parpars.registerParameter("ph", "pH-value for pH-dep. protonation", DOUBLE, false, "7.0");
	parpars.registerFlag("rm", "remove input file when finished");
	parpars.registerFlag("k", "keep existing 3D coordinates (flag precedes '-kp')");
	parpars.registerFlag("kp", "keep existing 3D coordinates but re-protonate compound in a pH dependent manner (flag is preceded by '-k')");
	String man = String("This tool takes input molecules and generates a single 3D conformation which is ready for docking. The input has to be a chemical file\n\
containing valid topologies and conistent bond order assignements. 2D coordinates in the input file are overwritten, 3D coordinates can be kept ('-k' or '-kp').\n\n\
  '-k':   3D coordinates are tried to be kept. Molecules with non-zero coordinates in all three dimensions are passed through without modifications. \n\
          However, if a molecule is not ready for docking (i.e. unusual bond leghts, unusual charges), the molecule will be rebuild and new \n\
          3D coordinates are assigned. If only hydrogens are missing, the coordinates of non-hydrogen atoms are kept but the molecule gets newly protonated.\n\
  '-kp':  3D coordinates are tried to be kept as for the '-k' flag but the molecule will be newly protonated.\n\n\
Please note that the main purpose of this tool is to generate valid starting conformations for docking or other optimization procedures.\n\
Therefore, the generated 3D coordinates for each fragment should be all right, but in extreme cases (i.e. very large and/or complex molecules) \n\
different fragments might still overlap with each other.\n\n\
Supported formats are ") + MolFileFactory::getSupportedFormats() + String(".");
	parpars.setToolManual(man);
	parpars.setSupportedFormats("i",MolFileFactory::getSupportedFormats());
	parpars.setSupportedFormats("o",MolFileFactory::getSupportedFormats());
	parpars.setOutputFormatSource("o","i");
	parpars.parse(argc, argv);

	GenericMolFile* input = MolFileFactory::open(parpars.get("i"), ios::in);
	GenericMolFile* output = MolFileFactory::open(parpars.get("o"), ios::out, input);
	DockResultFile* drf_output = dynamic_cast<DockResultFile*>(output);
	if (drf_output)
	{
		drf_output->setToolInfo(parpars.getStartCommand(), parpars.getStartTime());
	}

	double pH = 7.4;
	if (parpars.get("ph") != CommandlineParser::NOT_FOUND)
	{
		pH = parpars.get("ph").toDouble();
	}

	bool keep3Dcoords = false;
	if (parpars.has("k"))
	{
		keep3Dcoords = true;
	}

	bool keep3DcoordsProtonate = false;
	if (parpars.has("kp"))
	{
		keep3DcoordsProtonate = true;
	}

	OpenBabel::OBForceField* pFF = OpenBabel::OBForceField::FindForceField("MMFF94");
	if (!pFF)
	{
		cerr << "[Error:] Openbabel MMFF force-field could not be found.\nPlease make sure to link this executable to plugin_forcefields.so, /otherwise the openbabel forcefield-plugins cannot be used!" << endl;
		exit(1);
	}

	String mol_name;
	bool setup_ok;
	bool ob_error;
	bool rebuild_mol;
	int no_written = 0;
	int no_ignored = 0;
	Molecule *mol, *new_mol;
	OpenBabel::OBMol *obmol;
	boost::unordered_map<unsigned int, OpenBabel::vector3> coord_backup;
	for (Size i=1; (mol = input->read()); i++)
	{
		if (no_written%5 == 0)
		{
			Log.level(20) << "\r" << no_written << " molecules";
			Log.flush();
		}

		mol_name = mol->getName();
		if (mol_name=="")
		{
			mol_name = "?";
		}

		// Check if molecule fulfills minimal validity criteria
		if (!basicMoleculeCheck(mol))
		{
			no_ignored++;

			Log.level(20) << "Error " << mol_name << " is skipped because of either containing no atoms, multiple fragments or undefined elements." << endl;

			delete mol;

			continue;
		}

		if (keep3Dcoords || keep3DcoordsProtonate)
		{
			if (advancedMoleculeCheck(mol))
			{
				rebuild_mol = false;

				if (keep3Dcoords)
				{
					if (hasHydrogensCheck(mol))
					{
						if (output->write(*mol))
						{
							no_written++;
						}
						else
						{
							no_ignored++;
						}

						delete mol;

						continue;
					}

					Log.level(20) << "Molecule <" << mol_name << "> is newly protonated because of missing hydrogens (non-hydrogen atoms keep their 3D coordinates)." << endl;
				}
			}
			else
			{
				rebuild_mol = true;

				Log.level(20) << "Molecule <" << mol_name << "> is rebuild because of either missing 3D coordinates, unusual charges or unusual bond lengths." << endl;
			}
		}

		// Rebuild or re-protonate and minimze molecule using OpenBabel tools

		// Note: Openbabel::OpGen3D::Do() is NOT used directly here, because it re-assigns hydrogens for a static ph of 7.4,
		// i.e. the pH can not be specified. Furthermore, it does also not remove hydrogens before using OBBuilder, resulting in hydrogens sometimes having more than one bond!
		obmol = MolecularSimilarity::createOBMol(*mol);

		ob_error = false;
		try
		{
			// Remove all hydrogens before using OBBuilder, otherwise hydrogens end up having more than one bond! (Sigh!)
			obmol->DeleteHydrogens();

			// Backup original atom coordinates
			coord_backup.clear();
			if (!rebuild_mol && keep3DcoordsProtonate)
			{
				for(OpenBabel::OBAtomIterator a_it=obmol->BeginAtoms(); a_it!=obmol->EndAtoms(); ++a_it)
				{
					coord_backup.insert(make_pair((*a_it)->GetIdx(), (*a_it)->GetVector()));
				}
			}

			// Create 3D coordinates for individual fragments using template library
			OpenBabel::OBBuilder builder;
			builder.Build(*obmol);
			obmol->SetDimension(3);

			// Set up a constraints object for OpenBabel minimization
			// It is used to set positional constraints on non-hydrogen atoms when only hydrogens should be minimized
			OpenBabel::OBFFConstraints constraints;

			// Reset original coordinates and set positional constraints on non-hydrogen atoms
			if (!rebuild_mol && keep3DcoordsProtonate)
			{
				for(OpenBabel::OBAtomIterator a_it=obmol->BeginAtoms(); a_it!=obmol->EndAtoms(); ++a_it)
				{
					(*a_it)->SetVector(coord_backup[(*a_it)->GetIdx()]);

					constraints.AddAtomConstraint((*a_it)->GetIdx());
				}
			}

			// Now add hydrogens
			obmol->AddHydrogens(false, true, pH);

			// Setup MMFF94 force-field
			setup_ok = pFF->Setup(*obmol, constraints);

			if (setup_ok)
			{
				// Optimize bond-lengths and torsions
				pFF->SteepestDescent(70, 1.0e-4); // 250, 1e-04

				// Rotate fragments around rotatable bonds
				pFF->WeightedRotorSearch(10, 5); // 200, 25

				// Optimize bond-lengths and torsions again
				pFF->ConjugateGradients(70, 1.0e-4); // 250, 1e-06
				pFF->UpdateCoordinates(*obmol);
			}
			else
			{
				Log.level(20) << "[Warning:] Openbabel force-field setup failed for molecule " << i << ". Will only use template-based approach without force-field optimization for this molecule!" << endl;
			}
		}
		catch (...)
		{
			Log.level(20) << "Error while trying to generate 3D coordinates for molecule " << i<< " ";
			if (mol->getName() != "")
			{
				Log.level(20) << "'" << mol->getName() << "'";
			}
			Log.level(20) << ". Will write unmodified input coordinates to output-file." << endl;

			delete obmol;

			ob_error = true;

			if (output->write(*mol))
			{
				no_written++;
			}
			else
			{
				no_ignored++;
			}
		}

		if (!ob_error)
		{
			// Fetch final 3D coordinates
			new_mol = MolecularSimilarity::createMolecule(*obmol);
			for (NamedPropertyIterator it=mol->beginNamedProperty(); it!=mol->endNamedProperty(); it++)
			{
				new_mol->setProperty(*it);
			}
			new_mol->setName(mol->getName());

			if (output->write(*new_mol))
			{
				no_written++;
			}
			else
			{
				no_ignored++;
			}

			delete mol;
			delete obmol;
			delete new_mol;
		}
	}

	Log.level(20) << "\r";
	if (no_ignored > 0)
	{
		Log.level(20) << "ignored " << no_ignored << " identical molecules!" << endl;
	}
	Log.level(20) << "wrote " << no_written << " molecules." << endl;

	input->close();
	output->close();

	delete input;
	delete output;

	if (parpars.has("rm"))
	{
		File::remove(parpars.get("i"));
	}
}

<commit_msg>source/APPLICATIONS/TOOLS/Ligand3DGenerator.C: Incorporated changes from Daniel to load OpenBabel's ForceField Plugin.<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/KERNEL/bond.h>
#include <BALL/KERNEL/molecule.h>
#include <BALL/KERNEL/PTE.h>
#include <BALL/KERNEL/selector.h>
#include <BALL/FORMAT/molFileFactory.h>
#include <BALL/FORMAT/dockResultFile.h>
#include <BALL/FORMAT/commandlineParser.h>
#include <BALL/STRUCTURE/molecularSimilarity.h>

#include <boost/unordered_map.hpp>

#include <openbabel/mol.h>
#include <openbabel/builder.h>
#include <openbabel/forcefield.h>
#include <openbabel/plugin.h>
#include <openbabel/obconversion.h>
#include "version.h"

using namespace BALL;
using namespace std;

// Check whether the given molecule really contains only one molecule
void checkBonds(const Atom* atom, set<const Atom*>& visited_atoms)
{
	if (visited_atoms.find(atom) != visited_atoms.end())
	{
		return;
	}

	visited_atoms.insert(atom);
	for (Atom::BondConstIterator b_it = atom->beginBond(); +b_it; b_it++)
	{
		checkBonds(b_it->getPartner(*atom), visited_atoms);
	}
}

// Check if a molecule has atoms, is single connected component and has elements defined
bool basicMoleculeCheck(Molecule* mol)
{
	// Check if it molecule has no atoms
	if (mol->countAtoms() == 0)
	{
		return false;
	}

	// Check if molecule is a contains a single fragment
	set<const Atom*> visited_atoms;
	checkBonds(&*mol->beginAtom(), visited_atoms);
	if (visited_atoms.size() != mol->countAtoms())
	{
		return false;
	}

	// Check if there are undefined elements
	for (AtomConstIterator it=mol->beginAtom(); it!=mol->endAtom(); ++it)
	{
		if (it->getElement().getName() == BALL_ELEMENT_NAME_DEFAULT)
		{
			return false;
		}
	}

	return true;
}

// Basic check if a ligand contains a hydrogen and thus can be regarded as "protonated"
bool hasHydrogensCheck(Molecule* mol)
{
	for (AtomConstIterator it = mol->beginAtom(); +it; it++)
	{
		if (it->getElement().getSymbol() == "H")
		{
			return true;
		}
	}

	return false;
}

// Check if a valid molecule is ready for docking
bool advancedMoleculeCheck(Molecule* mol)
{
	bool all_x_zero = true;
	bool all_y_zero = true;
	bool all_z_zero = true;

	for (AtomConstIterator it = mol->beginAtom(); +it; it++)
	{
		if (fabs(it->getCharge()) > 5)
		{
			return false;
		}

		for (Atom::BondConstIterator b_it = it->beginBond(); +b_it; b_it++)
		{
			if (b_it->getLength() < 0.7 || b_it->getLength() > 2.5)
			{
				return false;
			}
		}

		const TVector3<float>& pos = it->getPosition();
		if (all_x_zero)
		{
			if (fabs(pos[0]) > 0.001)
			{
				all_x_zero = false;
			}
		}
		if (all_y_zero)
		{
			if (fabs(pos[1]) > 0.001)
			{
				all_y_zero = false;
			}
		}
		if (all_z_zero)
		{
			if (fabs(pos[2]) > 0.001)
			{
				all_z_zero = false;
			}
		}
	}

	if (all_x_zero || all_y_zero || all_z_zero)
	{
		return false;
	}
	else
	{
		return true;
	}
}

int main(int argc, char* argv[])
{
	CommandlineParser parpars("Ligand3DGenerator", "generate 3D coordinates for small molecules", VERSION, String(__DATE__), "Preparation");
	parpars.registerParameter("i", "input file", INFILE, true);
	parpars.registerParameter("o", "output file", OUTFILE, true);
	parpars.registerParameter("ph", "pH-value for pH-dep. protonation", DOUBLE, false, "7.0");
	parpars.registerParameter("ff", "Forcefield to use for optimization (any available OpenBabel plugin)", STRING, false, "MMFF94");
	parpars.registerFlag("rm", "remove input file when finished");
	parpars.registerFlag("k", "keep existing 3D coordinates (flag precedes '-kp')");
	parpars.registerFlag("kp", "keep existing 3D coordinates but re-protonate compound in a pH dependent manner (flag is preceded by '-k')");
	String man = String("This tool takes input molecules and generates a single 3D conformation which is ready for docking. The input has to be a chemical file\n\
containing valid topologies and conistent bond order assignements. 2D coordinates in the input file are overwritten, 3D coordinates can be kept ('-k' or '-kp').\n\n\
  '-k':   3D coordinates are tried to be kept. Molecules with non-zero coordinates in all three dimensions are passed through without modifications. \n\
          However, if a molecule is not ready for docking (i.e. unusual bond leghts, unusual charges), the molecule will be rebuild and new \n\
          3D coordinates are assigned. If only hydrogens are missing, the coordinates of non-hydrogen atoms are kept but the molecule gets newly protonated.\n\
  '-kp':  3D coordinates are tried to be kept as for the '-k' flag but the molecule will be newly protonated.\n\n\
Please note that the main purpose of this tool is to generate valid starting conformations for docking or other optimization procedures.\n\
Therefore, the generated 3D coordinates for each fragment should be all right, but in extreme cases (i.e. very large and/or complex molecules) \n\
different fragments might still overlap with each other.\n\n\
Supported formats are ") + MolFileFactory::getSupportedFormats() + String(".");
	parpars.setToolManual(man);
	parpars.setSupportedFormats("i",MolFileFactory::getSupportedFormats());
	parpars.setSupportedFormats("o",MolFileFactory::getSupportedFormats());
	parpars.setOutputFormatSource("o","i");
	parpars.parse(argc, argv);

	// Create a dummy OBConversion object, that loads the available plugins.
	// If you know another, more elegant way to teach OpenBabel to do so
	// be my guest
	OpenBabel::OBConversion();

	GenericMolFile* input = MolFileFactory::open(parpars.get("i"), ios::in);
	GenericMolFile* output = MolFileFactory::open(parpars.get("o"), ios::out, input);
	DockResultFile* drf_output = dynamic_cast<DockResultFile*>(output);
	if (drf_output)
	{
		drf_output->setToolInfo(parpars.getStartCommand(), parpars.getStartTime());
	}

	double pH = 7.4;
	if (parpars.get("ph") != CommandlineParser::NOT_FOUND)
	{
		pH = parpars.get("ph").toDouble();
	}

	bool keep3Dcoords = false;
	if (parpars.has("k"))
	{
		keep3Dcoords = true;
	}

	bool keep3DcoordsProtonate = false;
	if (parpars.has("kp"))
	{
		keep3DcoordsProtonate = true;
	}

	std::string ff = parpars.get("ff");
	OpenBabel::OBPlugin* plugin = OpenBabel::OBPlugin::GetPlugin("forcefields", ff.c_str());

	if(!plugin)
	{
		std::vector<std::string> forcefields;
		OpenBabel::OBPlugin::ListAsVector("forcefields", ff.c_str(), forcefields);

		cerr << "[Error:] No OpenBabel plugin containing the specified force field could be found. "
		        "Available forcefields are:\n";

		for(std::vector<std::string>::iterator it = forcefields.begin(); it != forcefields.end(); ++it)
		{
			std::cerr << "\t" << *it << "\n";
		}

		cerr << "Please make sure that the plugin is installed and BABEL_LIBDIR is set accordingly."
		        "\nYo can verify this by typing \"obabel -L forcefields\"" << endl;

		return 1;
	}

	OpenBabel::OBForceField* pFF = dynamic_cast<OpenBabel::OBForceField*>(plugin);
	if (!pFF)
	{
		cerr << "[Error:] Could not convert the provided plugin to a OBForceField. This is most likely a problem with OpenBabel.\n"
		        "If you can rule this out, please report a bug on the BALL bugtracker." << std::endl;
		return 1;
	}

	String mol_name;
	bool setup_ok;
	bool ob_error;
	bool rebuild_mol;
	int no_written = 0;
	int no_ignored = 0;
	Molecule *mol, *new_mol;
	OpenBabel::OBMol *obmol;
	boost::unordered_map<unsigned int, OpenBabel::vector3> coord_backup;
	for (Size i=1; (mol = input->read()); i++)
	{
		if (no_written%5 == 0)
		{
			Log.level(20) << "\r" << no_written << " molecules";
			Log.flush();
		}

		mol_name = mol->getName();
		if (mol_name=="")
		{
			mol_name = "?";
		}

		// Check if molecule fulfills minimal validity criteria
		if (!basicMoleculeCheck(mol))
		{
			no_ignored++;

			Log.level(20) << "Error " << mol_name << " is skipped because of either containing no atoms, multiple fragments or undefined elements." << endl;

			delete mol;

			continue;
		}

		if (keep3Dcoords || keep3DcoordsProtonate)
		{
			if (advancedMoleculeCheck(mol))
			{
				rebuild_mol = false;

				if (keep3Dcoords)
				{
					if (hasHydrogensCheck(mol))
					{
						if (output->write(*mol))
						{
							no_written++;
						}
						else
						{
							no_ignored++;
						}

						delete mol;

						continue;
					}

					Log.level(20) << "Molecule <" << mol_name << "> is newly protonated because of missing hydrogens (non-hydrogen atoms keep their 3D coordinates)." << endl;
				}
			}
			else
			{
				rebuild_mol = true;

				Log.level(20) << "Molecule <" << mol_name << "> is rebuild because of either missing 3D coordinates, unusual charges or unusual bond lengths." << endl;
			}
		}

		// Rebuild or re-protonate and minimze molecule using OpenBabel tools

		// Note: Openbabel::OpGen3D::Do() is NOT used directly here, because it re-assigns hydrogens for a static ph of 7.4,
		// i.e. the pH can not be specified. Furthermore, it does also not remove hydrogens before using OBBuilder, resulting in hydrogens sometimes having more than one bond!
		obmol = MolecularSimilarity::createOBMol(*mol);

		ob_error = false;
		try
		{
			// Remove all hydrogens before using OBBuilder, otherwise hydrogens end up having more than one bond! (Sigh!)
			obmol->DeleteHydrogens();

			// Backup original atom coordinates
			coord_backup.clear();
			if (!rebuild_mol && keep3DcoordsProtonate)
			{
				for(OpenBabel::OBAtomIterator a_it=obmol->BeginAtoms(); a_it!=obmol->EndAtoms(); ++a_it)
				{
					coord_backup.insert(make_pair((*a_it)->GetIdx(), (*a_it)->GetVector()));
				}
			}

			// Create 3D coordinates for individual fragments using template library
			OpenBabel::OBBuilder builder;
			builder.Build(*obmol);
			obmol->SetDimension(3);

			// Set up a constraints object for OpenBabel minimization
			// It is used to set positional constraints on non-hydrogen atoms when only hydrogens should be minimized
			OpenBabel::OBFFConstraints constraints;

			// Reset original coordinates and set positional constraints on non-hydrogen atoms
			if (!rebuild_mol && keep3DcoordsProtonate)
			{
				for(OpenBabel::OBAtomIterator a_it=obmol->BeginAtoms(); a_it!=obmol->EndAtoms(); ++a_it)
				{
					(*a_it)->SetVector(coord_backup[(*a_it)->GetIdx()]);

					constraints.AddAtomConstraint((*a_it)->GetIdx());
				}
			}

			// Now add hydrogens
			obmol->AddHydrogens(false, true, pH);

			// Setup MMFF94 force-field
			setup_ok = pFF->Setup(*obmol, constraints);

			if (setup_ok)
			{
				// Optimize bond-lengths and torsions
				pFF->SteepestDescent(70, 1.0e-4); // 250, 1e-04

				// Rotate fragments around rotatable bonds
				pFF->WeightedRotorSearch(10, 5); // 200, 25

				// Optimize bond-lengths and torsions again
				pFF->ConjugateGradients(70, 1.0e-4); // 250, 1e-06
				pFF->UpdateCoordinates(*obmol);
			}
			else
			{
				Log.level(20) << "[Warning:] Openbabel force-field setup failed for molecule " << i << ". Will only use template-based approach without force-field optimization for this molecule!" << endl;
			}
		}
		catch (...)
		{
			Log.level(20) << "Error while trying to generate 3D coordinates for molecule " << i<< " ";
			if (mol->getName() != "")
			{
				Log.level(20) << "'" << mol->getName() << "'";
			}
			Log.level(20) << ". Will write unmodified input coordinates to output-file." << endl;

			delete obmol;

			ob_error = true;

			if (output->write(*mol))
			{
				no_written++;
			}
			else
			{
				no_ignored++;
			}
		}

		if (!ob_error)
		{
			// Fetch final 3D coordinates
			new_mol = MolecularSimilarity::createMolecule(*obmol);
			for (NamedPropertyIterator it=mol->beginNamedProperty(); it!=mol->endNamedProperty(); it++)
			{
				new_mol->setProperty(*it);
			}
			new_mol->setName(mol->getName());

			if (output->write(*new_mol))
			{
				no_written++;
			}
			else
			{
				no_ignored++;
			}

			delete mol;
			delete obmol;
			delete new_mol;
		}
	}

	Log.level(20) << "\r";
	if (no_ignored > 0)
	{
		Log.level(20) << "ignored " << no_ignored << " identical molecules!" << endl;
	}
	Log.level(20) << "wrote " << no_written << " molecules." << endl;

	input->close();
	output->close();

	delete input;
	delete output;

	if (parpars.has("rm"))
	{
		File::remove(parpars.get("i"));
	}
}

<|endoftext|>


<commit_before>
#include <cppexpose/reflection/Object.h>

#include <cassert>
#include <typeinfo>

#include <unordered_set>

#include <cppassist/string/manipulation.h>

#include <cppexpose/json/JSON.h>

namespace
{
    const char g_separator = '.';
    const std::string g_separatorString = ".";
    const std::string g_parent = "parent";
}

namespace cppexpose
{

Object::Object()
: Object("")
{
}

Object::Object(const std::string & name)
: m_className("Object")
{
    initProperty(name, nullptr);
}

Object::~Object()
{
    clear();
}

const std::string & Object::className() const
{
    return m_className;
}

void Object::setClassName(const std::string & className)
{
    m_className = className;
}

void Object::clear()
{
    // Remove properties
    // removeProperty() modifies m_properties, so don't use iterators here!
    while (!m_properties.empty())
    {
        removeProperty(m_properties.back());
    }
}

const std::unordered_map<std::string, AbstractProperty *> & Object::properties() const
{
    return m_propertiesMap;
}

bool Object::propertyExists(const std::string & name) const
{
    return m_propertiesMap.find(name) != m_propertiesMap.end();
}

AbstractProperty * Object::property(size_t index)
{
    if (index < m_properties.size()) {
        return m_properties[index];
    }

    return nullptr;
}

const AbstractProperty * Object::property(size_t index) const
{
    if (index < m_properties.size()) {
        return m_properties[index];
    }

    return nullptr;
}

AbstractProperty * Object::property(const std::string & path)
{
    std::vector<std::string> splittedPath = cppassist::string::split(path, g_separator);
    return const_cast<AbstractProperty *>(findProperty(splittedPath));
}

const AbstractProperty * Object::property(const std::string & path) const
{
    std::vector<std::string> splittedPath = cppassist::string::split(path, g_separator);
    return findProperty(splittedPath);
}

bool Object::addProperty(AbstractProperty * property)
{
    // Reject properties that have no name, or whose name already exists,
    // or that already have a parent object.
    if (!property || this->propertyExists(property->name()) || property->parent() != nullptr)
    {
        return false;
    }

    // Set parent
    property->setParent(this);

    // Invoke callback
    auto newIndex = m_properties.size();
    beforeAdd(newIndex, property);

    // Add property
    m_properties.push_back(property);
    m_propertiesMap.insert(std::make_pair(property->name(), property));

    // Invoke callback
    afterAdd(newIndex, property);

    // Success
    return true;
}

bool Object::addProperty(std::unique_ptr<AbstractProperty> && property)
{
    const auto success = addProperty(property.get());
    if (success)
    {
        m_managedProperties.push_back(std::move(property));
    }

    return success;
}

bool Object::removeProperty(AbstractProperty * property)
{
    // Reject properties that are not part of the object
    if (!property || property->parent() != this)
    {
        return false;
    }

    // Find property in object
    auto it = std::find(m_properties.begin(), m_properties.end(), property);
    if (it == m_properties.end())
    {
        return false;
    }

    // Get property index
    size_t index = std::distance(m_properties.begin(), it);

    // Invoke callback
    beforeRemove(index, property);

    // Remove property from object
    m_properties.erase(it);
    m_propertiesMap.erase(property->name());

    // Reset property parent
    property->setParent(nullptr);

    // Invoke callback
    afterRemove(index, property);

    // Remove from managed list (deletes the property)
    auto it2 = std::find_if(m_managedProperties.begin(), m_managedProperties.end(), [property](const std::unique_ptr<AbstractProperty> & managedProperty) { return managedProperty.get() == property; });
    if (it2 != m_managedProperties.end())
    {
        m_managedProperties.erase(it2);
    }

    // Success
    return true;
}

const std::vector<Method> & Object::functions() const
{
    return m_functions;
}

bool Object::isObject() const
{
    return true;
}

std::unique_ptr<AbstractTyped> Object::clone() const
{
    // [TODO]
    return cppassist::make_unique<Object>(name());
}

const std::type_info & Object::type() const
{
    return typeid(Object);
}

std::string Object::typeName() const
{
    return "Object";
}

bool Object::isReadOnly() const
{
    return false;
}

bool Object::isComposite() const
{
    return true;
}

size_t Object::numSubValues() const
{
    return m_properties.size();
}

AbstractTyped * Object::subValue(size_t index)
{
    if (index < m_properties.size()) {
        return m_properties[index];
    }

    return nullptr;
}

bool Object::isEnum() const
{
    return false;
}

bool Object::isArray() const
{
    return false;
}

bool Object::isVariant() const
{
    return false;
}

bool Object::isString() const
{
    return false;
}

bool Object::isBool() const
{
    return false;
}

bool Object::isNumber() const
{
    return false;
}

bool Object::isIntegral() const
{
    return false;
}

bool Object::isSignedIntegral() const
{
    return false;
}

bool Object::isUnsignedIntegral() const
{
    return false;
}

bool Object::isFloatingPoint() const
{
    return false;
}

Variant Object::toVariant() const
{
    // Create variant map from all properties in the object
    Variant map = Variant::map();
    for (const auto & it : m_propertiesMap) {
        // Get name and property
        const std::string & name = it.first;
        AbstractProperty *  prop = it.second;

        // Add to variant map
        (*map.asMap())[name] = prop->toVariant();
    }

    // Return variant representation
    return map;
}

bool Object::fromVariant(const Variant & value)
{
    // Check if variant is a map
    if (!value.isVariantMap()) {
        return false;
    }

    // Get all values from variant map
    for (const auto & it : *value.asMap()) {
        // Get name and value
        const std::string & name = it.first;
        const Variant &     var  = it.second;

        // If this names an existing property, set its value
        AbstractProperty * prop = this->property(name);
        if (prop) {
            prop->fromVariant(var);
        }
    }

    // Done
    return true;
}

std::string Object::toString() const
{
    // Convert object into JSON
    return JSON::stringify(this->toVariant());
}

bool Object::fromString(const std::string & str)
{
    // Convert from JSON
    Variant values;
    if (JSON::parse(values, str)) {
        return fromVariant(values);
    }

    // Error
    return false;
}

bool Object::toBool() const
{
    return false;
}

bool Object::fromBool(bool)
{
    return false;
}

long long Object::toLongLong() const
{
    return 0ll;
}

bool Object::fromLongLong(long long)
{
    return false;
}

unsigned long long Object::toULongLong() const
{
    return 0ull;
}

bool Object::fromULongLong(unsigned long long)
{
    return false;
}

double Object::toDouble() const
{
    return 0.0;
}

bool Object::fromDouble(double)
{
    return false;
}

std::string Object::relativePathTo(const Object * const other) const
{
    // Return "." if the objects are the same
    if (this == other) {
        return g_separatorString;
    }

    // Find all ancestors of "this"
    std::unordered_set<const Object*> ancestors;

    const Object * curObject = this;
    while (curObject)
    {
        ancestors.insert(curObject);
        curObject = curObject->parent();
    }

    // Find the common parent from "other"
    std::vector<std::string> otherPath;
    const Object * commonParent = nullptr;

    curObject = other;
    while (curObject)
    {
        if (ancestors.count(curObject))
        {
            commonParent = curObject;
            break;
        }

        otherPath.push_back(curObject->name());
        curObject = curObject->parent();
    }

    // Abort if no common parent has been found
    if (!commonParent) {
        return "";
    }

    // Count number of steps from this to the common parent
    curObject = this;
    size_t numParents = 0;
    while (curObject != commonParent)
    {
        numParents++;
        curObject = curObject->parent();
    }

    // Compose string
    std::string relativePath = "";

    for (size_t i = 0; i < numParents; i++)
    {
        relativePath += (i == 0) ? "parent" : ".parent";
    }

    for (size_t i = 0; i < otherPath.size(); i++)
    {
        relativePath += "." + otherPath[otherPath.size() - 1 - i];
    }

    return relativePath;
}

const AbstractProperty * Object::findProperty(const std::vector<std::string> & path) const
{
    // Find property
    const AbstractProperty * property = this;

    auto current = path.begin();
    const auto end = path.end();

    while (current != end)
    {
        // Get property name (first part of the path)
        const std::string & name = *current;

        if (name == g_parent)
        {
            // Parent property
            property = property->m_parent;
        }
        else
        {
            // Sub-property
            auto object = static_cast<const Object *>(property);
            const auto it = object->m_propertiesMap.find(name);

            if (it != object->m_propertiesMap.end())
            {
                property = it->second;
            }
            else
            {
                property = nullptr;
            }
        }

        // Check if property exists
        if (!property) {
            return nullptr;
        }

        // Compute next path segment
        ++current;

        // If there are no more sub-paths, return the found property
        if (current == end) {
            return property;
        }

        // Otherwise, it is an element in the middle of the path, so ensure it is an object
        if (!property->isObject()) {
            return nullptr;
        }
    }

    return nullptr;
}

} // namespace cppexpose
<commit_msg>Explicit string::split parameters<commit_after>
#include <cppexpose/reflection/Object.h>

#include <cassert>
#include <typeinfo>

#include <unordered_set>

#include <cppassist/string/manipulation.h>

#include <cppexpose/json/JSON.h>

namespace
{
    const char g_separator = '.';
    const std::string g_separatorString = ".";
    const std::string g_parent = "parent";
}

namespace cppexpose
{

Object::Object()
: Object("")
{
}

Object::Object(const std::string & name)
: m_className("Object")
{
    initProperty(name, nullptr);
}

Object::~Object()
{
    clear();
}

const std::string & Object::className() const
{
    return m_className;
}

void Object::setClassName(const std::string & className)
{
    m_className = className;
}

void Object::clear()
{
    // Remove properties
    // removeProperty() modifies m_properties, so don't use iterators here!
    while (!m_properties.empty())
    {
        removeProperty(m_properties.back());
    }
}

const std::unordered_map<std::string, AbstractProperty *> & Object::properties() const
{
    return m_propertiesMap;
}

bool Object::propertyExists(const std::string & name) const
{
    return m_propertiesMap.find(name) != m_propertiesMap.end();
}

AbstractProperty * Object::property(size_t index)
{
    if (index < m_properties.size()) {
        return m_properties[index];
    }

    return nullptr;
}

const AbstractProperty * Object::property(size_t index) const
{
    if (index < m_properties.size()) {
        return m_properties[index];
    }

    return nullptr;
}

AbstractProperty * Object::property(const std::string & path)
{
    std::vector<std::string> splittedPath = cppassist::string::split(path, g_separator, true);
    return const_cast<AbstractProperty *>(findProperty(splittedPath));
}

const AbstractProperty * Object::property(const std::string & path) const
{
    std::vector<std::string> splittedPath = cppassist::string::split(path, g_separator, true);
    return findProperty(splittedPath);
}

bool Object::addProperty(AbstractProperty * property)
{
    // Reject properties that have no name, or whose name already exists,
    // or that already have a parent object.
    if (!property || this->propertyExists(property->name()) || property->parent() != nullptr)
    {
        return false;
    }

    // Set parent
    property->setParent(this);

    // Invoke callback
    auto newIndex = m_properties.size();
    beforeAdd(newIndex, property);

    // Add property
    m_properties.push_back(property);
    m_propertiesMap.insert(std::make_pair(property->name(), property));

    // Invoke callback
    afterAdd(newIndex, property);

    // Success
    return true;
}

bool Object::addProperty(std::unique_ptr<AbstractProperty> && property)
{
    const auto success = addProperty(property.get());
    if (success)
    {
        m_managedProperties.push_back(std::move(property));
    }

    return success;
}

bool Object::removeProperty(AbstractProperty * property)
{
    // Reject properties that are not part of the object
    if (!property || property->parent() != this)
    {
        return false;
    }

    // Find property in object
    auto it = std::find(m_properties.begin(), m_properties.end(), property);
    if (it == m_properties.end())
    {
        return false;
    }

    // Get property index
    size_t index = std::distance(m_properties.begin(), it);

    // Invoke callback
    beforeRemove(index, property);

    // Remove property from object
    m_properties.erase(it);
    m_propertiesMap.erase(property->name());

    // Reset property parent
    property->setParent(nullptr);

    // Invoke callback
    afterRemove(index, property);

    // Remove from managed list (deletes the property)
    auto it2 = std::find_if(m_managedProperties.begin(), m_managedProperties.end(), [property](const std::unique_ptr<AbstractProperty> & managedProperty) { return managedProperty.get() == property; });
    if (it2 != m_managedProperties.end())
    {
        m_managedProperties.erase(it2);
    }

    // Success
    return true;
}

const std::vector<Method> & Object::functions() const
{
    return m_functions;
}

bool Object::isObject() const
{
    return true;
}

std::unique_ptr<AbstractTyped> Object::clone() const
{
    // [TODO]
    return cppassist::make_unique<Object>(name());
}

const std::type_info & Object::type() const
{
    return typeid(Object);
}

std::string Object::typeName() const
{
    return "Object";
}

bool Object::isReadOnly() const
{
    return false;
}

bool Object::isComposite() const
{
    return true;
}

size_t Object::numSubValues() const
{
    return m_properties.size();
}

AbstractTyped * Object::subValue(size_t index)
{
    if (index < m_properties.size()) {
        return m_properties[index];
    }

    return nullptr;
}

bool Object::isEnum() const
{
    return false;
}

bool Object::isArray() const
{
    return false;
}

bool Object::isVariant() const
{
    return false;
}

bool Object::isString() const
{
    return false;
}

bool Object::isBool() const
{
    return false;
}

bool Object::isNumber() const
{
    return false;
}

bool Object::isIntegral() const
{
    return false;
}

bool Object::isSignedIntegral() const
{
    return false;
}

bool Object::isUnsignedIntegral() const
{
    return false;
}

bool Object::isFloatingPoint() const
{
    return false;
}

Variant Object::toVariant() const
{
    // Create variant map from all properties in the object
    Variant map = Variant::map();
    for (const auto & it : m_propertiesMap) {
        // Get name and property
        const std::string & name = it.first;
        AbstractProperty *  prop = it.second;

        // Add to variant map
        (*map.asMap())[name] = prop->toVariant();
    }

    // Return variant representation
    return map;
}

bool Object::fromVariant(const Variant & value)
{
    // Check if variant is a map
    if (!value.isVariantMap()) {
        return false;
    }

    // Get all values from variant map
    for (const auto & it : *value.asMap()) {
        // Get name and value
        const std::string & name = it.first;
        const Variant &     var  = it.second;

        // If this names an existing property, set its value
        AbstractProperty * prop = this->property(name);
        if (prop) {
            prop->fromVariant(var);
        }
    }

    // Done
    return true;
}

std::string Object::toString() const
{
    // Convert object into JSON
    return JSON::stringify(this->toVariant());
}

bool Object::fromString(const std::string & str)
{
    // Convert from JSON
    Variant values;
    if (JSON::parse(values, str)) {
        return fromVariant(values);
    }

    // Error
    return false;
}

bool Object::toBool() const
{
    return false;
}

bool Object::fromBool(bool)
{
    return false;
}

long long Object::toLongLong() const
{
    return 0ll;
}

bool Object::fromLongLong(long long)
{
    return false;
}

unsigned long long Object::toULongLong() const
{
    return 0ull;
}

bool Object::fromULongLong(unsigned long long)
{
    return false;
}

double Object::toDouble() const
{
    return 0.0;
}

bool Object::fromDouble(double)
{
    return false;
}

std::string Object::relativePathTo(const Object * const other) const
{
    // Return "." if the objects are the same
    if (this == other) {
        return g_separatorString;
    }

    // Find all ancestors of "this"
    std::unordered_set<const Object*> ancestors;

    const Object * curObject = this;
    while (curObject)
    {
        ancestors.insert(curObject);
        curObject = curObject->parent();
    }

    // Find the common parent from "other"
    std::vector<std::string> otherPath;
    const Object * commonParent = nullptr;

    curObject = other;
    while (curObject)
    {
        if (ancestors.count(curObject))
        {
            commonParent = curObject;
            break;
        }

        otherPath.push_back(curObject->name());
        curObject = curObject->parent();
    }

    // Abort if no common parent has been found
    if (!commonParent) {
        return "";
    }

    // Count number of steps from this to the common parent
    curObject = this;
    size_t numParents = 0;
    while (curObject != commonParent)
    {
        numParents++;
        curObject = curObject->parent();
    }

    // Compose string
    std::string relativePath = "";

    for (size_t i = 0; i < numParents; i++)
    {
        relativePath += (i == 0) ? "parent" : ".parent";
    }

    for (size_t i = 0; i < otherPath.size(); i++)
    {
        relativePath += "." + otherPath[otherPath.size() - 1 - i];
    }

    return relativePath;
}

const AbstractProperty * Object::findProperty(const std::vector<std::string> & path) const
{
    // Find property
    const AbstractProperty * property = this;

    auto current = path.begin();
    const auto end = path.end();

    while (current != end)
    {
        // Get property name (first part of the path)
        const std::string & name = *current;

        if (name == g_parent)
        {
            // Parent property
            property = property->m_parent;
        }
        else
        {
            // Sub-property
            auto object = static_cast<const Object *>(property);
            const auto it = object->m_propertiesMap.find(name);

            if (it != object->m_propertiesMap.end())
            {
                property = it->second;
            }
            else
            {
                property = nullptr;
            }
        }

        // Check if property exists
        if (!property) {
            return nullptr;
        }

        // Compute next path segment
        ++current;

        // If there are no more sub-paths, return the found property
        if (current == end) {
            return property;
        }

        // Otherwise, it is an element in the middle of the path, so ensure it is an object
        if (!property->isObject()) {
            return nullptr;
        }
    }

    return nullptr;
}

} // namespace cppexpose
<|endoftext|>


<commit_before>/****************************************************************************/
/* Copyright 2005-2006, Francis Russell                                     */
/*                                                                          */
/* 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.                                           */
/*                                                                          */
/****************************************************************************/

#ifndef DESOLIN_PROFILING_HASHING_VISITOR_HPP
#define DESOLIN_PROFILING_HASHING_VISITOR_HPP

#include "Desolin_profiling_fwd.hpp"
#include <cstddef>
#include <typeinfo>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <cassert>
#include <boost/functional/hash.hpp>

namespace desolin
{

namespace detail
{

template<typename T_element>
class PHashingVisitor : public PExpressionNodeVisitor<T_element>
{
private:
  const std::map<const PExpressionNode<T_element>*, int> nodeNumberings;
  std::size_t hash;

  template<typename exprType>
  inline std::size_t hashExprNode(const PExprNode<exprType, T_element>& node) const
  {
    const char* nodeTypeString = typeid(node).name();
    return boost::hash_range(nodeTypeString, nodeTypeString+strlen(nodeTypeString));
  }

  template<typename resultType, typename exprType>
  std::size_t hashUnOp(const PUnOp<resultType, exprType, T_element>& unop) const
  {
    std::size_t seed = hashExprNode(unop);
    const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator operand = nodeNumberings.find(&unop.getOperand());
    assert(operand != nodeNumberings.end());
    boost::hash_combine(seed, operand->second);
    return seed;
  }

  template<typename resultType, typename leftType, typename rightType>
  std::size_t hashBinOp(const PBinOp<resultType, leftType, rightType, T_element>& binop) const
  {
    std::size_t seed = hashExprNode(binop);
    const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator left = nodeNumberings.find(&binop.getLeft());
    const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator right = nodeNumberings.find(&binop.getRight());
    assert(left != nodeNumberings.end());
    assert(right != nodeNumberings.end());
    boost::hash_combine(seed, left->second);
    boost::hash_combine(seed, right->second);
    return seed;
  }

  template<typename exprType>
  std::size_t hashElementSet(const PElementSet<exprType, T_element>& node) const
  {
    std::size_t seed = hashUnOp(node);
    const std::vector<const PExprNode<scalar, T_element>*> assignments(node.getAssignments());
    typedef typename std::vector<const PExprNode<scalar, T_element>*>::const_iterator ConstIterator;

    for(ConstIterator assignment = assignments.begin(); assignment!=assignments.end(); ++assignment)
    {
      const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator numbering = nodeNumberings.find(*assignment);
      assert(numbering != nodeNumberings.end());
      boost::hash_combine(seed, numbering->second);
    }
    return seed;
  }

  template<typename exprType>
  std::size_t hashPairwise(const PPairwise<exprType, T_element>& node) const
  {
    std::size_t seed = hashBinOp(node);
    boost::hash_combine(seed, node.getOperation());
    return seed;
  }

  template<typename exprType>
  std::size_t hashScalarPiecewise(const PScalarPiecewise<exprType, T_element>& node) const
  {
    std::size_t seed = hashBinOp(node);
    boost::hash_combine(seed, node.getOperation());
    return seed;
  }

public:

  PHashingVisitor(const std::map<const PExpressionNode<T_element>*, int>& numberings) : nodeNumberings(numberings)
  {
  }

  inline std::size_t getHash() const
  {
    return hash;
  }

  virtual void visit(PElementGet<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PElementGet<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PElementSet<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashElementSet(e));
  }

  virtual void visit(PElementSet<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashElementSet(e));
  }

  virtual void visit(PLiteral<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashExprNode(e));
  }

  virtual void visit(PLiteral<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashExprNode(e));
  }

  virtual void visit(PLiteral<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashExprNode(e));
  }

  virtual void visit(PMatrixMult<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PMatrixVectorMult<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PTransposeMatrixVectorMult<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PVectorDot<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PVectorCross<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PVectorTwoNorm<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PMatrixTranspose<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PPairwise<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PPairwise<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PPairwise<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PScalarPiecewise<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PScalarPiecewise<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PScalarPiecewise<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PNegate<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PNegate<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PNegate<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PAbsolute<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PSquareRoot<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }
};

}

}

#endif
<commit_msg>Fix profiling hashing visitor.<commit_after>/****************************************************************************/
/* Copyright 2005-2006, Francis Russell                                     */
/*                                                                          */
/* 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.                                           */
/*                                                                          */
/****************************************************************************/

#ifndef DESOLIN_PROFILING_HASHING_VISITOR_HPP
#define DESOLIN_PROFILING_HASHING_VISITOR_HPP

#include "Desolin_profiling_fwd.hpp"
#include <cstddef>
#include <typeinfo>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <cassert>
#include <boost/functional/hash.hpp>

namespace desolin
{

namespace detail
{

template<typename T_element>
class PHashingVisitor : public PExpressionNodeVisitor<T_element>
{
private:
  const std::map<const PExpressionNode<T_element>*, int> nodeNumberings;
  std::size_t hash;

  template<typename exprType>
  inline std::size_t hashExprNode(const PExprNode<exprType, T_element>& node) const
  {
    const char* nodeTypeString = typeid(node).name();
    return boost::hash_range(nodeTypeString, nodeTypeString+strlen(nodeTypeString));
  }

  template<typename resultType, typename exprType>
  std::size_t hashUnOp(const PUnOp<resultType, exprType, T_element>& unop) const
  {
    std::size_t seed = hashExprNode(unop);
    const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator operand = nodeNumberings.find(&unop.getOperand());
    assert(operand != nodeNumberings.end());
    boost::hash_combine(seed, operand->second);
    return seed;
  }

  template<typename resultType, typename leftType, typename rightType>
  std::size_t hashBinOp(const PBinOp<resultType, leftType, rightType, T_element>& binop) const
  {
    std::size_t seed = hashExprNode(binop);
    const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator left = nodeNumberings.find(&binop.getLeft());
    const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator right = nodeNumberings.find(&binop.getRight());
    assert(left != nodeNumberings.end());
    assert(right != nodeNumberings.end());
    boost::hash_combine(seed, left->second);
    boost::hash_combine(seed, right->second);
    return seed;
  }

  template<typename exprType>
  std::size_t hashElementSet(const PElementSet<exprType, T_element>& node) const
  {
    std::size_t seed = hashUnOp(node);
    const std::vector<const PExprNode<scalar, T_element>*> assignments(node.getAssignments());
    typedef typename std::vector<const PExprNode<scalar, T_element>*>::const_iterator ConstIterator;

    for(ConstIterator assignment = assignments.begin(); assignment!=assignments.end(); ++assignment)
    {
      const typename std::map<const PExpressionNode<T_element>*, int>::const_iterator numbering = nodeNumberings.find(*assignment);
      assert(numbering != nodeNumberings.end());
      boost::hash_combine(seed, numbering->second);
    }
    return seed;
  }

  template<typename exprType>
  std::size_t hashPairwise(const PPairwise<exprType, T_element>& node) const
  {
    std::size_t seed = hashBinOp(node);
    boost::hash_combine(seed, node.getOperation());
    return seed;
  }

  template<typename exprType>
  std::size_t hashScalarPiecewise(const PScalarPiecewise<exprType, T_element>& node) const
  {
    std::size_t seed = hashBinOp(node);
    boost::hash_combine(seed, node.getOperation());
    return seed;
  }

public:

  PHashingVisitor(const std::map<const PExpressionNode<T_element>*, int>& numberings) : nodeNumberings(numberings), hash(0)
  {
  }

  inline std::size_t getHash() const
  {
    return hash;
  }

  virtual void visit(PElementGet<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PElementGet<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PElementSet<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashElementSet(e));
  }

  virtual void visit(PElementSet<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashElementSet(e));
  }

  virtual void visit(PLiteral<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashExprNode(e));
  }

  virtual void visit(PLiteral<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashExprNode(e));
  }

  virtual void visit(PLiteral<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashExprNode(e));
  }

  virtual void visit(PMatrixMult<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PMatrixVectorMult<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PTransposeMatrixVectorMult<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PVectorDot<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PVectorCross<T_element>& e)
  {
    boost::hash_combine(hash, hashBinOp(e));
  }

  virtual void visit(PVectorTwoNorm<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PMatrixTranspose<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PPairwise<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashPairwise(e));
  }

  virtual void visit(PPairwise<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashPairwise(e));
  }

  virtual void visit(PPairwise<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashPairwise(e));
  }

  virtual void visit(PScalarPiecewise<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashScalarPiecewise(e));
  }

  virtual void visit(PScalarPiecewise<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashScalarPiecewise(e));
  }

  virtual void visit(PScalarPiecewise<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashScalarPiecewise(e));
  }

  virtual void visit(PNegate<scalar, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PNegate<vector, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PNegate<matrix, T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PAbsolute<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }

  virtual void visit(PSquareRoot<T_element>& e)
  {
    boost::hash_combine(hash, hashUnOp(e));
  }
};

}

}

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

namespace dll {

/*!
 * \brief A descriptor for an activation layer.
 *
 * Such a layer only applies an activation function to its inputs
 * and has no weights.
 */
template <typename... Parameters>
struct activation_layer_desc {
    /*!
     * A list of all the parameters of the descriptor
     */
    using parameters = cpp::type_list<Parameters...>;

    /*!
     * \brief The layer's activation function
     */
    static constexpr function activation_function = detail::get_value<activation<function::SIGMOID>, Parameters...>::value;

    /*!
     * The layer type
     */
    using layer_t = activation_layer<activation_layer_desc<Parameters...>>;

    /*!
     * The dynamic layer type
     */
    using dyn_layer_t = activation_layer<activation_layer_desc<Parameters...>>;

    //Make sure only valid types are passed to the configuration list
    static_assert(
        detail::is_valid<cpp::type_list<activation_id>, Parameters...>::value,
        "Invalid parameters type for activation_layer_desc");
};

} //end of dll namespace
<commit_msg>Simplify activation layer descriptors<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

namespace dll {

/*!
 * \brief A descriptor for an activation layer.
 *
 * Such a layer only applies an activation function to its inputs
 * and has no weights.
 */
template <dll::function F = dll::function::SIGMOID>
struct activation_layer_desc {
    /*!
     * \brief The layer's activation function
     */
    static constexpr function activation_function = F;

    /*!
     * The layer type
     */
    using layer_t = activation_layer<activation_layer_desc<F>>;

    /*!
     * The dynamic layer type
     */
    using dyn_layer_t = activation_layer<activation_layer_desc<F>>;
};

} //end of dll namespace
<|endoftext|>