Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » PartialParsingHelper.reparse removes Container ?!
PartialParsingHelper.reparse removes Container ?! [message #908340] Wed, 05 September 2012 07:42 Go to next message
Michael Vorburger is currently offline Michael VorburgerFriend
Messages: 103
Registered: July 2009
Senior Member
Hello,

While experimenting with Xtext and Data Binding, building a EMFXtextProperties which goes via an IReadAccess<XtextResource> & IWriteAccess<XtextResource> (= XtextDocument) instead of an EditingDomain (see other Forum thread "Xtext + FormEditor") I ran into the following problem which looks like a design flaw or bug, unless I misunderstand:

So my Data Binding EMFXtextValueProperty.doSetValue goes into your XtextDocument.modify. The idea was that your DefaultTextEditComposer will pick up the EMF model modification from the data binding, and update the document text. That never happens (actually it happens once / first time, and then no longer, in an open editor), because [...hours of debugging...] DefaultTextEditComposer's (IS-A EContentAdapter) notifyChanged never gets called anymore, because PartialParsingHelper.reparse unset a contained object container, see the more detailed stack trace below, so the notification chain is broken.

I'm hoping the explanation makes sense - if it doesn't, I can publish full example code illustrating more clearly what I mean - if you Xtext Core guys would be willing to look into this?

Any thoughts / advise much appreciated!

Regards,
Michael


Thread [main] (Suspended (breakpoint at line 180 in MinimalEObjectImpl$Container))
owns: RunnableLock (id=2533)
FieldImpl(MinimalEObjectImpl$Container).eBasicSetContainer(InternalEObject) line: 180
FieldImpl(MinimalEObjectImpl).eBasicSetContainer(InternalEObject, int) line: 665
FieldImpl(BasicEObjectImpl).eBasicSetContainer(InternalEObject, int, NotificationChain) line: 1328
FieldImpl(BasicEObjectImpl).eInverseRemove(InternalEObject, int, Class<?>, NotificationChain) line: 1441
EObjectContainmentEList<E>(EcoreEList<E>).inverseRemove(E, NotificationChain) line: 322
EObjectContainmentEList<E>(NotifyingListImpl<E>).setUnique(int, E) line: 1180
EObjectContainmentEList<E>(AbstractEList<E>).set(int, E) line: 266
PartialParsingHelper.reparse(IParser, IParseResult, ReplaceRegion) line: 158
ScreenParser(AbstractAntlrParser).doReparse(IParseResult, ReplaceRegion) line: 136
ScreenParser(AbstractParser).reparse(IParseResult, ReplaceRegion) line: 40
LazyLinkingResource(XtextResource).update(int, int, String) line: 217
XtextReconcilerUnitOfWork.process(XtextResource) line: 55
XtextReconcilerUnitOfWork.process(Object) line: 1
XtextReconcilerUnitOfWork(IUnitOfWork$Void<T>).exec(T) line: 36
XtextDocument$XtextDocumentLocker(AbstractReadWriteAcces<P>).modify(IUnitOfWork<T,P>) line: 49
XtextDocument$XtextDocumentLocker.modify(IUnitOfWork<T,XtextResource>) line: 181
XtextDocument$XtextDocumentLocker.process(IUnitOfWork<T,XtextResource>) line: 202
XtextReconciler$DocumentListener.performNecessaryUpdates(IXtextDocumentContentObserver$Processor) line: 81
XtextDocument.updateContentBeforeRead() line: 135
XtextDocument$XtextDocumentLocker.beforeReadOnly(XtextResource, IUnitOfWork<?,XtextResource>) line: 155
XtextDocument$XtextDocumentLocker.beforeReadOnly(Object, IUnitOfWork) line: 1
XtextDocument$XtextDocumentLocker(AbstractReadWriteAcces<P>).readOnly(IUnitOfWork<T,P>) line: 31
XtextDocument.readOnly(IUnitOfWork<T,XtextResource>) line: 78
DefaultFoldingRegionProvider.getFoldingRegions(IXtextDocument) line: 56
DefaultFoldingStructureProvider.calculateProjectionAnnotationModel(boolean) line: 114
DefaultFoldingStructureProvider.modelChanged(XtextResource) line: 92
XtextDocument.notifyModelListeners(XtextResource) line: 118
XtextDocument$XtextDocumentLocker.afterModify(XtextResource, Object, IUnitOfWork<?,XtextResource>) line: 172
XtextDocument$XtextDocumentLocker.afterModify(Object, Object, IUnitOfWork) line: 1
XtextDocument$XtextDocumentLocker(AbstractReadWriteAcces<P>).modify(IUnitOfWork<T,P>) line: 50
XtextDocument$XtextDocumentLocker.modify(IUnitOfWork<T,XtextResource>) line: 181
XtextDocument.internalModify(IUnitOfWork<T,XtextResource>) line: 90
XtextDocument.modify(IUnitOfWork<T,XtextResource>) line: 83
XtextResourceDelegatingAccess.modify(IUnitOfWork<T,XtextResource>) line: 29
EMFXtextValueProperty.doSetValue(Object, Object) line: 35
EMFXtextValueProperty(ValueProperty).setValue(Object, Object) line: 83
SimplePropertyObservableValue.doSetValue(Object) line: 104
SimplePropertyObservableValue(AbstractObservableValue).setValue(Object) line: 55
EMFXtextObservableValueDecorator(DecoratingObservableValue).setValue(Object) line: 103
EMFUpdateValueStrategy(UpdateValueStrategy).doSet(IObservableValue, Object) line: 486
ValueBinding$4.run() line: 197
Realm$1.run() line: 148
SafeRunner.run(ISafeRunnable) line: 42
Realm.safeRun(Runnable) line: 152
SWTObservables$DisplayRealm(Realm).exec(Runnable) line: 170
ValueBinding$3.run() line: 188
Realm$1.run() line: 148
SafeRunner.run(ISafeRunnable) line: 42
Realm.safeRun(Runnable) line: 152
SWTObservables$DisplayRealm(Realm).exec(Runnable) line: 170
ValueBinding.doUpdate(IObservableValue, IObservableValue, UpdateValueStrategy, boolean, boolean) line: 151
ValueBinding.access$4(ValueBinding, IObservableValue, IObservableValue, UpdateValueStrategy, boolean, boolean) line: 140
ValueBinding$1.handleValueChange(ValueChangeEvent) line: 45
ValueChangeEvent.dispatch(IObservablesListener) line: 62
BeanObservableValueDecorator(ChangeManager).fireEvent(ObservableEvent) line: 119
BeanObservableValueDecorator(DecoratingObservableValue).fireValueChange(ValueDiff) line: 55
BeanObservableValueDecorator(DecoratingObservableValue).handleValueChange(ValueChangeEvent) line: 93
DecoratingObservableValue$1.handleValueChange(ValueChangeEvent) line: 67
ValueChangeEvent.dispatch(IObservablesListener) line: 62
SimplePropertyObservableValue(ChangeManager).fireEvent(ObservableEvent) line: 119
SimplePropertyObservableValue(AbstractObservableValue).fireValueChange(ValueDiff) line: 71
SimplePropertyObservableValue.notifyIfChanged(ValueDiff) line: 120
SimplePropertyObservableValue.access$1(SimplePropertyObservableValue, ValueDiff) line: 112
SimplePropertyObservableValue$2.run() line: 66
Realm$1.run() line: 148
SafeRunner.run(ISafeRunnable) line: 42
Realm.safeRun(Runnable) line: 152
SWTObservables$DisplayRealm.access$0(Runnable) line: 1
SWTObservables$1.run() line: 551
RunnableLock.run() line: 35
UISynchronizer(Synchronizer).runAsyncMessages(boolean) line: 135
Display.runAsyncMessages(boolean) line: 3529
Display.readAndDispatch() line: 3182
Re: PartialParsingHelper.reparse removes Container ?! [message #908384 is a reply to message #908340] Wed, 05 September 2012 09:34 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Michael,

the partial parser will replace entire subtrees of the model. Of course
it will unset the container of the removed parts. What would you expect
to happen? No, it's not an option to do a full diff-merge of the new
subtree and old subtree (complexity and performance-wise).

Regards,
Sebastian
--
Looking for professional support for Xtext, Xtend or Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 05.09.12 09:42, schrieb Michael Vorburger:
> Hello,
>
> While experimenting with Xtext and Data Binding, building a
> EMFXtextProperties which goes via an IReadAccess<XtextResource> &
> IWriteAccess<XtextResource> (= XtextDocument) instead of an
> EditingDomain (see other Forum thread "Xtext + FormEditor") I ran into
> the following problem which looks like a design flaw or bug, unless I
> misunderstand:
>
> So my Data Binding EMFXtextValueProperty.doSetValue goes into your
> XtextDocument.modify. The idea was that your DefaultTextEditComposer
> will pick up the EMF model modification from the data binding, and
> update the document text. That never happens (actually it happens once
> / first time, and then no longer, in an open editor), because [...hours
> of debugging...] DefaultTextEditComposer's (IS-A EContentAdapter)
> notifyChanged never gets called anymore, because
> PartialParsingHelper.reparse unset a contained object container, see the
> more detailed stack trace below, so the notification chain is broken.
>
> I'm hoping the explanation makes sense - if it doesn't, I can publish
> full example code illustrating more clearly what I mean - if you Xtext
> Core guys would be willing to look into this?
>
> Any thoughts / advise much appreciated!
>
> Regards,
> Michael
>
>
> Thread [main] (Suspended (breakpoint at line 180 in
> MinimalEObjectImpl$Container))
> owns: RunnableLock (id=2533)
> FieldImpl(MinimalEObjectImpl$Container).eBasicSetContainer(InternalEObject) line: 180
> FieldImpl(MinimalEObjectImpl).eBasicSetContainer(InternalEObject,
> int) line: 665
> FieldImpl(BasicEObjectImpl).eBasicSetContainer(InternalEObject,
> int, NotificationChain) line: 1328
> FieldImpl(BasicEObjectImpl).eInverseRemove(InternalEObject, int,
> Class<?>, NotificationChain) line: 1441
> EObjectContainmentEList<E>(EcoreEList<E>).inverseRemove(E,
> NotificationChain) line: 322
> EObjectContainmentEList<E>(NotifyingListImpl<E>).setUnique(int, E)
> line: 1180
> EObjectContainmentEList<E>(AbstractEList<E>).set(int, E) line: 266
> PartialParsingHelper.reparse(IParser, IParseResult, ReplaceRegion)
> line: 158
> ScreenParser(AbstractAntlrParser).doReparse(IParseResult,
> ReplaceRegion) line: 136
> ScreenParser(AbstractParser).reparse(IParseResult, ReplaceRegion)
> line: 40
> LazyLinkingResource(XtextResource).update(int, int, String) line: 217
> XtextReconcilerUnitOfWork.process(XtextResource) line: 55
> XtextReconcilerUnitOfWork.process(Object) line: 1
> XtextReconcilerUnitOfWork(IUnitOfWork$Void<T>).exec(T) line: 36
> XtextDocument$XtextDocumentLocker(AbstractReadWriteAcces<P>).modify(IUnitOfWork<T,P>) line: 49
> XtextDocument$XtextDocumentLocker.modify(IUnitOfWork<T,XtextResource>) line: 181
> XtextDocument$XtextDocumentLocker.process(IUnitOfWork<T,XtextResource>) line: 202
> XtextReconciler$DocumentListener.performNecessaryUpdates(IXtextDocumentContentObserver$Processor) line: 81
> XtextDocument.updateContentBeforeRead() line: 135
> XtextDocument$XtextDocumentLocker.beforeReadOnly(XtextResource,
> IUnitOfWork<?,XtextResource>) line: 155
> XtextDocument$XtextDocumentLocker.beforeReadOnly(Object,
> IUnitOfWork) line: 1
> XtextDocument$XtextDocumentLocker(AbstractReadWriteAcces<P>).readOnly(IUnitOfWork<T,P>) line: 31
> XtextDocument.readOnly(IUnitOfWork<T,XtextResource>) line: 78
> DefaultFoldingRegionProvider.getFoldingRegions(IXtextDocument)
> line: 56
> DefaultFoldingStructureProvider.calculateProjectionAnnotationModel(boolean) line: 114
> DefaultFoldingStructureProvider.modelChanged(XtextResource) line: 92
> XtextDocument.notifyModelListeners(XtextResource) line: 118
> XtextDocument$XtextDocumentLocker.afterModify(XtextResource,
> Object, IUnitOfWork<?,XtextResource>) line: 172
> XtextDocument$XtextDocumentLocker.afterModify(Object, Object,
> IUnitOfWork) line: 1
> XtextDocument$XtextDocumentLocker(AbstractReadWriteAcces<P>).modify(IUnitOfWork<T,P>) line: 50
> XtextDocument$XtextDocumentLocker.modify(IUnitOfWork<T,XtextResource>) line: 181
> XtextDocument.internalModify(IUnitOfWork<T,XtextResource>) line: 90
> XtextDocument.modify(IUnitOfWork<T,XtextResource>) line: 83
> XtextResourceDelegatingAccess.modify(IUnitOfWork<T,XtextResource>)
> line: 29
> EMFXtextValueProperty.doSetValue(Object, Object) line: 35
> EMFXtextValueProperty(ValueProperty).setValue(Object, Object) line: 83
> SimplePropertyObservableValue.doSetValue(Object) line: 104
> SimplePropertyObservableValue(AbstractObservableValue).setValue(Object) line: 55
> EMFXtextObservableValueDecorator(DecoratingObservableValue).setValue(Object) line: 103
> EMFUpdateValueStrategy(UpdateValueStrategy).doSet(IObservableValue,
> Object) line: 486
> ValueBinding$4.run() line: 197
> Realm$1.run() line: 148
> SafeRunner.run(ISafeRunnable) line: 42
> Realm.safeRun(Runnable) line: 152
> SWTObservables$DisplayRealm(Realm).exec(Runnable) line: 170
> ValueBinding$3.run() line: 188
> Realm$1.run() line: 148
> SafeRunner.run(ISafeRunnable) line: 42
> Realm.safeRun(Runnable) line: 152
> SWTObservables$DisplayRealm(Realm).exec(Runnable) line: 170
> ValueBinding.doUpdate(IObservableValue, IObservableValue,
> UpdateValueStrategy, boolean, boolean) line: 151
> ValueBinding.access$4(ValueBinding, IObservableValue,
> IObservableValue, UpdateValueStrategy, boolean, boolean) line: 140
> ValueBinding$1.handleValueChange(ValueChangeEvent) line: 45
> ValueChangeEvent.dispatch(IObservablesListener) line: 62
> BeanObservableValueDecorator(ChangeManager).fireEvent(ObservableEvent) line: 119
> BeanObservableValueDecorator(DecoratingObservableValue).fireValueChange(ValueDiff) line: 55
> BeanObservableValueDecorator(DecoratingObservableValue).handleValueChange(ValueChangeEvent) line: 93
> DecoratingObservableValue$1.handleValueChange(ValueChangeEvent)
> line: 67
> ValueChangeEvent.dispatch(IObservablesListener) line: 62
> SimplePropertyObservableValue(ChangeManager).fireEvent(ObservableEvent) line: 119
> SimplePropertyObservableValue(AbstractObservableValue).fireValueChange(ValueDiff) line: 71
> SimplePropertyObservableValue.notifyIfChanged(ValueDiff) line: 120
> SimplePropertyObservableValue.access$1(SimplePropertyObservableValue, ValueDiff) line: 112
> SimplePropertyObservableValue$2.run() line: 66
> Realm$1.run() line: 148
> SafeRunner.run(ISafeRunnable) line: 42
> Realm.safeRun(Runnable) line: 152
> SWTObservables$DisplayRealm.access$0(Runnable) line: 1
> SWTObservables$1.run() line: 551
> RunnableLock.run() line: 35
> UISynchronizer(Synchronizer).runAsyncMessages(boolean) line: 135
> Display.runAsyncMessages(boolean) line: 3529
> Display.readAndDispatch() line: 3182
Re: PartialParsingHelper.reparse removes Container ?! [message #911972 is a reply to message #908384] Wed, 12 September 2012 17:22 Go to previous messageGo to next message
Michael Vorburger is currently offline Michael VorburgerFriend
Messages: 103
Registered: July 2009
Senior Member
Hello Sebastian,

I've meanwhile found a moment to put together a full and standalone example illustrating more clearly what I'm struggling with:

github.com/vorburger/xtext-sandbox/tree/master/XtextDocumentBinding has the classic Model / Greeting DSL. The github.com/vorburger/xtext-sandbox/blob/master/XtextDocumentBinding/ch.voburger.xtext.sandbox.mydsl.ui/src/ch/voburger/xtext/sandbox/mydsl/ui/editor/MUIXtextEditor.java adds two SWT Text widgets under the Editor. One is "classic" addModifyListener(), and works, and the other is using EMFXtextProperties... the idea being that this would be bi-directional declarative data binding (only the binding from the TextBox into Xtext ). Now, it works once / first time, but then no longer (until you close / re-open editor). I've "hit the ceiling" Wink with my understanding of Xtext internals as to why...

It's not the fact that I'm passing Greeting out of IUnitOfWork, is it? I realize that's not entirely clean - but for the moment can't think of another way to do this with DataBinding - and doubted it's the underlying cause of the problem here.

Any thoughts / advise much appreciated!

Thanks a lot,
Michael

PS: Would github.com/vorburger/xtext-sandbox/tree/master/XtextDocumentBinding/ch.vorburger.xtext.databinding/src/ch/vorburger/xtext/databinding potentially be of interest as a contribution (once it's fully implemented and works) ?

[Updated on: Wed, 12 September 2012 17:23]

Report message to a moderator

Re: PartialParsingHelper.reparse removes Container ?! [message #911977 is a reply to message #911972] Wed, 12 September 2012 17:33 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Michael,

taken from

public interface IUnitOfWork<R,P> {
/**
* [..]
* <b>Do not return any references to something contained in this
resource</b>[..]
*/
R exec(P state) throws Exception;

Does that answer your question?

We make no guarantees about the live cylce of an instance from the
resource that is aquired in and returned from an IUnitOfWork. Xtext does
not work this way.

You may want to dive into
org.eclipse.xtext.ui.editor.outline.impl.AbstractOutlineNode to learn
how this one deals with EObjects from the resource.

Once it's fully implemented and works as expected, such a contribution
is welcome :)

Regards,
Sebastian
--
Looking for professional support for Xtext, Xtend or Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 12.09.12 19:22, schrieb Michael Vorburger:
> Hello Sebastian,
>
> I've meanwhile found a moment to put together a full and standalone
> example illustrating more clearly what I'm struggling with:
>
> github.com/vorburger/xtext-sandbox/tree/master/XtextDocumentBinding has
> the classic Model / Greeting DSL. The
> github.com/vorburger/xtext-sandbox/blob/master/XtextDocumentBinding/ch.voburger.xtext.sandbox.mydsl.ui/src/ch/voburger/xtext/sandbox/mydsl/ui/editor/MUIXtextEditor.java
> adds two SWT Text widgets under the Editor. One is "classic"
> addModifyListener(), and works, and the other is using
> EMFXtextProperties... the idea being that this would be bi-directional
> declarative data binding (only the binding from the TextBox into Xtext
> ). Now, it works once / first time, but then no longer (until you close
> / re-open editor). I've "hit the ceiling" ;) with my understanding of
> Xtext internals as to why...
>
> It's not the fact that I'm passing Greeting out of IUnitOfWork, is it? I
> realize that's not entirely clean - but for the moment can't think of
> another way to do this with DataBinding - and doubted it's the
> underlying cause of the problem here.
>
> Any thoughts / advise much appreciated!
>
> Thanks a lot,
> Michael
>
> PS: Would
> github.com/vorburger/xtext-sandbox/tree/master/XtextDocumentBinding/ch.vorburger.xtext.databinding/src/ch/vorburger/xtext/databinding
> potentially be of interest as a contribution (once it's fully
> implemented and works) ?
Re: PartialParsingHelper.reparse removes Container ?! [message #912462 is a reply to message #911977] Thu, 13 September 2012 16:14 Go to previous messageGo to next message
Michael Vorburger is currently offline Michael VorburgerFriend
Messages: 103
Registered: July 2009
Senior Member
Sebastian,

Indeed peeking into AbstractOutlineNode was helpful - thank you very much.

I've started make changes to ch.vorburger.xtext.databinding (see latest commits to my GitHub project if interested), along the lines of not passing the EObject into observe() but IReadAccess<XtextResource>, and am starting to see stuff work better.

Am still struggling slightly with Notification - not 100% sure yet what's the best way, but hopefully I can sort that out.. If you have any advise on what the best way is to attach an EMF Adapter to the Resource of the XTextDocument, I'd be interested! Is something like this:

IReadAccess<XtextResource> access = ...;
return access.readOnly(new IUnitOfWork<Object, XtextResource>() {
@Override public Object exec(XtextResource state) throws Exception {
state.eAdapters().add(...);
}
);

fair game, or am I "returning any references to something contained in this
resource" by doing this?

BTW: If XtextDocument's ensureThatStateIsNotReturned would catch it instead of having a "TODO activate" and relevant code commented out, then may be people like me wouldn't waste your time on posting examples with // TODO This is wrong, but do it anyways? Wink Do you want a Bugzilla for that (Issue Summary: "XtextDocument should ensureThatStateIsNotReturned") ?

Thanks again.
Re: PartialParsingHelper.reparse removes Container ?! [message #915081 is a reply to message #912462] Sun, 16 September 2012 11:40 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Hi Michael,

the problem with 'ensureThatStateIsNotReturned' was that people thought
they are really smart and used thing like 'EObject[] { eObject }' or
'new MySmartWrapper(eObject)' thus we did not want to impose a rather
expensive and unsecure check for all clients.

Yes, it's save to add a content adapter or something to the resource.
That one will be notified in a read or write transaction anyway (as long
as no third party code modifies the resource's content).

Regards,
Sebastian
--
Looking for professional support for Xtext, Xtend or Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 13.09.12 18:14, schrieb Michael Vorburger:
> Sebastian,
>
> Indeed peeking into AbstractOutlineNode was helpful - thank you very much.
> I've started make changes to ch.vorburger.xtext.databinding (see latest
> commits to my GitHub project if interested), along the lines of not
> passing the EObject into observe() but IReadAccess<XtextResource>, and
> am starting to see stuff work better.
> Am still struggling slightly with Notification - not 100% sure yet
> what's the best way, but hopefully I can sort that out.. If you have any
> advise on what the best way is to attach an EMF Adapter to the Resource
> of the XTextDocument, I'd be interested! Is something like this:
>
> IReadAccess<XtextResource> access = ...;
> return access.readOnly(new IUnitOfWork<Object, XtextResource>() {
> @Override public Object exec(XtextResource state) throws Exception {
> state.eAdapters().add(...);
> }
> );
>
> fair game, or am I "returning any references to something contained in
> this resource" by doing this?
>
> BTW: If XtextDocument's ensureThatStateIsNotReturned would catch it
> instead of having a "TODO activate" and relevant code commented out,
> then may be people like me wouldn't waste your time on posting examples
> with // TODO This is wrong, but do it anyways? ;) Do you want a Bugzilla
> for that (Issue Summary: "XtextDocument should
> ensureThatStateIsNotReturned") ?
>
> Thanks again.
Re: PartialParsingHelper.reparse removes Container ?! [message #921683 is a reply to message #915081] Mon, 24 September 2012 10:36 Go to previous message
Michael Vorburger is currently offline Michael VorburgerFriend
Messages: 103
Registered: July 2009
Senior Member
Sebastien - thanks for your response. Just wanted to let you know that I made some progress on this front, but am now stuck (and getting lost..) in points which have a lot more to do with the Data Binding API internals than with Xtext - thus taking this to http://www.eclipse.org/forums/index.php/m/921679/#msg_921679.
Previous Topic:Referencing elements of a DSL from another DSL using XText 1.0.1
Next Topic:Unit testing validation errors
Goto Forum:
  


Current Time: Fri Apr 19 01:54:55 GMT 2024

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

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

Back to the top