Topics

What should ProvidingManager.provide() return if not supported?


Bob Jacobsen
 

I don’t know of anything that would break.

Formally, it might be good to go through a deprecation cycle. But the problem is that, if we want to end up with the AbstractProxyManager and AbstractProvidingProxyManager names, in the meantime your code is a bit of a mess (because the problem is that ProvidingManager is implemented too high)

To do this:

- Create the classes as described earlier.

- In AbstractProxyManager, leave the ProvidingManager method in place and marked as deprecated; have it show a runtime deprecated warning (Log4JUtil.deprecationWarning)
- Have your implementation throw UnsupportedOperationException for provide(..); mark it as @Override

Eventually, the ProvidingManager provide can be removed from AbstractProxyManager, which will remind you to remove it from your classes via the @Override

But I don’t think it’s really necessary.

Bob

On Jan 5, 2020, at 8:11 AM, danielb987 <db123@...> wrote:

Can I change AbstractProxyManager to not be a ProvidingManager without breaking anything? If so, I will be happy to do that. I was afraid that since AbstractProxyManager is public, I couldn't do that. But maybe it's no problem for classes in the jmri.managers package?
--
Bob Jacobsen
@BobJacobsen


danielb987
 

Bob

I sent my mail before I got yours.

Can I change AbstractProxyManager to not be a ProvidingManager without breaking anything? If so, I will be happy to do that. I was afraid that since AbstractProxyManager is public, I couldn't do that. But maybe it's no problem for classes in the jmri.managers package?

Daniel

2020-01-05 16:49 skrev Bob Jacobsen:

By far the most useful approach is to have system name completely
describe how to access the hardware device. A system name where the
suffix can be parsed out to give enough information to create the
object is just easier to manage from e.g. scripts and file loading.
Examples are C/MRI Light/Turnout/Switch (LTS) which have the node and
pin encoded in the address; the Power Line connection which specifies
house code and device code, and Grapevine which encodes all sorts of
things in its names.
https://www.jmri.org/help/en/html/hardware/cmri/CMRI.shtml
https://www.jmri.org/help/en/html/hardware/powerline/Names.shtml
https://www.jmri.org/help/en/html/hardware/grapevine/Names.shtml
That’s not the complete configuration, of course. Things like
feedback sensors still need to be directly configured. But it’s
enough to _create_ the object so that it can be retained, even if that
configuration will be happening later.
But in the alternative that for some reason this can’t be done, you
can always reimplement a different ProxyServer that doesn’t also
implement ProvidingManager. A clean way to do this would be to create
a new AbstractProvidingProxyManager that is a subclass of
AbstractProxyManager, move all the existing subclasses to that, and
then have AbstractProxyManager provide everything _except_ the
ProvidingManager implementation. That way we end up with
AbstractProxyManager being a minimal implementation of ProxyManager
hence Manager, and the AbstractProvidingProxyManager still providing
the super classes for everything that’s there now.
Bob

On Jan 5, 2020, at 5:56 AM, danielb987 <db123@...> wrote:
I'm implementing managers for AnalogIO and StringIO. I'm going to add a generic ProxyManager and a specific LocoNet manager for these.
AbstractProxyManager implements ProvidingManager, so I must add the method provide() in the ProxyManager. But I cannot create an AnalogIO or a StringIO from only a system name, so this method should always fail, at least for the LocoNet manager. What is the proper way to handle this? Throw an IllegalArgumentException("not supported") or throw an UnsupportedOperationException("not supported") ?
Daniel
--
Bob Jacobsen
@BobJacobsen


danielb987
 

2020-01-05 16:29 skrev Randall Wood via Groups.Io:
Also, by your design, it seems I could have two different NamedBeans
that attempt to write (and I assume read) two different types of data
(say 8 bit integer vs float or 16 bit integer vs variable length
string) from the same device/SV. That suggests you should have a
NamedBean for an IO device, not for an IO device by type of data
handled.
Both AnalogIO and StringIO are NamedBeans. So they should have different type letters.

For me, the important part is to implement managers for AnalogIO and StringIO. I choose LocoNet, since that's what I'm used to and have to work with. But it could be JSON, C/MRI or anything else instead. I just want some reference implementation to let people use AnalogIO and StringIO in real life.

It seems that the easiest way forward is to let AnalogIO_Manager and StringIO_Manager implement ProxyManager and not extend AbstractProxyManager. And I think the best way to do that is to add a AbstractNonProvidingProxyManager that is parent to AbstractProxyManager.


abstract public class AbstractNonProvidingProxyManager<E extends NamedBean> implements ProxyManager<E>, Manager.ManagerDataListener<E>


abstract public class AbstractProxyManager<E extends NamedBean> extends AbstractNonProvidingProxyManager<E> implements ProvidingManager<E>


AbstractNonProvidingProxyManager is a proxy manager that doesn't provide named beans.

AbstractProxyManager is a proxy manager that provides named beans.

Daniel


Bob Jacobsen
 

By far the most useful approach is to have system name completely describe how to access the hardware device. A system name where the suffix can be parsed out to give enough information to create the object is just easier to manage from e.g. scripts and file loading. Examples are C/MRI Light/Turnout/Switch (LTS) which have the node and pin encoded in the address; the Power Line connection which specifies house code and device code, and Grapevine which encodes all sorts of things in its names.

https://www.jmri.org/help/en/html/hardware/cmri/CMRI.shtml
https://www.jmri.org/help/en/html/hardware/powerline/Names.shtml
https://www.jmri.org/help/en/html/hardware/grapevine/Names.shtml

That’s not the complete configuration, of course. Things like feedback sensors still need to be directly configured. But it’s enough to _create_ the object so that it can be retained, even if that configuration will be happening later.

But in the alternative that for some reason this can’t be done, you can always reimplement a different ProxyServer that doesn’t also implement ProvidingManager. A clean way to do this would be to create a new AbstractProvidingProxyManager that is a subclass of AbstractProxyManager, move all the existing subclasses to that, and then have AbstractProxyManager provide everything _except_ the ProvidingManager implementation. That way we end up with AbstractProxyManager being a minimal implementation of ProxyManager hence Manager, and the AbstractProvidingProxyManager still providing the super classes for everything that’s there now.

Bob

On Jan 5, 2020, at 5:56 AM, danielb987 <db123@...> wrote:

I'm implementing managers for AnalogIO and StringIO. I'm going to add a generic ProxyManager and a specific LocoNet manager for these.

AbstractProxyManager implements ProvidingManager, so I must add the method provide() in the ProxyManager. But I cannot create an AnalogIO or a StringIO from only a system name, so this method should always fail, at least for the LocoNet manager. What is the proper way to handle this? Throw an IllegalArgumentException("not supported") or throw an UnsupportedOperationException("not supported") ?

Daniel
--
Bob Jacobsen
@BobJacobsen


Randall Wood <rhwood@...>
 

On 05-Jan-2020, at 09:51, danielb987 <db123@...> wrote:

LocoNet doesn't have support for analog values or string values as far as I know. So I'm going to use the LocoNet OPC_PEER command, using "SV programming format 1" and "SV programming format 2".

This means that an AnalogIO on the LocoNet needs:
* Destination address
* SV address
* Type (8 bit integer, 16 bit integer, 32 bit integer or 32 bit float)

A StringIO on the LocoNet needs:
* Destination address
* SV address
* Type (8 byte string using SV format 1 or variable length string using multiple OPC_PEER packages to send the string)

I can create a system name that has destination address, sv address and type, but I don't see the point of doing so since there is no way to auto discover analog IO or string IO on the LocoNet. I can discover OPC_PEER devices, but there is currently no way for the devices to tell their configuration of SV addresses.

My problem is not the need for a user name. My problem is that I need a destination address, sv address and type, and I prefer to not have these final to allow the user to be able to change these.
- There is no documented requirement that the system name of a NamedBean be final (there is a protocol requirement that the system name of an AbstractNamedBean be final).
- There is no requirement the NamedBean implementations extend AbstractNamedBean (there are already NamedBean implementations that don’t).
- The *only* requirement is that system names be unique within a running JMRI instance.

Also, by your design, it seems I could have two different NamedBeans that attempt to write (and I assume read) two different types of data (say 8 bit integer vs float or 16 bit integer vs variable length string) from the same device/SV. That suggests you should have a NamedBean for an IO device, not for an IO device by type of data handled.

Daniel

2020-01-05 15:13 skrev Randall Wood via Groups.Io:
The requirement (and this is an *absolute* requirement) for NamedBeans
is that the user name is optional, and the system name is the only
name that’s needed.
User Names are set by the user, and only by the user, not by system
connections (unless the message in the system contains both something
that can be a system name and something that can be a user name).
This is because devices on a connection (like LocoNet) can *only* be
addressed by data encoded in the system name.
If you can’t work with that constraint then you don’t have a usable
design (especially for a device on the LocoNet).
Put another way, you can’t create a discovered LocoNet device with a
user name, because the LocoNet did not provide a user name to use,
just an address that is encoded into the system name.
ProvidingManagers are designed to work with system connected devices
to allow a flow like LocoNet traffic handler on connection “L”, sees
message from thing at address 42->reads message, determines thing is
Turnout->requests bean for turnout at address 42 (I.e. requests bean
LT42) be provided->ProvidingManager returns that bean, creating it if
needed.
If you *really* need to add LocoNet devices that can’t be provided
implement ProxyManager instead of extending AbstractProxyManager.
But I would first reconsider your requirement that user names be
assigned, since that’s not possible on the LocoNet itself.
Randall
On Jan 5, 2020, at 08:56, danielb987 <db123@...> wrote:
I'm implementing managers for AnalogIO and StringIO. I'm going to add a generic ProxyManager and a specific LocoNet manager for these.
AbstractProxyManager implements ProvidingManager, so I must add the method provide() in the ProxyManager. But I cannot create an AnalogIO or a StringIO from only a system name, so this method should always fail, at least for the LocoNet manager. What is the proper way to handle this? Throw an IllegalArgumentException("not supported") or throw an UnsupportedOperationException("not supported") ?
Daniel


danielb987
 

LocoNet doesn't have support for analog values or string values as far as I know. So I'm going to use the LocoNet OPC_PEER command, using "SV programming format 1" and "SV programming format 2".

This means that an AnalogIO on the LocoNet needs:
* Destination address
* SV address
* Type (8 bit integer, 16 bit integer, 32 bit integer or 32 bit float)

A StringIO on the LocoNet needs:
* Destination address
* SV address
* Type (8 byte string using SV format 1 or variable length string using multiple OPC_PEER packages to send the string)

I can create a system name that has destination address, sv address and type, but I don't see the point of doing so since there is no way to auto discover analog IO or string IO on the LocoNet. I can discover OPC_PEER devices, but there is currently no way for the devices to tell their configuration of SV addresses.

My problem is not the need for a user name. My problem is that I need a destination address, sv address and type, and I prefer to not have these final to allow the user to be able to change these.

Daniel

2020-01-05 15:13 skrev Randall Wood via Groups.Io:

The requirement (and this is an *absolute* requirement) for NamedBeans
is that the user name is optional, and the system name is the only
name that’s needed.
User Names are set by the user, and only by the user, not by system
connections (unless the message in the system contains both something
that can be a system name and something that can be a user name).
This is because devices on a connection (like LocoNet) can *only* be
addressed by data encoded in the system name.
If you can’t work with that constraint then you don’t have a usable
design (especially for a device on the LocoNet).
Put another way, you can’t create a discovered LocoNet device with a
user name, because the LocoNet did not provide a user name to use,
just an address that is encoded into the system name.
ProvidingManagers are designed to work with system connected devices
to allow a flow like LocoNet traffic handler on connection “L”, sees
message from thing at address 42->reads message, determines thing is
Turnout->requests bean for turnout at address 42 (I.e. requests bean
LT42) be provided->ProvidingManager returns that bean, creating it if
needed.
If you *really* need to add LocoNet devices that can’t be provided
implement ProxyManager instead of extending AbstractProxyManager.
But I would first reconsider your requirement that user names be
assigned, since that’s not possible on the LocoNet itself.
Randall
On Jan 5, 2020, at 08:56, danielb987 <db123@...> wrote:
I'm implementing managers for AnalogIO and StringIO. I'm going to add a generic ProxyManager and a specific LocoNet manager for these.
AbstractProxyManager implements ProvidingManager, so I must add the method provide() in the ProxyManager. But I cannot create an AnalogIO or a StringIO from only a system name, so this method should always fail, at least for the LocoNet manager. What is the proper way to handle this? Throw an IllegalArgumentException("not supported") or throw an UnsupportedOperationException("not supported") ?
Daniel


Randall Wood <rhwood@...>
 

The requirement (and this is an *absolute* requirement) for NamedBeans is that the user name is optional, and the system name is the only name that’s needed.

User Names are set by the user, and only by the user, not by system connections (unless the message in the system contains both something that can be a system name and something that can be a user name).

This is because devices on a connection (like LocoNet) can *only* be addressed by data encoded in the system name.

If you can’t work with that constraint then you don’t have a usable design (especially for a device on the LocoNet).

Put another way, you can’t create a discovered LocoNet device with a user name, because the LocoNet did not provide a user name to use, just an address that is encoded into the system name.

ProvidingManagers are designed to work with system connected devices to allow a flow like LocoNet traffic handler on connection “L”, sees message from thing at address 42->reads message, determines thing is Turnout->requests bean for turnout at address 42 (I.e. requests bean LT42) be provided->ProvidingManager returns that bean, creating it if needed.

If you *really* need to add LocoNet devices that can’t be provided implement ProxyManager instead of extending AbstractProxyManager.

But I would first reconsider your requirement that user names be assigned, since that’s not possible on the LocoNet itself.

Randall

On Jan 5, 2020, at 08:56, danielb987 <db123@...> wrote:

I'm implementing managers for AnalogIO and StringIO. I'm going to add a generic ProxyManager and a specific LocoNet manager for these.

AbstractProxyManager implements ProvidingManager, so I must add the method provide() in the ProxyManager. But I cannot create an AnalogIO or a StringIO from only a system name, so this method should always fail, at least for the LocoNet manager. What is the proper way to handle this? Throw an IllegalArgumentException("not supported") or throw an UnsupportedOperationException("not supported") ?

Daniel



danielb987
 

I'm implementing managers for AnalogIO and StringIO. I'm going to add a generic ProxyManager and a specific LocoNet manager for these.

AbstractProxyManager implements ProvidingManager, so I must add the method provide() in the ProxyManager. But I cannot create an AnalogIO or a StringIO from only a system name, so this method should always fail, at least for the LocoNet manager. What is the proper way to handle this? Throw an IllegalArgumentException("not supported") or throw an UnsupportedOperationException("not supported") ?

Daniel