Skip to main content



      Home
Home » Modeling » Modeling (top-level project) » Reference Containment Question
Reference Containment Question [message #378379] Thu, 16 November 2006 23:22 Go to next message
Eclipse UserFriend
Originally posted by: ole_ersoy.yahoo.com

Hi,

I'm experimenting with non containment references and demand loading of
resources using the Purchase Order model from the emf book.

If I set containment to true on the PO items EReference and add an item to
the reference that is actually owned by a different reasource, I get no
exceptions.

However, if I set containment to true on the items reference and repeat
the same test, I get an

org.eclipse.emf.ecore.resource.Resource$IOWrappedException.. .the object is
not contained in resource.

I was expecting this to be the other way around. So that when containment
is true, I should get an exception, because the item added to the items
list is contained in a different resource...

Am I missing something?

Thanks,
- Ole
Re: Reference Containment Question [message #378380 is a reply to message #378379] Thu, 16 November 2006 23:25 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: ole_ersoy.yahoo.com

Oooops:

However, if I set containment to true on the items reference and repeat
the same test, I get an


Should have been

However, if I set containment to false on the items reference and repeat
the same test, I get an
Re: Reference Containment Question [message #378381 is a reply to message #378380] Fri, 17 November 2006 04:45 Go to previous messageGo to next message
Eclipse UserFriend
Ole,

This question would be best asked in the EMF newsgroup. The only time
you should get the exception you show is when you have a non-containment
reference to an object not contained directly or indirect by any
resource, i.e., an object for which eResource() is null. When you
assign an object to a containment reference, it will be removed from
where it's currently contained so assigning an item currently in another
resource to the list will remove it from that other resource. There is
support for cross resource containment, which involves setting
resolveProxies to true and settings the GenModel's "Containment Proxies"
properto true to respect that. In that case, an object assigned to the
containment list will not be removed from the other resource if it is
directly contained by that resource (but it still will be removed from
any other container since there can be just one eContainer()).


Ole wrote:
> Oooops:
>
> However, if I set containment to true on the items reference and
> repeat the same test, I get an
>
>
> Should have been
>
> However, if I set containment to false on the items reference and
> repeat the same test, I get an
>
>
Re: Reference Containment Question [message #378382 is a reply to message #378381] Fri, 17 November 2006 10:10 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: ole_ersoy.yahoo.com

Hi Ed,

I thought this was the EMF newsgroup? Please let me know if there a
different one you had in mind (gmt, mddl, etc.).

I think this might be a bug, because both items are assigned to a
resource, created like this:

resource1 =
resourceSet.createResource(URI.createFileURI("src/test/resources/po1.xml "));


resource2 = resourceSet.createResource(URI.createFileURI("src/po2.xml"));


I added the PO to resource1 and both items to the PO.

However I added the second item to resource 2.

When I call save on the resources both po1.xml and po2.xml are created.

However, if I set containment to false on the items reference, I get the
exceptions.

I can submit a bug and test case that would be helpful.

Cheers,
- Ole
Re: Reference Containment Question [message #378383 is a reply to message #378382] Fri, 17 November 2006 10:30 Go to previous messageGo to next message
Eclipse UserFriend
Ole,

This is the newsgroup for the overall modeling project. The newsgroup
for EMF is currently eclipse.tools.emf. We need to move it under
modeling, but we haven't done that yet because you can't actually move a
newsgroup but instead have to create a new empty one which I don't want
because then thousands of previous questions and answers effectively
become somewhat invisible.) I've added it to the list so replies will
appear in both groups.

You say you are adding two items to the list. So for your second case
where you make the items reference be non-containment you've also added
two items, but only the second item is added to a resource. So the
first item will not be contained by the purchase order, nor did you add
it to any resource to make it be contained by a resource. So that first
item is not contained by anything and will cause this exception. Keep
in mind that managing containment correctly is a fundamental aspect of
maintaining referential integrity so the odds of this being buggy after
more than four years of heavy use is pretty close to zero...


Ole wrote:
> Hi Ed,
>
> I thought this was the EMF newsgroup? Please let me know if there a
> different one you had in mind (gmt, mddl, etc.).
>
> I think this might be a bug, because both items are assigned to a
> resource, created like this:
>
> resource1 =
> resourceSet.createResource(URI.createFileURI("src/test/resources/po1.xml "));
>
>
>
> resource2 = resourceSet.createResource(URI.createFileURI("src/po2.xml"));
>
>
> I added the PO to resource1 and both items to the PO.
>
> However I added the second item to resource 2.
>
> When I call save on the resources both po1.xml and po2.xml are created.
>
> However, if I set containment to false on the items reference, I get
> the exceptions.
>
> I can submit a bug and test case that would be helpful.
>
> Cheers,
> - Ole
>
Re: Reference Containment Question [message #378384 is a reply to message #378383] Fri, 17 November 2006 11:01 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: ole_ersoy.yahoo.com

Ed,

Sounds good. I'll post to tools.emf next time.

Both items have been added to resources.

So the first item is in resource1 and the second item is in resource2.

The second item is also added to the containment items EReference on the
PO.

So the first item is contained by the purchase order. The purchase order
is contained in resource1.

The second item is contained by resource2.

The second item is also added to the items list on the PO.

Then the two resources are serialized.



So when containment is set to true on the PO items reference, I get no
exceptions, but when it's false, I get the exception.

If I understand correctly, containment being set to true means that all
the items that are on the items list should be owned by the resource that
owns the PO.

If containment is set to false on the items EReference, then the scenario
I'm describing where the second item is contained by resource2, should be
ok/no exceptions?

Does that sound right?

Cheers,
- Ole
Re: Reference Containment Question [message #378385 is a reply to message #378384] Fri, 17 November 2006 11:08 Go to previous messageGo to next message
Eclipse UserFriend
Ole,

Yes, in the second scenario, the second item is fine because you've
added it to the second resource. But in the second scenario, the first
item is added only to the purchase order's items list which is not a
containment. So that first item is not contained by PO and is hence is
not contained by the resource containing PO. So it's not contained
anywhere, right? This is exactly the case where you will get a dangling
reference exception during save.


Ole wrote:
> Ed,
>
> Sounds good. I'll post to tools.emf next time.
>
> Both items have been added to resources.
>
> So the first item is in resource1 and the second item is in resource2.
>
> The second item is also added to the containment items EReference on
> the PO.
>
> So the first item is contained by the purchase order. The purchase
> order is contained in resource1.
>
> The second item is contained by resource2.
>
> The second item is also added to the items list on the PO.
>
> Then the two resources are serialized.
>
>
>
> So when containment is set to true on the PO items reference, I get no
> exceptions, but when it's false, I get the exception.
>
> If I understand correctly, containment being set to true means that
> all the items that are on the items list should be owned by the
> resource that owns the PO.
>
> If containment is set to false on the items EReference, then the
> scenario I'm describing where the second item is contained by
> resource2, should be ok/no exceptions?
>
> Does that sound right?
>
> Cheers,
> - Ole
>
>
Re: Reference Containment Question [message #378386 is a reply to message #378385] Fri, 17 November 2006 12:27 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: ole_ersoy.yahoo.com

Oooooh - I think the lights are starting to turn on.

Because items is a non-containment EReference, all existing Items added to
items must be added directly to a resource as well or the resource
reference has to be set on the Item so that it knows what resource it
belongs to.

That makes sense.

What about the flip side.

If I set containment to true on the items EReference,
I think I should expect an exception when serializing
because the second item is not owned by the resource
that owns the PO.

For example I did this:

po.getItems().add(item1);
po.getItems().add(item2);

resource1.getContents().add(po);
resource2.getContents().add(item2);

In this case the po's items EList is
EObjectContainmentEList

So if I understand correctly all the items added to this list should be
owned
by the resource that the po is owned by.

However, when I save resource1 and resource2,
the items are saved to each resource correspondingly.

Should I get an exception here saying that
item2 is owned by a resource other than the resource
that owns the items list?

Thanks again,
- Ole


OK - I think Thanks again.
- Ole
Re: Reference Containment Question [message #378387 is a reply to message #378386] Fri, 17 November 2006 14:21 Go to previous messageGo to next message
Eclipse UserFriend
Ole,

Comments below.


Ole wrote:
> Oooooh - I think the lights are starting to turn on.
>
> Because items is a non-containment EReference, all existing Items
> added to items must be added directly to a resource as well or the
> resource reference has to be set on the Item so that it knows what
> resource it belongs to.
> That makes sense.
>
> What about the flip side.
>
> If I set containment to true on the items EReference, I think I should
> expect an exception when serializing
> because the second item is not owned by the resource that owns the PO.
If the second item is not contained by a different resource, it will be
contained by the same resource as contains PO. So that should be fine.
And in fact, unless your support cross resource containment, adding the
item to the items list will remove it from the other resource.
>
> For example I did this:
>
> po.getItems().add(item1);
> po.getItems().add(item2);
> resource1.getContents().add(po);
> resource2.getContents().add(item2);
Unless getItems supports cross resource containment, this will actually
remove it from the getItems list.
>
> In this case the po's items EList is
> EObjectContainmentEList
>
> So if I understand correctly all the items added to this list should
> be owned
> by the resource that the po is owned by.
>
> However, when I save resource1 and resource2,
> the items are saved to each resource correspondingly.
>
> Should I get an exception here saying that item2 is owned by a
> resource other than the resource
> that owns the items list?
No, because you'll notice that item to has been moved and isn't even
referenced by PO. Try the cross resource containment support I outlined
and see how it behaves differently. The light will burn even brighter. ;-)
>
> Thanks again,
> - Ole
>
>
> OK - I think Thanks again. - Ole
>
Re: Reference Containment Question [message #378389 is a reply to message #378387] Fri, 17 November 2006 16:47 Go to previous message
Eclipse UserFriend
Originally posted by: ole_ersoy.yahoo.com

Ed,

I inlined comments (Although I'm using the eclipse Web Interface so
I'm putting really big spaces around my comments):


Ole wrote:

Oooooh - I think the lights are starting to turn on.

Because items is a non-containment EReference, all existing Items
added to items must be added directly to a resource as well or the
resource reference has to be set on the Item so that it knows what
resource it belongs to. That makes sense.

What about the flip side.

If I set containment to true on the items EReference, I think I should
expect an exception when serializing
because the second item is not owned by the resource that owns the PO.

If the second item is not contained by a different resource, it will be
contained by the same resource as contains PO.
So that should be fine. And in fact, unless your support cross resource
containment, adding the item to the items list will remove it from the
other resource.





OK - I created the two items, then added them to the items list, then
added the second item to the second resource.

Both item serialize like this within the purchase order po1.xml file:

<pt:PurchaseOrder>
<items href="src/test/resources/po1.xml#/0"/>
<items href="src/po2.xml#/0"/>
</pt:PurchaseOrder>

So now the second item href points to the po2.xml file ...

So I must be supporting cross-document containment here.

I thought containment meant all items in a single document. However in
this case since I added item2 to resource2, it seems that EMF is ok with
it item2 being serialized to po2.xml, where it shows up like this:

<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:maven="http://maven.apache.org/POM/4.0.0"
xmlns:pt="http://www.pyramidetechnologies.com/model/emf.po">
<pt:Item name="item2Name"/>
</xmi:XMI>






For example I did this:

po.getItems().add(item1);
po.getItems().add(item2);
resource1.getContents().add(po);
resource2.getContents().add(item2);

Unless getItems supports cross resource containment, this will actually
remove it from the getItems list.




Well - I guess getItems supports cross resource containment, because it
has to in this case....so this seems to be built into EMF...that's just
how it works right?

So if I were to describe containment for this case I would say that it
means that >>> items added to a containment EReference are owned by the
resource that owns the EReference, unless the item is added to a different
resource after having been added to the EReference. Adding the item to a
different resource after adding it to the EReference resets the items
eResource parameter and this has now created cross document containment
situation per the items EReference.

So in this case it seems like the concept of containment in EMF means that
if an object is added or set to an EReference that is a containment
reference, then the eResource of that object is set to the same eResource
of the containment EReference. That's all. There's really no other
constraint imposed.





In this case the po's items EList is
EObjectContainmentEList

So if I understand correctly all the items added to this list should
be owned
by the resource that the po is owned by.

However, when I save resource1 and resource2,
the items are saved to each resource correspondingly.

Should I get an exception here saying that item2 is owned by a
resource other than the resource
that owns the items list?

No, because you'll notice that item to has been moved and isn't even
referenced by PO. Try the cross resource containment support I outlined
and see how it behaves differently. The light will burn even brighter. ;-)





Yeah .... I think there's stuff moving around up there :-)





Thanks again,
- Ole
Re: Reference Containment Question [message #585002 is a reply to message #378379] Thu, 16 November 2006 23:25 Go to previous message
Eclipse UserFriend
Oooops:

However, if I set containment to true on the items reference and repeat
the same test, I get an


Should have been

However, if I set containment to false on the items reference and repeat
the same test, I get an
Re: Reference Containment Question [message #585026 is a reply to message #378380] Fri, 17 November 2006 04:45 Go to previous message
Eclipse UserFriend
Ole,

This question would be best asked in the EMF newsgroup. The only time
you should get the exception you show is when you have a non-containment
reference to an object not contained directly or indirect by any
resource, i.e., an object for which eResource() is null. When you
assign an object to a containment reference, it will be removed from
where it's currently contained so assigning an item currently in another
resource to the list will remove it from that other resource. There is
support for cross resource containment, which involves setting
resolveProxies to true and settings the GenModel's "Containment Proxies"
properto true to respect that. In that case, an object assigned to the
containment list will not be removed from the other resource if it is
directly contained by that resource (but it still will be removed from
any other container since there can be just one eContainer()).


Ole wrote:
> Oooops:
>
> However, if I set containment to true on the items reference and
> repeat the same test, I get an
>
>
> Should have been
>
> However, if I set containment to false on the items reference and
> repeat the same test, I get an
>
>
Re: Reference Containment Question [message #585043 is a reply to message #378381] Fri, 17 November 2006 10:10 Go to previous message
Eclipse UserFriend
Hi Ed,

I thought this was the EMF newsgroup? Please let me know if there a
different one you had in mind (gmt, mddl, etc.).

I think this might be a bug, because both items are assigned to a
resource, created like this:

resource1 =
resourceSet.createResource(URI.createFileURI("src/test/resources/po1.xml "));


resource2 = resourceSet.createResource(URI.createFileURI("src/po2.xml"));


I added the PO to resource1 and both items to the PO.

However I added the second item to resource 2.

When I call save on the resources both po1.xml and po2.xml are created.

However, if I set containment to false on the items reference, I get the
exceptions.

I can submit a bug and test case that would be helpful.

Cheers,
- Ole
Re: Reference Containment Question [message #585051 is a reply to message #378382] Fri, 17 November 2006 10:30 Go to previous message
Eclipse UserFriend
Ole,

This is the newsgroup for the overall modeling project. The newsgroup
for EMF is currently eclipse.tools.emf. We need to move it under
modeling, but we haven't done that yet because you can't actually move a
newsgroup but instead have to create a new empty one which I don't want
because then thousands of previous questions and answers effectively
become somewhat invisible.) I've added it to the list so replies will
appear in both groups.

You say you are adding two items to the list. So for your second case
where you make the items reference be non-containment you've also added
two items, but only the second item is added to a resource. So the
first item will not be contained by the purchase order, nor did you add
it to any resource to make it be contained by a resource. So that first
item is not contained by anything and will cause this exception. Keep
in mind that managing containment correctly is a fundamental aspect of
maintaining referential integrity so the odds of this being buggy after
more than four years of heavy use is pretty close to zero...


Ole wrote:
> Hi Ed,
>
> I thought this was the EMF newsgroup? Please let me know if there a
> different one you had in mind (gmt, mddl, etc.).
>
> I think this might be a bug, because both items are assigned to a
> resource, created like this:
>
> resource1 =
> resourceSet.createResource(URI.createFileURI("src/test/resources/po1.xml "));
>
>
>
> resource2 = resourceSet.createResource(URI.createFileURI("src/po2.xml"));
>
>
> I added the PO to resource1 and both items to the PO.
>
> However I added the second item to resource 2.
>
> When I call save on the resources both po1.xml and po2.xml are created.
>
> However, if I set containment to false on the items reference, I get
> the exceptions.
>
> I can submit a bug and test case that would be helpful.
>
> Cheers,
> - Ole
>
Re: Reference Containment Question [message #585067 is a reply to message #378383] Fri, 17 November 2006 11:01 Go to previous message
Eclipse UserFriend
Ed,

Sounds good. I'll post to tools.emf next time.

Both items have been added to resources.

So the first item is in resource1 and the second item is in resource2.

The second item is also added to the containment items EReference on the
PO.

So the first item is contained by the purchase order. The purchase order
is contained in resource1.

The second item is contained by resource2.

The second item is also added to the items list on the PO.

Then the two resources are serialized.



So when containment is set to true on the PO items reference, I get no
exceptions, but when it's false, I get the exception.

If I understand correctly, containment being set to true means that all
the items that are on the items list should be owned by the resource that
owns the PO.

If containment is set to false on the items EReference, then the scenario
I'm describing where the second item is contained by resource2, should be
ok/no exceptions?

Does that sound right?

Cheers,
- Ole
Re: Reference Containment Question [message #585075 is a reply to message #378384] Fri, 17 November 2006 11:08 Go to previous message
Eclipse UserFriend
Ole,

Yes, in the second scenario, the second item is fine because you've
added it to the second resource. But in the second scenario, the first
item is added only to the purchase order's items list which is not a
containment. So that first item is not contained by PO and is hence is
not contained by the resource containing PO. So it's not contained
anywhere, right? This is exactly the case where you will get a dangling
reference exception during save.


Ole wrote:
> Ed,
>
> Sounds good. I'll post to tools.emf next time.
>
> Both items have been added to resources.
>
> So the first item is in resource1 and the second item is in resource2.
>
> The second item is also added to the containment items EReference on
> the PO.
>
> So the first item is contained by the purchase order. The purchase
> order is contained in resource1.
>
> The second item is contained by resource2.
>
> The second item is also added to the items list on the PO.
>
> Then the two resources are serialized.
>
>
>
> So when containment is set to true on the PO items reference, I get no
> exceptions, but when it's false, I get the exception.
>
> If I understand correctly, containment being set to true means that
> all the items that are on the items list should be owned by the
> resource that owns the PO.
>
> If containment is set to false on the items EReference, then the
> scenario I'm describing where the second item is contained by
> resource2, should be ok/no exceptions?
>
> Does that sound right?
>
> Cheers,
> - Ole
>
>
Re: Reference Containment Question [message #585092 is a reply to message #378385] Fri, 17 November 2006 12:27 Go to previous message
Eclipse UserFriend
Oooooh - I think the lights are starting to turn on.

Because items is a non-containment EReference, all existing Items added to
items must be added directly to a resource as well or the resource
reference has to be set on the Item so that it knows what resource it
belongs to.

That makes sense.

What about the flip side.

If I set containment to true on the items EReference,
I think I should expect an exception when serializing
because the second item is not owned by the resource
that owns the PO.

For example I did this:

po.getItems().add(item1);
po.getItems().add(item2);

resource1.getContents().add(po);
resource2.getContents().add(item2);

In this case the po's items EList is
EObjectContainmentEList

So if I understand correctly all the items added to this list should be
owned
by the resource that the po is owned by.

However, when I save resource1 and resource2,
the items are saved to each resource correspondingly.

Should I get an exception here saying that
item2 is owned by a resource other than the resource
that owns the items list?

Thanks again,
- Ole


OK - I think Thanks again.
- Ole
Re: Reference Containment Question [message #585106 is a reply to message #378386] Fri, 17 November 2006 14:21 Go to previous message
Eclipse UserFriend
Ole,

Comments below.


Ole wrote:
> Oooooh - I think the lights are starting to turn on.
>
> Because items is a non-containment EReference, all existing Items
> added to items must be added directly to a resource as well or the
> resource reference has to be set on the Item so that it knows what
> resource it belongs to.
> That makes sense.
>
> What about the flip side.
>
> If I set containment to true on the items EReference, I think I should
> expect an exception when serializing
> because the second item is not owned by the resource that owns the PO.
If the second item is not contained by a different resource, it will be
contained by the same resource as contains PO. So that should be fine.
And in fact, unless your support cross resource containment, adding the
item to the items list will remove it from the other resource.
>
> For example I did this:
>
> po.getItems().add(item1);
> po.getItems().add(item2);
> resource1.getContents().add(po);
> resource2.getContents().add(item2);
Unless getItems supports cross resource containment, this will actually
remove it from the getItems list.
>
> In this case the po's items EList is
> EObjectContainmentEList
>
> So if I understand correctly all the items added to this list should
> be owned
> by the resource that the po is owned by.
>
> However, when I save resource1 and resource2,
> the items are saved to each resource correspondingly.
>
> Should I get an exception here saying that item2 is owned by a
> resource other than the resource
> that owns the items list?
No, because you'll notice that item to has been moved and isn't even
referenced by PO. Try the cross resource containment support I outlined
and see how it behaves differently. The light will burn even brighter. ;-)
>
> Thanks again,
> - Ole
>
>
> OK - I think Thanks again. - Ole
>
Re: Reference Containment Question [message #585130 is a reply to message #378387] Fri, 17 November 2006 16:47 Go to previous message
Eclipse UserFriend
Ed,

I inlined comments (Although I'm using the eclipse Web Interface so
I'm putting really big spaces around my comments):


Ole wrote:

Oooooh - I think the lights are starting to turn on.

Because items is a non-containment EReference, all existing Items
added to items must be added directly to a resource as well or the
resource reference has to be set on the Item so that it knows what
resource it belongs to. That makes sense.

What about the flip side.

If I set containment to true on the items EReference, I think I should
expect an exception when serializing
because the second item is not owned by the resource that owns the PO.

If the second item is not contained by a different resource, it will be
contained by the same resource as contains PO.
So that should be fine. And in fact, unless your support cross resource
containment, adding the item to the items list will remove it from the
other resource.





OK - I created the two items, then added them to the items list, then
added the second item to the second resource.

Both item serialize like this within the purchase order po1.xml file:

<pt:PurchaseOrder>
<items href="src/test/resources/po1.xml#/0"/>
<items href="src/po2.xml#/0"/>
</pt:PurchaseOrder>

So now the second item href points to the po2.xml file ...

So I must be supporting cross-document containment here.

I thought containment meant all items in a single document. However in
this case since I added item2 to resource2, it seems that EMF is ok with
it item2 being serialized to po2.xml, where it shows up like this:

<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:maven="http://maven.apache.org/POM/4.0.0"
xmlns:pt="http://www.pyramidetechnologies.com/model/emf.po">
<pt:Item name="item2Name"/>
</xmi:XMI>






For example I did this:

po.getItems().add(item1);
po.getItems().add(item2);
resource1.getContents().add(po);
resource2.getContents().add(item2);

Unless getItems supports cross resource containment, this will actually
remove it from the getItems list.




Well - I guess getItems supports cross resource containment, because it
has to in this case....so this seems to be built into EMF...that's just
how it works right?

So if I were to describe containment for this case I would say that it
means that >>> items added to a containment EReference are owned by the
resource that owns the EReference, unless the item is added to a different
resource after having been added to the EReference. Adding the item to a
different resource after adding it to the EReference resets the items
eResource parameter and this has now created cross document containment
situation per the items EReference.

So in this case it seems like the concept of containment in EMF means that
if an object is added or set to an EReference that is a containment
reference, then the eResource of that object is set to the same eResource
of the containment EReference. That's all. There's really no other
constraint imposed.





In this case the po's items EList is
EObjectContainmentEList

So if I understand correctly all the items added to this list should
be owned
by the resource that the po is owned by.

However, when I save resource1 and resource2,
the items are saved to each resource correspondingly.

Should I get an exception here saying that item2 is owned by a
resource other than the resource
that owns the items list?

No, because you'll notice that item to has been moved and isn't even
referenced by PO. Try the cross resource containment support I outlined
and see how it behaves differently. The light will burn even brighter. ;-)





Yeah .... I think there's stuff moving around up there :-)





Thanks again,
- Ole
Previous Topic:Reference Containment Question
Next Topic:EMF using XMI
Goto Forum:
  


Current Time: Wed Jul 23 10:34:23 EDT 2025

Powered by FUDForum. Page generated in 0.34600 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top