Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EMF-IncQuery » Reflective IncQueryEngine
Reflective IncQueryEngine [message #1074634] Sat, 27 July 2013 09:36 Go to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi everyone,

I'm trying to set up a IncQueryEngine to work reflectively using a globalEiqModel.xmi and a target model only (no generated code), but without much success. To demonstrate the problem, in the linked project [1], I've deleted src-gen and the related extensions in plugin.xml and disabled the IncQuery and Xtext builders so that they are not regenerated automatically. Running PluggedInTest as a plugged-in test when src-gen is not around throws an exception; if I enable the builder everything works well. I've tried to see how QueryExplorer does it but haven't had much luck. Any thoughts would be really appreciated.

Cheers,
Dimitris

[1] https://dl.dropboxusercontent.com/u/5636547/org.eclipse.epsilon.emc.incquery.demo.zip
Re: Reflective IncQueryEngine [message #1074639 is a reply to message #1074634] Sat, 27 July 2013 09:53 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan Ujhelyi
Messages: 221
Registered: July 2009
Senior Member
Hi Dimitris,

we do have a Generic Pattern Matcher feature that can be initialized using an IncQuery pattern. The Query Explorer uses the IncQueryEngine#getMatcher(Pattern) method to initialize such matchers in the ObservablePatternMatcherRoot#addMatchersForPatterns method. This method has the added benefit that it checks whether a generated matcher is available, and returns that if possible, or simply initializes a new generic matcher.

I hope this helps, if not, feel free to ask for clarification.

Cheers,
Zoltán
Re: Reflective IncQueryEngine [message #1074643 is a reply to message #1074639] Sat, 27 July 2013 10:09 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Zoltán,

Thanks for your quick reply! As advised, I've replaced the following lines of code in my plugged in test

IQuerySpecification<? extends IncQueryMatcher<? extends IPatternMatch>> querySpecification
= QuerySpecificationRegistry.getOrCreateQuerySpecification(patternModel.getPatterns().get(0));

System.err.println(querySpecification.getMatcher(engine).getAllMatches().size());

with this one

System.err.println(engine.getMatcher(patternModel.getPatterns().get(0)).getAllMatches().size());

but I'm now getting a different NPE:

java.lang.NullPointerException
at org.eclipse.xtext.common.types.util.JavaReflectAccess.getRawType(JavaReflectAccess.java:107)
at org.eclipse.xtext.common.types.util.JavaReflectAccess.getMethod(JavaReflectAccess.java:73)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:920)
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeOperation(XbaseInterpreter.java:916)

Any thoughts?

Cheers,
Dimitris
Re: Reflective IncQueryEngine [message #1074732 is a reply to message #1074643] Sat, 27 July 2013 15:39 Go to previous messageGo to next message
Istvan Rath is currently offline Istvan Rath
Messages: 54
Registered: July 2009
Member
Hi Dimitris,

our documentation has some details and example code on getting the reflective query invocation API to work, at http://wiki.eclipse.org/EMFIncQuery/UserDocumentation/API/Advanced . If you have some time, could you verify that these techniques work/do not work for you? (In case they don't work, I'll check and correct the docs.)

As for the NPE, unfortunately it seems to come from the Xbase interpreter. As this is an external component w.r.t. our codebase, it would help a lot if you could specify exactly which version of Xtext and IncQuery you are using.

Finally, two important remarks:
- running patterns with check expressions in interpreted mode is much slower than the compiled mode, so for performance benchmarks the compiled version is definitely recommended. (This only applies to check expressions, though.)
- I have looked into your example code:
pattern EXX() {
 nr == count find ECWA()
 check (nr > 1)
}

can be replaced by the much more performant
pattern EXX() {
 find ECWA()
}

as a find implies that it has to have at least one match (which is semantically equivalent to your formulation).



HTH, cheers
Istvan
Re: Reflective IncQueryEngine [message #1074765 is a reply to message #1074732] Sat, 27 July 2013 18:08 Go to previous messageGo to next message
Joost van Pinxten is currently offline Joost van Pinxten
Messages: 50
Registered: November 2012
Member
Hi Istvan,

Istvan Rath wrote on Sat, 27 July 2013 11:39
Hi Dimitris,

our documentation has some details and example code on getting the reflective query invocation API to work, at http://wiki.eclipse.org/EMFIncQuery/UserDocumentation/API/Advanced . If you have some time, could you verify that these techniques work/do not work for you? (In case they don't work, I'll check and correct the docs.)

Thanks for this information; we have indeed been looking at the advanced standalone usage of the IncQuery engine. We will have another go, hopefully next week.

Istvan Rath wrote on Sat, 27 July 2013 11:39

As for the NPE, unfortunately it seems to come from the Xbase interpreter. As this is an external component w.r.t. our codebase, it would help a lot if you could specify exactly which version of Xtext and IncQuery you are using.


It seems that the Xbase interpreter is not correctly injected, which might have to do with the environment that we're instantiating the IQ Engine in. Although I don't know the exact version right now, we were running this example in Kepler, so most probably the Xtext version was 2.4.2. We were using the stable 0.7.0 release of IncQuery.

Istvan Rath wrote on Sat, 27 July 2013 11:39

Finally, two important remarks:
- running patterns with check expressions in interpreted mode is much slower than the compiled mode, so for performance benchmarks the compiled version is definitely recommended. (This only applies to check expressions, though.)
- I have looked into your example code:
pattern EXX() {
 nr == count find ECWA()
 check (nr > 1)
}

can be replaced by the much more performant
pattern EXX() {
 find ECWA()
}

as a find implies that it has to have at least one match (which is semantically equivalent to your formulation).



HTH, cheers
Istvan


This is not equivalent! Your 'find'-example is equivalent to:
pattern EXX() {
 nr == count find ECWA();
 check (nr >= 1); // notice the greater-equal here
}

In our simple pattern, we have chosen that we need more than one occurrence before we want to match.

Cheers, thanks for looking into it and pointing out the possible performance issues.
Joost

[Updated on: Sat, 27 July 2013 18:09]

Report message to a moderator

Re: Reflective IncQueryEngine [message #1074780 is a reply to message #1074765] Sat, 27 July 2013 19:10 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Istvan,

Thanks for your reply. I suspect that the versions of Xtext and Xbase (both 2.4.2) we're using is not the problem as the QueryExplorer (which I assume also works in a reflective manner) works fine for this example. We did use [1] as our starting point but without much success I'm afraid. Does the plugged-in test [2] work as expected in your setup?

Cheers,
Dimitris

[1] http://wiki.eclipse.org/EMFIncQuery/UserDocumentation/API/Advanced
[2] https://dl.dropboxusercontent.com/u/5636547/org.eclipse.epsilon.emc.incquery.demo.zip
Re: Reflective IncQueryEngine [message #1074787 is a reply to message #1074780] Sat, 27 July 2013 19:38 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan Ujhelyi
Messages: 221
Registered: July 2009
Senior Member
Hi,

I had some time to experiment with your project, and now I know why it is not working, and can provide workarounds (but sadly, no real solution).

The problem is that our code that copies the patterns into the globaleiqmodel file, does not copy well the check expressions. For the generated code, it does not matter, as the compiled expressions are registered using the org.eclipse.incquery.runtime.xexpressionevaluator extension point that our runtime finds. When you are turning off all generated code, this compiled Xbase expressions are not found, so the system tries to parse the (incorrect) check expressions.

What might work as workaround:
* Do not turn off the code generation, or at least provide the expressionevaluator. In this case, you can still instantiate the generic matcher.
* You can try to parse the original .eiq file. Sadly because of a late change in Xtext 2.4 we had to provide a quick and hacky solution for the IncQuery parsing, which means, you need to have GUI dependencies to parse the eiq files with check expressions, which is most likely not what you want. If you are interested in that solution, check the test setup of our patternlanguage test project (http://git.eclipse.org/c/incquery/org.eclipse.incquery.git/tree/tests/org.eclipse.incquery.patternlanguage.emf.tests).

However, my real question is, what are you trying to achieve with this interesting setup? If possible, I would be glad to offer a more stable alternative.

Cheers,
Zoltán
Re: Reflective IncQueryEngine [message #1074791 is a reply to message #1074787] Sat, 27 July 2013 19:51 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Zoltán,

Thanks for looking into this. GUI dependencies are not a blocker at these stage so we'll try the second solution. We're trying to build a driver for Epsilon [1] that will enable languages of the platform to consume the results of IncQuery pattern matching so that identified matches can be used in further model management operations (e.g. model-to-text/model-to-model transformation etc).

Cheers,
Dimitris

[1] http://eclipse.org/epsilon/
Re: Reflective IncQueryEngine [message #1074792 is a reply to message #1074791] Sat, 27 July 2013 19:53 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan Ujhelyi
Messages: 221
Registered: July 2009
Senior Member
Hi,

for that goal, I do not see why the generated matchers cannot be used (especially that you do have the eiq files and IncQuery projects available). That is a more stable and tested solution.

I would strongly recommend staying on that road.

Cheers,
Zoltán
Re: Reflective IncQueryEngine [message #1074795 is a reply to message #1074792] Sat, 27 July 2013 20:04 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Zoltán,

We'd prefer to also provide support for using IncQuery in a reflective mode - if possible - so that users don't have to keep launching new Eclipse instances during development.

Cheers,
Dimitris
Re: Reflective IncQueryEngine [message #1074797 is a reply to message #1074795] Sat, 27 July 2013 20:07 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan Ujhelyi
Messages: 221
Registered: July 2009
Senior Member
Hi,

in this case you are right, clearly this eiq parsing way seems the most promising. If the IncQuery SDK is installed, then (if I remember correctly) it should register everything required to simply open the eiq files the same way you have opened the xmi model. However, for headless execution, you need to help it.

Cheers,
Zoltán
Re: Reflective IncQueryEngine [message #1075365 is a reply to message #1074765] Mon, 29 July 2013 10:00 Go to previous messageGo to next message
Istvan Rath is currently offline Istvan Rath
Messages: 54
Registered: July 2009
Member
Hi guys,


Quote:
This is not equivalent! Your 'find'-example is equivalent to:
pattern EXX() {
nr == count find ECWA();
check (nr >= 1); // notice the greater-equal here
}

In our simple pattern, we have chosen that we need more than one occurrence before we want to match.


True! I have overlooked that detail. Anyway, your pattern could be expressed as

pattern EXX() {
 find ECWA(A);
 find ECWA(B);
 A != B;
}


which will likely yield better performance than the check()-based variant. (This depends on some other factors such as the composition of your instance model and the number of matches ECWA() actually has, but it might be worth a look if you are optimizing for performance.)

Another similar trick could be to omit the IsInEcore() construct entirely, and restrict the matching scope to the resource of your instance model (instead of the entire resourceset) - this would make this "manual" filtering for Ecore elements (which, I presume, are in a different resource than your instance model) unnecessary.

Quote:
I suspect that the versions of Xtext and Xbase (both 2.4.2) we're using is not the problem as the QueryExplorer (which I assume also works in a reflective manner) works fine for this example. We did use [1] as our starting point but without much success I'm afraid.


As Zoltan wrote, the source of the issue is in our tooling, namely that the serialization of Xbase expressions to globalEiqModel.xmi is not correct. As the Query Explorer does not use this, but parses and loads the .eiq resources directly through Xtext, it is not affected by the issue. I will extend the headless example and its corresponding wiki page [1] to illustrate how this should be done from Java code, which will hopefully help you to resolve the issue.

Istvan
Re: Reflective IncQueryEngine [message #1076123 is a reply to message #1075365] Tue, 30 July 2013 18:54 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Istvan,

That'd be great - thanks! Please let us know when you've updated the wiki so that we can give it another go.

Cheers,
Dimitris
Re: Reflective IncQueryEngine [message #1076416 is a reply to message #1076123] Wed, 31 July 2013 11:10 Go to previous messageGo to next message
Jan Reimann is currently offline Jan Reimann
Messages: 127
Registered: July 2009
Senior Member
Hi Dimitris,
it seems that I have a similar problem: it works with the QueryExplorer
but it doesn't while testing. Maybe you want to have a look at the other
thread. At
http://www.eclipse.org/forums/index.php/mv/msg/465369/1075321/#msg_1075321
you'll find my test project attached. At least I can load the pattern
model but don't get expected results in contrast to the results I get
from QueryExplorer.

best regards,
Jan
Re: Reflective IncQueryEngine [message #1076421 is a reply to message #1076416] Wed, 31 July 2013 11:25 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Jan,

Thanks for the heads up! I'll have a look at your project when I pick this up again and let you know how it goes.

Cheers,
Dimitris
Re: Reflective IncQueryEngine [message #1076441 is a reply to message #1076123] Wed, 31 July 2013 12:04 Go to previous messageGo to next message
Istvan Rath is currently offline Istvan Rath
Messages: 54
Registered: July 2009
Member
Hi guys,

I have some good news. http://wiki.eclipse.org/EMFIncQuery/UserDocumentation/API/Advanced#Loading_EIQ_resources_programmatically now shows a technique that works on my setup, the most important part is
// Xtext resource magic -- this is needed for EIQs
new EMFPatternLanguageStandaloneSetup()
{
 @Override
 public Injector createInjector() {
  return Guice.createInjector(new GeneratorModule());
 }
}.createInjectorAndDoEMFRegistration();
// use a trick to load Pattern models from a file
ResourceSet resourceSet = new ResourceSetImpl();
URI fileURI = URI.createPlatformResourceURI("test/src/test/test.eiq", false);
Resource patternResource = resourceSet.getResource(fileURI, true);


As Zoltan has predicted before, this code (through GeneratorModule) brings in some UI dependencies, which you'll have to live with until we resolve (the newly created) https://bugs.eclipse.org/bugs/show_bug.cgi?id=414121

Another issue to take into consideration is that in EIQs loaded like this, there seem to be some minor differences (e.g. FQNs vs names, see the bug above for details) which have to be taken into consideration depending on what you want to do with your Pattern instances. (Pattern matching with IncQuery works just fine.)

I have also fixed another bug that involved the XBase interpreter, so I recommend to try this technique on a recent CI build of IncQuery. (It should also get into the integration builds soon.)

Let me know if this helps,
cheers
Istvan
Re: Reflective IncQueryEngine [message #1077819 is a reply to message #1076441] Fri, 02 August 2013 07:28 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Istvan,

Thanks! I've tried this with the latest CI build and it works fine. The only glitch is that I'm getting a few error markers on my .eiq file which I don't understand and which don't seem to be affecting the runtime behaviour (see linked screenshot). Any thoughts?

Cheers,
Dimitris

https://dl.dropboxusercontent.com/u/5636547/shared/incqueryerrormarkers.png
Re: Reflective IncQueryEngine [message #1077824 is a reply to message #1077819] Fri, 02 August 2013 07:36 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan Ujhelyi
Messages: 221
Registered: July 2009
Senior Member
Hi Dimitris,

it seems to me that these messages remain there incorrectly. Can you try to delete the markers (in the Problems view) and then try to recompile the queries?

Cheers,
Zoltán
Re: Reflective IncQueryEngine [message #1077828 is a reply to message #1077824] Fri, 02 August 2013 07:41 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Zoltán,

I've tried cleaning the project / deleting the markers manually but they seem to be regenerated.

Cheers,
Dimitris
Re: Reflective IncQueryEngine [message #1077866 is a reply to message #1077828] Fri, 02 August 2013 08:44 Go to previous messageGo to next message
Istvan Rath is currently offline Istvan Rath
Messages: 54
Registered: July 2009
Member
Hi Dimitris,

I have taken an in-depth look at your project and found that your project's setup was rather weird (when looking into the .project file). How did you create it?

Anyway, if you fix the .project file to contain something like this:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>org.eclipse.epsilon.emc.incquery.demo</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>org.eclipse.incquery.tooling.core.projectbuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.jdt.core.javabuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.pde.ManifestBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.pde.SchemaBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>org.eclipse.pde.PluginNature</nature>
		<nature>org.eclipse.jdt.core.javanature</nature>
		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
		<nature>org.eclipse.incquery.projectnature</nature>
	</natures>
</projectDescription>


Then the IncQuery builder will run correctly (it is possible, that the src-gen folder needs to be created manually), and your error markers should disappear. In general, it is a good idea to make sure that the IncQuery builder runs succcessfully on your project (even if you don't intend to use the generated code at all).
Re: Reflective IncQueryEngine [message #1080681 is a reply to message #1077866] Tue, 06 August 2013 08:52 Go to previous messageGo to next message
Dimitris Kolovos is currently offline Dimitris Kolovos
Messages: 880
Registered: July 2009
Senior Member
Hi Istvan,

Thanks for looking into this! I turned on/off the IncQuery and Xtext builders a couple of times but that was about it, I think. In any event, the error has now disappeared so we can move forward with this.

Cheers,
Dimitris
Re: Reflective IncQueryEngine [message #1083627 is a reply to message #1080681] Sat, 10 August 2013 07:36 Go to previous messageGo to next message
Istvan Rath is currently offline Istvan Rath
Messages: 54
Registered: July 2009
Member
Good news. For future reference, if you encounter issues that are suspiciously related to the IncQuery buikder, it is worth first taking a look into the .project as "weird" .project contents (caused by e.g. Creating a project with an old and buggy version of the IncQuery tooling) can cause very nasty and hard to reproduce buga even with the newest IncQuery installed.
Re: Reflective IncQueryEngine [message #1115945 is a reply to message #1083627] Tue, 24 September 2013 20:04 Go to previous messageGo to next message
Joost van Pinxten is currently offline Joost van Pinxten
Messages: 50
Registered: November 2012
Member
Good evening all,

I've had some time to work on this again and I've fiddled around a bit with the examples. At first I could not make Dimitris' PluggedInTest work as the IncQueryHeadlessAdvanced#executeDemo_GenericAPI_LoadFromEIQ method (it's throwing me "java.lang.Override is not on the classpath" exceptions while instantiating the JVMInferredTypes). Even though I could run that advanced headless example (after modifying the data dependencies to my own).

However, after that, I have been able to simply run the code [1] that Dimitris and I had written (slightly modified by Dimitris through your examples). This means that the pattern definitions and corresponding matchers from IncQuery (at least for the current v0.8.0) can now be used as a part of Epsilon!

Thanks for the great support! We'll let you know when there is some more progress towards a more robust version of this integration Smile

Cheers!
Joost

[1] https://code.google.com/p/epsilonlabs/source/browse/#svn%2Ftrunk%2Forg.eclipse.epsilon.emc.incquery

[Updated on: Tue, 24 September 2013 20:12]

Report message to a moderator

Re: Reflective IncQueryEngine [message #1116293 is a reply to message #1115945] Wed, 25 September 2013 07:49 Go to previous messageGo to next message
Istvan Rath is currently offline Istvan Rath
Messages: 54
Registered: July 2009
Member
Hi Joost,

thanks for the update and the good news. Is there any tutorial on how exactly this Epsilon-IncQuery integration can be used? (And what it is useful for?)

cheers
Istvan
Re: Reflective IncQueryEngine [message #1116307 is a reply to message #1116293] Wed, 25 September 2013 08:11 Go to previous messageGo to next message
Joost van Pinxten is currently offline Joost van Pinxten
Messages: 50
Registered: November 2012
Member
Good morning Istvan,

There is no such documentation or tutorial yet, but the functionality would be comparable (i.e. an alternative) to what the Epsilon Pattern Language [1] (chapter 11) offers.

As for as a tutorial, if you'd want to try it out, use an Eclipse with IQ 0.8.0.201309231452 and Epsilon (+ Epsilon EMF integration) 1.1.0.201309221936. Then simply checkout the org.eclipse.epsilon.emc.incquery and org.eclipse.epsilon.emc.incquery.demo projects from the EpsilonLabs repo [2]. Open the .incquery project and run a new Eclipse instance; open the .incquery.demo project and run the test.launch (or the test.eol manually). This should show a single match in the console: (i.e. "Match found: C1").

The only thing necessary to use an existing IncQuery project is the place of the pattern file (.eiq) and the model to execute the patterns on; they are then automatically available in any EOL script. As Epsilon already supports many interesting stuff for EMF classes, most functionality was almost automatically available for IncQuery matches!

One of the idea's we've had, is to be able to bind the Epsilon operations onto the appearance/disappearance of pattern matches (through for example the EVM), such that Epsilon can benefit from the incremental approach of the IncQuery matching engine. However, this is quite a bit more involved and, unfortunately, we can't spend a lot of time on this integration at the moment.

Cheers,
Joost

[1] http://eclipse.org/epsilon/doc/book/
[2] http://code.google.com/p/epsilonlabs/

[Updated on: Wed, 25 September 2013 09:16]

Report message to a moderator

Re: Reflective IncQueryEngine [message #1243920 is a reply to message #1074634] Tue, 11 February 2014 16:45 Go to previous message
Zoltan Ujhelyi is currently offline Zoltan Ujhelyi
Messages: 221
Registered: July 2009
Senior Member
Hi all,

today I have finally outlined how the generic API (and the eiq file loading) will work in IncQuery 0.8.

Basically, there is no need for the UI dependencies anymore, and the hack István found is also not required.

On the other hand, the structure of IncQuery projects changed very much: there is no more globaleiqmodel.xmi version of the patterns (at all), and the generated code is much different, so a migration step is needed for version 0.8 (see https://wiki.eclipse.org/EMFIncQuery/Releases/MigrateTo0.8).

On the other hand, as seen in https://wiki.eclipse.org/EMFIncQuery/UserDocumentation/API/Advanced#Initializing_matchers_and_accessing_results it is possible to load eiq files without any problems.

We plan to release an integration build containing this new features this week, and a milestone build for the 1st of March.

If you have any questions, or suggestions about this approach, we will try our best to answer them.

Cheers,
Zoltán
Previous Topic:setSelectionToViewer NoSuchMethod exception
Next Topic:Is it possible to use incquery in Standalone EMF?
Goto Forum:
  


Current Time: Tue Oct 21 10:24:39 GMT 2014

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

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