JPA queries using instanceOf are not working with custom @DiscriminatorValue

1,341 views
Skip to first unread message

timowest

unread,
Sep 26, 2011, 2:03:32 PM9/26/11
to quer...@googlegroups.com
Hi Timo.
Performing a query using the instanceOf is not working.
It's generating the following:
alias.class = :a1, and a1 is the fully qualified name of the class.
However, the column contents is given by the @DiscriminatorValue annotation. The default value is the FQN, however, we use the same value as in an enum, so, it's a custom string value.
Querydsl should use that value on the instanceOf check.

Anyway, I saw that Querydsl is using the Hibernate-specific alias.class HQL property. Being a JPA query, it should use JPA 2's TYPE(alias) function. However, when I was testing and prepare a request for this (Querydsl using TYPE), I saw that Hibernate is not supporting passing bind parameters for these constructs. I've asked on the forum (https://forum.hibernate.org/viewtopic.php?f=1&t=1004637), as this seems unimplemented.

It would be nice if on the future Querydsl uses the TYPE for the instanceOf, specially to support other providers (I saw you're planning to test it using EclipseLink). This would, however, break Hibernate 3.5.1. Perhaps, on hibernate, doing the .class test, and other JPA providers, TYPE?

timowest

Ok, I will test this. Btw, which JPA provider are you using?

We are about halfway in supporting EclipseLink.

I just created a related issue : https://bugs.launchpad.net/querydsl/+bug/583234

luisfpg

> Ok, I will test this. Btw, which JPA provider are you using?

Hibernate 3.5.1.
It would work for me to just generate the alias.class = :param, however this is Hibernate-specific. Anyway, Hibernate is not supporting type(alias) = :param, according do my post on hibernate forum, as referred on the previous post.

timowest

I will release the fix tomorrow morning. It will probably Hibernate specific for now, since EclipseLink testing is still in progress.

topping

Hi guys, I know this is a really old post, but is this issue working with Hibernate 3.5.6? I am modifying a query with an additional where clause, i.e. ".where(client.instanceOf(Customer.class)" and client needs to be a specific type on a table with joined inheritance.

Thus far, I get the following exception in Hibernate:


java.lang.UnsupportedOperationException: At the moment this type is not the one actually used to map the discriminator.
at org.hibernate.persister.entity.DiscriminatorType.nullSafeSet(DiscriminatorType.java:111)
at org.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:67)
at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:571)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1632)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2449)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
at org.hibernate.loader.Loader.list(Loader.java:2187)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:310)
at $Proxy45.getResultList(Unknown Source)
at com.mysema.query.jpa.impl.AbstractJPAQuery.list(AbstractJPAQuery.java:180)

Am I doing something wrong or is there an issue?

Thanks, Brian

timowest

Can you provide more context on this problem?

topping

Sure!
Here's the query:

       JPAQuery query = JPAQuery(entityManager, JPQLTemplates.DEFAULT).from(QPartyRelationship.partyRelationship)
               
.join(QPartyRelationship.partyRelationship.type, QPartyRelationshipType.partyRelationshipType)
               
.join(QPartyRelationship.partyRelationship.clientPartyRole, client)
               
.join(QPartyRelationship.partyRelationship.supplierPartyRole, supplier)
               
.join(client.party, clientParty)
               
.join(supplier.party, supplierParty)
               
.where(client.instanceOf(Customer.class),
                       
QPartyRelationshipType.partyRelationshipType.name.eq("SYSTEM_CONTEXT_RELATION"),
                        supplierParty
.id.eq(command.getCurrentContext()));

Here's the classpath for this project:

[INFO] [dependency:tree {execution: default-cli}]
[INFO] net.mauswerks.pubsite:pubsite-domain:jar:1-SNAPSHOT
[INFO] +- com.vividsolutions:jts:jar:1.8:compile
[INFO] +- org.hibernate:hibernate-search:jar:3.3.0.Final:compile
[INFO] |  +- org.hibernate:hibernate-search-analyzers:jar:3.3.0.Final:compile
[INFO] |  |  \- org.apache.lucene:lucene-analyzers:jar:3.0.3:compile
[INFO] |  +- org.hibernate:hibernate-core:jar:3.6.0.Final:compile
[INFO] |  |  +- antlr:antlr:jar:2.7.7:compile (version managed from 2.7.6)
[INFO] |  |  +- commons-collections:commons-collections:jar:3.2.1:compile (version managed from 3.1)
[INFO] |  |  +- dom4j:dom4j:jar:1.6.1-osgi:compile (version managed from 1.6.1)
[INFO] |  |  \- javax.transaction:jta:jar:1.1:compile
[INFO] |  +- org.hibernate:hibernate-commons-annotations:jar:3.2.0.Final:compile
[INFO] |  +- org.apache.lucene:lucene-core:jar:3.0.3:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.6.1:compile
[INFO] +- com.mysema.querydsl:querydsl-jpa:jar:2.1.1:compile
[INFO] |  \- com.mysema.querydsl:querydsl-core:jar:2.1.1:compile
[INFO] |     +- net.sourceforge.collections:collections-generic:jar:4.01:compile
[INFO] |     +- commons-lang:commons-lang:jar:2.5:compile (version managed from 2.4)
[INFO] |     +- com.mysema.commons:mysema-commons-lang:jar:0.2.1:compile
[INFO] |     +- com.mysema.codegen:codegen:jar:0.3.1:compile
[INFO] |     +- net.sourceforge.findbugs:jsr305:jar:1.3.2:compile
[INFO] |     +- net.sourceforge.findbugs:annotations:jar:1.3.2:compile
[INFO] |     \- cglib:cglib:jar:2.2:compile
[INFO] +- com.mysema.querydsl:querydsl-apt:jar:2.1.1:provided
[INFO] +- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.0.Final:compile
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.6.1:compile
[INFO] |  \- log4j:log4j:jar:1.2.14:compile (version managed from 1.2.16)
[INFO] +- net.mauswerks.pubsite:pubsite-message:jar:1-SNAPSHOT:compile
[INFO] |  +- net.mauswerks.pubsite:pubsite-security:jar:1-SNAPSHOT:compile
[INFO] |  |  +- org.springframework.security:spring-security-core:jar:3.0.5.RELEASE:compile
[INFO] |  |  |  +- org.aspectj:aspectjrt:jar:1.6.8:compile
[INFO] |  |  |  \- org.aspectj:aspectjweaver:jar:1.6.8:compile
[INFO] |  |  +- org.springframework.security:spring-security-ldap:jar:3.0.5.RELEASE:compile
[INFO] |  |  |  \- org.springframework.ldap:spring-ldap-core:jar:1.3.0.RELEASE:compile
[INFO] |  |  +- org.springframework.security:spring-security-config:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-expression:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-core:jar:3.0.5.RELEASE:compile
[INFO] |  |  |  \- org.springframework:spring-asm:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-context:jar:3.0.5.RELEASE:compile
[INFO] |  |  |  \- org.springframework:spring-beans:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-tx:jar:3.0.5.RELEASE:compile
[INFO] |  |  |  \- aopalliance:aopalliance:jar:1.0:compile
[INFO] |  |  +- org.springframework:spring-aop:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- org.mule.modules:mule-module-spring-security:jar:3.1.1:compile
[INFO] |  |  |  +- org.mule.modules:mule-module-spring-config:jar:3.1.1:compile
[INFO] |  |  |  |  +- org.mule.modules:mule-module-annotations:jar:3.1.1:compile
[INFO] |  |  |  |  |  \- cglib:cglib-nodep:jar:2.2:compile
[INFO] |  |  |  |  \- jaxen:jaxen:jar:1.1.1-osgi:compile (version managed from 1.1.1)
[INFO] |  |  |  |     \- jdom:jdom:jar:1.0:compile
[INFO] |  |  |  +- org.mule.transports:mule-transport-http:jar:3.1.1:compile
[INFO] |  |  |  |  +- org.mule.transports:mule-transport-ssl:jar:3.1.1:compile
[INFO] |  |  |  |  \- tomcat:tomcat-util:jar:5.5.23:compile
[INFO] |  |  |  |     \- tomcat:tomcat-apr:jar:5.5.23:compile
[INFO] |  |  |  +- org.mule.transports:mule-transport-tcp:jar:3.1.1:compile
[INFO] |  |  |  +- org.mule.modules:mule-module-spring-extras:jar:3.1.1:compile
[INFO] |  |  |  |  +- org.springframework:spring-web:jar:3.0.5.RELEASE:compile (version managed from 3.0.3.RELEASE)
[INFO] |  |  |  |  +- org.mule.modules:mule-module-builders:jar:3.1.1:compile
[INFO] |  |  |  |  +- org.mule.modules:mule-module-management:jar:3.1.1:compile
[INFO] |  |  |  |  |  +- org.mule.modules:mule-module-xml:jar:3.1.1:compile
[INFO] |  |  |  |  |  |  +- org.apache.geronimo.specs:geronimo-stax-api_1.0_spec:jar:1.0.1:compile
[INFO] |  |  |  |  |  |  +- commons-jxpath:commons-jxpath:jar:1.3-osgi:compile
[INFO] |  |  |  |  |  |  +- com.thoughtworks.xstream:xstream:jar:1.2.2-osgi:compile
[INFO] |  |  |  |  |  |  +- joda-time:joda-time:jar:1.6.2:compile (version managed from 1.6)
[INFO] |  |  |  |  |  |  +- xpp3:xpp3_min:jar:1.1.3.4.O-osgi:compile
[INFO] |  |  |  |  |  |  +- org.codehaus.woodstox:woodstox-core-asl:jar:4.0.8:compile
[INFO] |  |  |  |  |  |  |  \- org.codehaus.woodstox:stax2-api:jar:3.0.2:compile
[INFO] |  |  |  |  |  |  +- net.java.dev.stax-utils:stax-utils:jar:20080702-osgi:compile
[INFO] |  |  |  |  |  |  +- net.sf.saxon:saxon:jar:8.9.0.4-osgi:compile
[INFO] |  |  |  |  |  |  +- net.sf.saxon:saxon-dom:jar:8.9.0.4-osgi:compile
[INFO] |  |  |  |  |  |  +- net.sf.saxon:saxon-xqj:jar:8.9.0.4:compile
[INFO] |  |  |  |  |  |  +- javax.xml.bind:jaxb-api:jar:2.1:compile
[INFO] |  |  |  |  |  |  \- com.sun.xml.bind:jaxb-impl:jar:2.1.9-osgi:runtime (version managed from 2.1.5)
[INFO] |  |  |  |  |  +- mx4j:mx4j-jmx:jar:2.1.1-osgi:compile
[INFO] |  |  |  |  |  +- mx4j:mx4j-impl:jar:2.1.1-osgi:compile
[INFO] |  |  |  |  |  +- mx4j:mx4j-tools:jar:2.1.1-osgi:compile
[INFO] |  |  |  |  |  +- mx4j:mx4j-remote:jar:2.1.1-osgi:compile
[INFO] |  |  |  |  |  +- com.yourkit:yjp-controller-api-redist:jar:9.0.8:compile
[INFO] |  |  |  |  |  \- tanukisoft:wrapper:jar:3.2.3:compile
[INFO] |  |  |  |  \- org.apache.geronimo.specs:geronimo-jms_1.1_spec:jar:1.1-osgi:compile
[INFO] |  |  |  \- org.springframework.security:spring-security-web:jar:3.0.5.RELEASE:compile (version managed from 3.0.3.RELEASE)
[INFO] |  |  +- org.springframework:spring-jdbc:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-jms:jar:3.0.5.RELEASE:compile
[INFO] |  |  +- commons-httpclient:commons-httpclient:jar:3.1-osgi:compile
[INFO] |  |  |  \- commons-codec:commons-codec:jar:1.3-osgi:compile
[INFO] |  |  +- org.springframework.security.oauth:spring-security-oauth:jar:1.0.0.M2:compile
[INFO] |  |  +- org.openid4java:openid4java-consumer:jar:0.9.5:compile
[INFO] |  |  |  +- org.openid4java:openid4java-nodeps:jar:0.9.5:compile
[INFO] |  |  |  \- net.sourceforge.nekohtml:nekohtml:jar:1.9.7:compile
[INFO] |  |  |     \- xerces:xercesImpl:jar:2.9.1:compile (version managed from 2.8.1)
[INFO] |  |  |        \- xml-apis:xml-apis:jar:1.3.04:compile
[INFO] |  |  +- org.apache.directory.server:apacheds-core:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-xdbm-search:jar:1.5.5:compile
[INFO] |  |  |  |  \- org.apache.directory.server:apacheds-schema-extras:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-xdbm-tools:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-schema-bootstrap:jar:1.5.5:compile
[INFO] |  |  |  |  \- org.apache.directory.server:apacheds-jdbm:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-core-entry:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-schema-registries:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-core-shared:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-core-constants:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-utils:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-jdbm-store:jar:1.5.5:compile
[INFO] |  |  |  |  \- org.apache.directory.server:apacheds-core-avl:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-xdbm-base:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.server:apacheds-bootstrap-extract:jar:1.5.5:compile
[INFO] |  |  |  +- org.apache.directory.shared:shared-cursor:jar:0.9.15:compile
[INFO] |  |  |  +- bouncycastle:bcprov-jdk15:jar:140:compile
[INFO] |  |  |  \- org.apache.directory.shared:shared-ldap:jar:0.9.15:compile
[INFO] |  |  |     +- org.apache.directory.shared:shared-asn1:jar:0.9.15:compile
[INFO] |  |  |     \- org.apache.directory.shared:shared-ldap-constants:jar:0.9.15:compile
[INFO] |  |  \- org.apache.directory.server:apacheds-server-jndi:jar:1.5.5:compile
[INFO] |  |     +- org.apache.directory.server:apacheds-protocol-ldap:jar:1.5.5:compile
[INFO] |  |     |  +- org.apache.directory.shared:shared-asn1-codec:jar:0.9.15:compile
[INFO] |  |     |  |  \- org.apache.mina:mina-core:jar:2.0.0-M6:compile
[INFO] |  |     |  +- org.apache.directory.server:apacheds-kerberos-shared:jar:1.5.5:compile
[INFO] |  |     |  +- org.apache.directory.server:apacheds-bootstrap-partition:jar:1.5.5:compile
[INFO] |  |     |  \- org.apache.directory.server:apacheds-protocol-shared:jar:1.5.5:compile
[INFO] |  |     \- org.apache.directory.server:apacheds-core-jndi:jar:1.5.5:compile
[INFO] |  \- org.mule:mule-core:jar:3.1.1:compile
[INFO] |     +- org.safehaus.jug:jug:jar:asl:2.0.0:compile
[INFO] |     +- backport-util-concurrent:backport-util-concurrent:jar:3.1-osgi:compile
[INFO] |     +- commons-cli:commons-cli:jar:1.2:compile
[INFO] |     +- commons-io:commons-io:jar:1.4:compile
[INFO] |     +- commons-pool:commons-pool:jar:1.5.5:compile (version managed from 1.5.3)
[INFO] |     +- javax.activation:activation:jar:1.1-osgi:compile
[INFO] |     +- org.apache.geronimo.specs:geronimo-jta_1.0.1B_spec:jar:1.1-osgi:compile
[INFO] |     +- org.apache.geronimo.specs:geronimo-j2ee-connector_1.5_spec:jar:1.1-osgi:compile
[INFO] |     +- javax.annotation:jsr250-api:jar:1.0:compile
[INFO] |     +- org.slf4j:jcl-over-slf4j:jar:1.6.1:compile
[INFO] |     +- asm:asm:jar:3.1:compile
[INFO] |     +- asm:asm-commons:jar:3.1:compile
[INFO] |     |  \- asm:asm-tree:jar:3.1:compile
[INFO] |     \- junit:junit:jar:4.8.1:test (scope managed from compile)
[INFO] +- commons-beanutils:commons-beanutils:jar:1.8.3:compile
[INFO] |  \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] \- postgresql:postgresql:jar:8.4-701.jdbc4:compile

When the query is run, I get the following exception:

java.lang.UnsupportedOperationException: At the moment this type is not the one actually used to map the discriminator.
        at org
.hibernate.persister.entity.DiscriminatorType.nullSafeSet(DiscriminatorType.java:111)
        at org
.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:67)
        at org
.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:571)
        at org
.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1716)
        at org
.hibernate.loader.Loader.doQuery(Loader.java:801)
        at org
.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
        at org
.hibernate.loader.Loader.doList(Loader.java:2533)
        at org
.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
        at org
.hibernate.loader.Loader.list(Loader.java:2271)
        at org
.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
        at org
.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
        at org
.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
        at org
.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
        at org
.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
        at org
.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:246)
        at sun
.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun
.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun
.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at org
.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:310)
        at $Proxy45
.getResultList(Unknown Source)
        at com
.mysema.query.jpa.impl.AbstractJPAQuery.list(AbstractJPAQuery.java:180)
        at net
.mauswerks.pubsite.core.service.impl.AccountServiceImpl.doQuery(AccountServiceImpl.java:227)
        at net
.mauswerks.pubsite.core.service.impl.AccountServiceImpl.dispatch(AccountServiceImpl.java:190)
        at sun
.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun
.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun
.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at org
.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
        at org
.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196)
        at $Proxy46
.dispatch(Unknown Source)
        at net
.mauswerks.pubsite.core.service.impl.AccountServiceImplTest.testAccountListQuery(AccountServiceIm
plTest
.java:67)
        at sun
.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun
.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun
.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at org
.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)

The statement that Hibernate thinks it is working on is:

select party4_.id as id24_, party4_.description as descript2_24_, party4_.name as name24_, party4_.partyIdentifier_id as partyIde4_24_, party4_1_.gender as gender25_, party4_1_.personName_id as personName3_25_, party4_3_.orgName_id as orgName2_47_, case when party4_4_.id is not null then 4 when party4_1_.id is not null then 1 when party4_2_.id is not null then 2 when party4_3_.id is not null then 3 when party4_.id is not null then 0 end as clazz_ from PartyRelationship partyrelat0_ inner join PartyRelationshipType partyrelat1_ on partyrelat0_.type_id=partyrelat1_.id inner join PartyRole partyrole2_ on partyrelat0_.clientPartyRole_id=partyrole2_.id inner join Party party4_ on partyrole2_.party_id=party4_.id left outer join Person party4_1_ on party4_.id=party4_1_.id left outer join HostingContext party4_2_ on party4_.id=party4_2_.id left outer join Organization party4_3_ on party4_.id=party4_3_.id left outer join Company party4_4_ on party4_.id=party4_4_.id inner join PartyRole partyrole3_ on partyrelat0_.supplierPartyRole_id=partyrole3_.id inner join Party party5_ on partyrole3_.party_id=party5_.id where partyrole2_.DTYPE=? and partyrelat1_.name=? and party5_.id=?

It dies working on the first parameter, which (correctly) is DTYPE (I am using default discriminator values). I don't understand the Hibernate code that well or why it's calling DiscriminatorValue.nullSafeSet(), which simply throws the exception.

timowest

Sorry for the late answer.

It looks the problem is the way you construct your query, for Hibernate create it in one of the following ways

new JPAQuery(entityManager

or
new JPAQuery(entityManager, HQLTemplates.DEFAULT)


If you use JPQLTemplates.DEFAULT, the DiscriminatorValue handling doesn't work, since the Hibernate fix is non-standard JPQL.

If this doesn't fix it could you provide the JPQL/HQL query? You can get it logged by enabling the following log4j loggers


log4j
.logger.com.mysema.query.jpa.impl=DEBUG



Reply all
Reply to author
Forward
0 new messages