<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Hi David,</div><div class=""><br class=""></div><div class="">Sorry about the radio silence yesterday. Bob and I have a guest in the office this week (Mike Jackson from BlueQuartz); I will try to be better about breaking away to answer email. </div><div class=""><br class=""></div><div class="">We could definitely subclass Metadata, but I don’t see why we need to. Currently, the create(), read() and write() functors are public fields that can be reassigned (once operators are more decoupled from smtk::model, they should become operators); as such, I don’t see any benefit to subclassing. </div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">as we change the model manager into a resource, it goes from being a single instance with potentially multiple sessions to multiple instances, each with a single session.</blockquote><br class=""></div><div class="">For the model system (and each of its derived bridges), something needs to be "the resource” that is unique to the bridge and is serializable. If the manager becomes the resource, that’s fine; it could then be given the responsibility of session management for its particular set of models. If the model itself becomes the resource (as Bob mentioned as an option last week), that’s fine too. Having a model as the top-level thing that can be written/read to/from disk makes sense to me, and operators would be able to access session-specific routines through the models associated with them. It would also be nice if a set of operators specific to a given session could be identified by their input or output type, obviating the need for an additional operator management system (instead, we could simply filter by input/output type to get all operators appropriate for a given model/component).</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">One variation of the below would be to make subclasses of Metadata templated on their resource type... then at least the create() member of Metadata could be implemented as "return T::create()->setId(uid);". If we add methods to Resource to return read/write (/import/export?) methods, then Metadata could be entirely templated.</blockquote><br class=""></div><div class="">I do love templates :) I think that, if we stick to the idea of our functors converting to operators, then we may not need that level of specialization though. I think that it’s probably better if we require the writer of a session to explicitly define what the create()/read()/write() methods are, rather than providing an implicit default. </div><div class=""><br class=""></div><div class="">Sincerely,</div><div class="">T.J.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">
<div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Thomas J. Corona, Ph.D.<br class="">Kitware, Inc.<br class="">Senior R&D Engineer<br class="">21 Corporate Drive<br class="">Clifton Park, NY 12065-8662<br class="">Phone: 518-881-4443</div></div>

</div>
<div><br class=""><blockquote type="cite" class=""><div class="">On Nov 13, 2017, at 1:20 PM, David Thompson <<a href="mailto:david.thompson@kitware.com" class="">david.thompson@kitware.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi TJ et al.,<br class=""><br class="">I wanted to follow up a little on the discussion we had last week about resources. As I understand it, we are now talking about having the model manager (renamed to Resource?) and each subclass (call them smtk::bridge::xxx::Resource) register themselves like so:<br class=""><br class="">    smtk::resource::Manager::registerResource(<br class="">      new smtk::resource::Metadata("xxx", type_id(smtk::bridge::xxx::Resource));<br class=""><br class="">somewhere in their static initializer.<br class=""><br class="">If so, it seems to make sense to do some combination of<br class=""><br class="">1. Subclass metadata for smtk::model as shown below so that the inherited setup() method can fill out the create/read/write members; and/or<br class="">2. Change the create/read/write methods in the metadata to point to operators (but which ones?).<br class=""><br class="">The subclass below shows some of the questions that pop up. Note in particular that as we change the model manager into a resource, it goes from being a single instance with potentially multiple sessions to multiple instances, each with a single session.<br class=""><br class="">That seems to indicate that the smtk;:model::Session and SessionRegistrar classes should change a little. A session should not ask for its (sole) model manager, but rather a model resource should ask for its sole session. It would be easy for the SessionRegistrar to find an existing session or create one as required.<br class=""><br class="">Is this what you had in mind? One variation of the below would be to make subclasses of Metadata templated on their resource type... then at least the create() member of Metadata could be implemented as "return T::create()->setId(uid);". If we add methods to Resource to return read/write (/import/export?) methods, then Metadata could be entirely templated.<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">      </span>David<br class=""><br class="">#ifndef smtk_model_Metadata_h<br class="">#define smtk_model_Metadata_h<br class=""><br class="">#include "smtk/model/Manaager.h"<br class=""><br class="">#include "smtk/resource/Metadata.h"<br class=""><br class="">namespace smtk<br class="">{<br class="">namespace model<br class="">{<br class=""><br class="">class Metadata : public smtk::resource::Metadata<br class="">{<br class="">  typedef smtk::resource::Metadata Superclass;<br class="">public:<br class="">  Metadata()<br class="">  : Superclass("model", typeid(smtk::model::Manager))<br class="">  {<br class="">    this->setup();<br class="">  }<br class=""><br class="">  void setup()<br class="">  {<br class="">    this->create = [](const smtk::common::UUID& uid)<br class="">    {<br class="">      auto rsrc = smtk::model::Manager::create();<br class="">      rsrc->setId(uid);<br class="">      return rsrc;<br class="">    };<br class="">    this->read = [](const std::string& url)<br class="">    {<br class="">      // Find a session of the proper type<br class="">      auto sess = smtk::model::SessionRegistrar::createSession(m_uniqueName);<br class="">      if (sess)<br class="">      {<br class="">        // Order is important here: the session should be registered to the<br class="">        // model resource before running operations. However, note that this<br class="">        // causes a chicken and egg problem because the reader should obtain<br class="">        // a UUID for the model resource. Assume the reader will modify its<br class="">        // resource's UUID? Only on load and not import?<br class="">        auto rsrc = smtk::model::Manager::create();<br class="">        rsrc->registerSession(sess);<br class="">        auto rdr = sess->op("load smtk model");<br class="">        if (rdr)<br class="">        {<br class="">          rdr->findFile("filename")->setValue(0, url);<br class="">          auto res = rdr->operate();<br class="">          // Success returns the shared pointer, keeping the model resource alive.<br class="">          // Failure discards the model resource.<br class="">          if (res->findInteger("outcome")->value() == smtk::operation::OPERATION_SUCCEEDED)<br class="">          {<br class="">            return rsrc;<br class="">          }<br class="">        }<br class="">      }<br class="">      return nullptr;<br class="">    };<br class="">    this->write = [](const ResourcePtr& rawRsrc)<br class="">    {<br class="">      auto rsrc = dynamic_pointer_cast<smtk::model::Resource>(rawRsrc);<br class="">      if (!rsrc)<br class="">      {<br class="">        return false;<br class="">      }<br class="">      auto wri = rsrc->session()->op("save smtk model");<br class="">      if (wri)<br class="">      {<br class="">        // This will require changes to the "save smtk model" operator.<br class="">        // Should we associate all the models in the resource?<br class="">        // Should we have an attribute::ResourceItem just like we have<br class="">        // attribute::ComponentItem so that an entire resource can be<br class="">        // associated to an attribute? We could also abuse ComponentItem<br class="">        // a little bit... if we have a way to create a Component with a<br class="">        // null UUID but a valid parent resource, it could be interpreted<br class="">        // as "the component that is the set of all components in the<br class="">        // resource," making it a stand-in for the entire resource.<br class="">        wri->associatedComponents()->setValue(0, xxx); // Associate all models in rsrc?<br class="">        wri->findFile("filename")->setValue(0, rsrc->location());<br class="">        auto res = wri->operate();<br class="">        return res->findInteger("outcome")->value() == smtk::operation::OPERATION_SUCCEEDED;<br class="">      }<br class="">      return false;<br class="">    }<br class="">  }<br class="">};<br class=""><br class="">}<br class="">}<br class=""><br class=""></div></div></blockquote></div><br class=""></body></html>