HHH-3351 : import envers as core module
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15406 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
e163f8264d
commit
78e5d9fd89
|
@ -0,0 +1,235 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-parent</artifactId>
|
||||
<version>3.4.0-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-envers</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Hibernate Envers</name>
|
||||
<description>Support for entity historizing</description>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
</systemProperties>
|
||||
<suiteXmlFiles>
|
||||
<suiteXmlFile>resources/test/testng.xml</suiteXmlFile>
|
||||
</suiteXmlFiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- javadocs : we want these run in the 'package' lifecycle phase-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>javadoc</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<aggregate>${jbossenvers.reports.aggregate}</aggregate>
|
||||
<links>
|
||||
<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
|
||||
<link>http://java.sun.com/javaee/5/docs/api/</link>
|
||||
</links>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-annotations</artifactId>
|
||||
<exclusions>
|
||||
<!-- todo : only needed until we migrate annotations/em back to core -->
|
||||
<exclusion>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm-attrs</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-commons-annotations</artifactId>
|
||||
<exclusions>
|
||||
<!-- todo : only needed until we migrate annotations/em back to core -->
|
||||
<exclusion>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm-attrs</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<exclusions>
|
||||
<!-- todo : only needed until we migrate annotations/em back to core -->
|
||||
<exclusion>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm-attrs</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-tools</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>5.8</version>
|
||||
<scope>test</scope>
|
||||
<classifier>jdk15</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<!-- todo : change to work like hibernate-core after we import annotations and em back into core -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-annotations</artifactId>
|
||||
<version>3.3.0.ga</version>
|
||||
</dependency>
|
||||
<!-- todo : change to work like hibernate-core after we import annotations and em back into core -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-commons-annotations</artifactId>
|
||||
<version>3.3.0.ga</version>
|
||||
</dependency>
|
||||
<!-- todo : change to work like hibernate-core after we import annotations and em back into core -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>3.3.1.ga</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-tools</artifactId>
|
||||
<version>3.2.0.ga</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
<version>1.6.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<properties>
|
||||
<!-- for now, at least, lets aggregate them -->
|
||||
<jbossenvers.reports.aggregate>true</jbossenvers.reports.aggregate>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.demo;
|
||||
|
||||
import org.jboss.envers.Versioned;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
public class Address {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
@Versioned
|
||||
private String streetName;
|
||||
|
||||
@Versioned
|
||||
private Integer houseNumber;
|
||||
|
||||
@Versioned
|
||||
private Integer flatNumber;
|
||||
|
||||
@Versioned
|
||||
@OneToMany(mappedBy = "address")
|
||||
private Set<Person> persons;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getStreetName() {
|
||||
return streetName;
|
||||
}
|
||||
|
||||
public void setStreetName(String streetName) {
|
||||
this.streetName = streetName;
|
||||
}
|
||||
|
||||
public Integer getHouseNumber() {
|
||||
return houseNumber;
|
||||
}
|
||||
|
||||
public void setHouseNumber(Integer houseNumber) {
|
||||
this.houseNumber = houseNumber;
|
||||
}
|
||||
|
||||
public Integer getFlatNumber() {
|
||||
return flatNumber;
|
||||
}
|
||||
|
||||
public void setFlatNumber(Integer flatNumber) {
|
||||
this.flatNumber = flatNumber;
|
||||
}
|
||||
|
||||
public Set<Person> getPersons() {
|
||||
return persons;
|
||||
}
|
||||
|
||||
public void setPersons(Set<Person> persons) {
|
||||
this.persons = persons;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Address)) return false;
|
||||
|
||||
Address address = (Address) o;
|
||||
|
||||
if (id != address.id) return false;
|
||||
if (flatNumber != null ? !flatNumber.equals(address.flatNumber) : address.flatNumber != null) return false;
|
||||
if (houseNumber != null ? !houseNumber.equals(address.houseNumber) : address.houseNumber != null) return false;
|
||||
if (streetName != null ? !streetName.equals(address.streetName) : address.streetName != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = id;
|
||||
result = 31 * result + (streetName != null ? streetName.hashCode() : 0);
|
||||
result = 31 * result + (houseNumber != null ? houseNumber.hashCode() : 0);
|
||||
result = 31 * result + (flatNumber != null ? flatNumber.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.demo;
|
||||
|
||||
import org.jboss.envers.Versioned;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
public class Person {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
@Versioned
|
||||
private String name;
|
||||
|
||||
@Versioned
|
||||
private String surname;
|
||||
|
||||
@Versioned
|
||||
@ManyToOne
|
||||
private Address address;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSurname() {
|
||||
return surname;
|
||||
}
|
||||
|
||||
public void setSurname(String surname) {
|
||||
this.surname = surname;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Person)) return false;
|
||||
|
||||
Person person = (Person) o;
|
||||
|
||||
if (id != person.id) return false;
|
||||
if (name != null ? !name.equals(person.name) : person.name != null) return false;
|
||||
if (surname != null ? !surname.equals(person.surname) : person.surname != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = id;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
result = 31 * result + (surname != null ? surname.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.demo;
|
||||
|
||||
import org.jboss.envers.VersionsReader;
|
||||
import org.jboss.envers.VersionsReaderFactory;
|
||||
import org.jboss.envers.DefaultRevisionEntity;
|
||||
import org.jboss.envers.query.VersionsRestrictions;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import java.util.*;
|
||||
import java.io.PrintStream;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class TestConsole {
|
||||
private EntityManager entityManager;
|
||||
|
||||
public TestConsole(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
private String convertString(String s, String def) {
|
||||
if ("NULL".equals(s)) { return null; }
|
||||
if ("".equals(s)) { return def; }
|
||||
return s;
|
||||
}
|
||||
|
||||
private int convertStringToInteger(String s, int def) {
|
||||
if ("".equals(s)) { return def; }
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Invalid number, returning 0.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void printPerson(StringBuilder sb, Person p) {
|
||||
sb.append("id = ").append(p.getId()).append(", name = ").append(p.getName())
|
||||
.append(", surname = ").append(p.getSurname());
|
||||
|
||||
Address a = p.getAddress();
|
||||
if (a != null) {
|
||||
sb.append(", address = <").append(a.getId()).append("> ").append(a.getStreetName()).append(" ")
|
||||
.append(a.getHouseNumber()).append("/").append(a.getFlatNumber());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void printPersons(StringBuilder sb) {
|
||||
List<Person> persons = entityManager.createQuery(
|
||||
"select p from Person p order by p.id").getResultList();
|
||||
|
||||
sb.append("Persons:\n");
|
||||
for (Person p : persons) {
|
||||
printPerson(sb, p);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void printPersonHistory(StringBuilder sb, int personId) {
|
||||
VersionsReader reader = VersionsReaderFactory.get(entityManager);
|
||||
|
||||
List personHistory = reader.createQuery()
|
||||
.forRevisionsOfEntity(Person.class, false, true)
|
||||
.add(VersionsRestrictions.idEq(personId))
|
||||
.getResultList();
|
||||
|
||||
if (personHistory.size() == 0) {
|
||||
sb.append("A person with id ").append(personId).append(" does not exist.\n");
|
||||
} else {
|
||||
for (Object historyObj : personHistory) {
|
||||
Object[] history = (Object[]) historyObj;
|
||||
DefaultRevisionEntity revision = (DefaultRevisionEntity) history[1];
|
||||
sb.append("revision = ").append(revision.getId()).append(", ");
|
||||
printPerson(sb, (Person) history[0]);
|
||||
sb.append(" (").append(revision.getRevisionDate()).append(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printPersonAtRevision(StringBuilder sb, int personId, int revision) {
|
||||
VersionsReader reader = VersionsReaderFactory.get(entityManager);
|
||||
|
||||
Person p = reader.find(Person.class, personId, revision);
|
||||
if (p == null) {
|
||||
sb.append("This person does not exist at that revision.");
|
||||
} else {
|
||||
printPerson(sb, p);
|
||||
}
|
||||
}
|
||||
|
||||
private void readAndSetAddress(Scanner scanner, Person p) {
|
||||
Address old = p.getAddress();
|
||||
|
||||
String input = scanner.nextLine();
|
||||
if ("NULL".equals(input)) {
|
||||
p.setAddress(null);
|
||||
if (old != null) {
|
||||
old.getPersons().remove(p);
|
||||
}
|
||||
} else if ("".equals(input)) {
|
||||
} else {
|
||||
try {
|
||||
Integer id = Integer.valueOf(input);
|
||||
|
||||
Address a = entityManager.find(Address.class, id);
|
||||
|
||||
if (a == null) {
|
||||
System.err.println("Unknown address id, setting to NULL.");
|
||||
p.setAddress(null);
|
||||
if (old != null) {
|
||||
old.getPersons().remove(p);
|
||||
}
|
||||
} else {
|
||||
p.setAddress(a);
|
||||
|
||||
a.getPersons().add(p);
|
||||
|
||||
if (old != null) {
|
||||
old.getPersons().remove(p);
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Invalid address id, setting to NULL.");
|
||||
p.setAddress(null);
|
||||
if (old != null) {
|
||||
old.getPersons().remove(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Person readNewPerson(PrintStream out, Scanner scanner) {
|
||||
Person p = new Person();
|
||||
|
||||
out.print("Person name (NULL for null): ");
|
||||
p.setName(convertString(scanner.nextLine(), ""));
|
||||
|
||||
out.print("Person surname (NULL for null): ");
|
||||
p.setSurname(convertString(scanner.nextLine(), ""));
|
||||
|
||||
out.print("Person address id (NULL for null): ");
|
||||
readAndSetAddress(scanner, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private void readModifyPerson(PrintStream out, Scanner scanner, int personId) {
|
||||
Person current = entityManager.find(Person.class, personId);
|
||||
|
||||
if (current == null) {
|
||||
out.println("Person with id " + personId + " does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
out.print("Person name (NULL for null, enter for no change, current - " + current.getName() + "): ");
|
||||
current.setName(convertString(scanner.nextLine(), current.getName()));
|
||||
|
||||
out.print("Person surname (NULL for null, enter for no change, current - " + current.getSurname() + "): ");
|
||||
current.setSurname(convertString(scanner.nextLine(), current.getSurname()));
|
||||
|
||||
out.print("Person address id (NULL for null, enter for no change, current - " +
|
||||
(current.getAddress() == null ? "NULL" : current.getAddress().getId()) + "): ");
|
||||
readAndSetAddress(scanner, current);
|
||||
}
|
||||
|
||||
private void printAddress(StringBuilder sb, Address a) {
|
||||
sb.append("id = ").append(a.getId()).append(", streetName = ").append(a.getStreetName())
|
||||
.append(", houseNumber = ").append(a.getHouseNumber())
|
||||
.append(", flatNumber = ").append(a.getFlatNumber())
|
||||
.append(", persons = (");
|
||||
|
||||
Iterator<Person> iter = a.getPersons().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Person p = iter.next();
|
||||
sb.append("<").append(p.getId()).append("> ").append(p.getName()).append(" ").append(p.getSurname());
|
||||
if (iter.hasNext()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(")");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void printAddresses(StringBuilder sb) {
|
||||
List<Address> addresses = entityManager.createQuery(
|
||||
"select a from Address a order by a.id").getResultList();
|
||||
|
||||
sb.append("Addresses:\n");
|
||||
for (Address a : addresses) {
|
||||
printAddress(sb, a);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void printAddressHistory(StringBuilder sb, int addressId) {
|
||||
VersionsReader reader = VersionsReaderFactory.get(entityManager);
|
||||
|
||||
List addressHistory = reader.createQuery()
|
||||
.forRevisionsOfEntity(Address.class, false, true)
|
||||
.add(VersionsRestrictions.idEq(addressId))
|
||||
.getResultList();
|
||||
|
||||
if (addressHistory.size() == 0) {
|
||||
sb.append("A address with id ").append(addressId).append(" does not exist.\n");
|
||||
} else {
|
||||
for (Object historyObj : addressHistory) {
|
||||
Object[] history = (Object[]) historyObj;
|
||||
DefaultRevisionEntity revision = (DefaultRevisionEntity) history[1];
|
||||
sb.append("revision = ").append(revision.getId()).append(", ");
|
||||
printAddress(sb, (Address) history[0]);
|
||||
sb.append(" (").append(revision.getRevisionDate()).append(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printAddressAtRevision(StringBuilder sb, int addressId, int revision) {
|
||||
VersionsReader reader = VersionsReaderFactory.get(entityManager);
|
||||
|
||||
Address a = reader.find(Address.class, addressId, revision);
|
||||
if (a == null) {
|
||||
sb.append("This address does not exist at that revision.");
|
||||
} else {
|
||||
printAddress(sb, a);
|
||||
}
|
||||
}
|
||||
|
||||
private Address readNewAddress(PrintStream out, Scanner scanner) {
|
||||
Address a = new Address();
|
||||
|
||||
out.print("Street name (NULL for null): ");
|
||||
a.setStreetName(convertString(scanner.nextLine(), ""));
|
||||
|
||||
out.print("House number: ");
|
||||
a.setHouseNumber(convertStringToInteger(scanner.nextLine(), 0));
|
||||
|
||||
out.print("Flat number: ");
|
||||
a.setFlatNumber(convertStringToInteger(scanner.nextLine(), 0));
|
||||
|
||||
a.setPersons(new HashSet<Person>());
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
private void readModifyAddress(PrintStream out, Scanner scanner, int addressId) {
|
||||
Address current = entityManager.find(Address.class, addressId);
|
||||
|
||||
if (current == null) {
|
||||
out.println("Address with id " + addressId + " does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
out.print("Street name (NULL for null, enter for no change, current - " + current.getStreetName() + "): ");
|
||||
current.setStreetName(convertString(scanner.nextLine(), current.getStreetName()));
|
||||
|
||||
out.print("House number (enter for no change, current - " + current.getHouseNumber() + "): ");
|
||||
current.setHouseNumber(convertStringToInteger(scanner.nextLine(), current.getHouseNumber()));
|
||||
|
||||
out.print("Flat number (enter for no change, current - " + current.getFlatNumber() + "): ");
|
||||
current.setFlatNumber(convertStringToInteger(scanner.nextLine(), current.getFlatNumber()));
|
||||
}
|
||||
|
||||
private void start() {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
PrintStream out = System.out;
|
||||
|
||||
while (true) {
|
||||
out.println("-----------------------------------------------");
|
||||
out.println("1 - list persons 5 - list addresses");
|
||||
out.println("2 - list person history 6 - list addresses history");
|
||||
out.println("3 - new person 7 - new address");
|
||||
out.println("4 - modify person 8 - modify address");
|
||||
out.println("9 - get person at revision 10 - get address at revision");
|
||||
out.println(" 0 - end");
|
||||
|
||||
try {
|
||||
int choice = scanner.nextInt();
|
||||
|
||||
scanner.nextLine();
|
||||
|
||||
entityManager.getTransaction().begin();
|
||||
|
||||
StringBuilder sb;
|
||||
int personId;
|
||||
int addressId;
|
||||
int revision;
|
||||
switch (choice) {
|
||||
case 1:
|
||||
sb = new StringBuilder();
|
||||
printPersons(sb);
|
||||
out.println(sb.toString());
|
||||
break;
|
||||
case 2:
|
||||
out.print("Person id: ");
|
||||
personId = scanner.nextInt(); scanner.nextLine();
|
||||
sb = new StringBuilder();
|
||||
printPersonHistory(sb, personId);
|
||||
out.println(sb.toString());
|
||||
break;
|
||||
case 3:
|
||||
Person p = readNewPerson(out, scanner);
|
||||
entityManager.persist(p);
|
||||
break;
|
||||
case 4:
|
||||
out.print("Person id: ");
|
||||
personId = scanner.nextInt(); scanner.nextLine();
|
||||
readModifyPerson(out, scanner, personId);
|
||||
break;
|
||||
case 5:
|
||||
sb = new StringBuilder();
|
||||
printAddresses(sb);
|
||||
out.println(sb.toString());
|
||||
break;
|
||||
case 6:
|
||||
out.print("Address id: ");
|
||||
addressId = scanner.nextInt(); scanner.nextLine();
|
||||
sb = new StringBuilder();
|
||||
printAddressHistory(sb, addressId);
|
||||
out.println(sb.toString());
|
||||
break;
|
||||
case 7:
|
||||
Address a = readNewAddress(out, scanner);
|
||||
entityManager.persist(a);
|
||||
break;
|
||||
case 8:
|
||||
out.print("Address id: ");
|
||||
addressId = scanner.nextInt(); scanner.nextLine();
|
||||
readModifyAddress(out, scanner, addressId);
|
||||
break;
|
||||
case 9:
|
||||
out.print("Person id: ");
|
||||
personId = scanner.nextInt(); scanner.nextLine();
|
||||
out.print("Revision number: ");
|
||||
revision = scanner.nextInt(); scanner.nextLine();
|
||||
if (revision <= 0) {
|
||||
System.out.println("Revision must be greater then 0!");
|
||||
continue;
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
printPersonAtRevision(sb, personId, revision);
|
||||
out.println(sb.toString());
|
||||
break;
|
||||
case 10:
|
||||
out.print("Address id: ");
|
||||
addressId = scanner.nextInt(); scanner.nextLine();
|
||||
out.print("Revision number: ");
|
||||
revision = scanner.nextInt(); scanner.nextLine();
|
||||
if (revision <= 0) {
|
||||
System.out.println("Revision must be greater then 0!");
|
||||
continue;
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
printAddressAtRevision(sb, addressId, revision);
|
||||
out.println(sb.toString());
|
||||
break;
|
||||
|
||||
case 0:
|
||||
return;
|
||||
}
|
||||
} catch (InputMismatchException e) {
|
||||
// continuing
|
||||
} finally {
|
||||
entityManager.getTransaction().commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasData() {
|
||||
return (((Long) entityManager.createQuery("select count(a) from Address a").getSingleResult()) +
|
||||
((Long) entityManager.createQuery("select count(p) from Person p").getSingleResult())) > 0;
|
||||
}
|
||||
|
||||
private void populateTestData() {
|
||||
entityManager.getTransaction().begin();
|
||||
|
||||
if (!hasData()) {
|
||||
Person p1 = new Person();
|
||||
Person p2 = new Person();
|
||||
Person p3 = new Person();
|
||||
|
||||
Address a1 = new Address();
|
||||
Address a2 = new Address();
|
||||
|
||||
p1.setName("James");
|
||||
p1.setSurname("Bond");
|
||||
p1.setAddress(a1);
|
||||
|
||||
p2.setName("John");
|
||||
p2.setSurname("McClane");
|
||||
p2.setAddress(a2);
|
||||
|
||||
p3.setName("Holly");
|
||||
p3.setSurname("Gennaro");
|
||||
p3.setAddress(a2);
|
||||
|
||||
a1.setStreetName("MI6");
|
||||
a1.setHouseNumber(18);
|
||||
a1.setFlatNumber(25);
|
||||
a1.setPersons(new HashSet<Person>());
|
||||
a1.getPersons().add(p1);
|
||||
|
||||
a2.setStreetName("Nakatomi Plaza");
|
||||
a2.setHouseNumber(10);
|
||||
a2.setFlatNumber(34);
|
||||
a2.setPersons(new HashSet<Person>());
|
||||
a2.getPersons().add(p2);
|
||||
a2.getPersons().add(p3);
|
||||
|
||||
entityManager.persist(a1);
|
||||
entityManager.persist(a2);
|
||||
|
||||
entityManager.persist(p1);
|
||||
entityManager.persist(p2);
|
||||
entityManager.persist(p3);
|
||||
|
||||
System.out.println("The DB was populated with example data.");
|
||||
}
|
||||
|
||||
entityManager.getTransaction().commit();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String userDbFile = System.getProperty("java.io.tmpdir") + File.separator + "_versions_demo.db";
|
||||
|
||||
Map<String, String> configurationOverrides = new HashMap<String, String>();
|
||||
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ConsolePU", configurationOverrides);
|
||||
EntityManager entityManager = emf.createEntityManager();
|
||||
|
||||
TestConsole console = new TestConsole(entityManager);
|
||||
|
||||
System.out.println("");
|
||||
System.out.println("Welcome to EntityVersions demo!");
|
||||
System.out.println("HSQLDB database file location: " + userDbFile);
|
||||
|
||||
console.populateTestData();
|
||||
console.start();
|
||||
|
||||
entityManager.close();
|
||||
emf.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
|
||||
<persistence-unit name="ConsolePU">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<class>org.jboss.envers.demo.Address</class>
|
||||
<class>org.jboss.envers.demo.Person</class>
|
||||
<exclude-unlisted-classes />
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
|
||||
<property name="hibernate.connection.url" value="jdbc:hsqldb:file:${java.io.tmpdir}/_versions_demo.db"/>
|
||||
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="hibernate.connection.username" value="sa"/>
|
||||
<property name="hibernate.connection.password" value=""/>
|
||||
|
||||
<!--<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
|
||||
<property name="hibernate.connection.url" value="jdbc:mysql:///hibernate_tests?useUnicode=true&characterEncoding=UTF-8"/>
|
||||
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
|
||||
<property name="hibernate.connection.username" value="root"/>
|
||||
<property name="hibernate.connection.password" value=""/>-->
|
||||
|
||||
<property name="hibernate.hbm2ddl.auto" value="update"/>
|
||||
<!--<property name="hibernate.show_sql" value="true"/>
|
||||
<property name="hibernate.format_sql" value="true"/>-->
|
||||
|
||||
<property name="hibernate.ejb.event.post-insert" value="org.jboss.envers.event.VersionsEventListener" />
|
||||
<property name="hibernate.ejb.event.post-update" value="org.jboss.envers.event.VersionsEventListener" />
|
||||
<property name="hibernate.ejb.event.post-delete" value="org.jboss.envers.event.VersionsEventListener" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.hibernate.tool.ant;
|
||||
|
||||
import org.jboss.envers.ant.JPAConfigurationTaskWithEnvers;
|
||||
import org.jboss.envers.ant.ConfigurationTaskWithEnvers;
|
||||
import org.jboss.envers.ant.AnnotationConfigurationTaskWithEnvers;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EnversHibernateToolTask extends HibernateToolTask {
|
||||
private void checkConfiguration() {
|
||||
if (configurationTask!=null) {
|
||||
throw new BuildException("Only a single configuration is allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
public JPAConfigurationTask createJpaConfiguration() {
|
||||
checkConfiguration();
|
||||
JPAConfigurationTask task = new JPAConfigurationTaskWithEnvers();
|
||||
configurationTask = task;
|
||||
return task;
|
||||
}
|
||||
|
||||
public ConfigurationTask createConfiguration() {
|
||||
checkConfiguration();
|
||||
ConfigurationTaskWithEnvers task = new ConfigurationTaskWithEnvers();
|
||||
configurationTask = task;
|
||||
return task;
|
||||
}
|
||||
|
||||
public AnnotationConfigurationTask createAnnotationConfiguration() {
|
||||
checkConfiguration();
|
||||
AnnotationConfigurationTaskWithEnvers task = new AnnotationConfigurationTaskWithEnvers();
|
||||
configurationTask = task;
|
||||
return task;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.Date;
|
||||
import java.text.DateFormat;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class DefaultRevisionEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
@RevisionNumber
|
||||
private int id;
|
||||
|
||||
@RevisionTimestamp
|
||||
private long timestamp;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public Date getRevisionDate() {
|
||||
return new Date(timestamp);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof DefaultRevisionEntity)) return false;
|
||||
|
||||
DefaultRevisionEntity that = (DefaultRevisionEntity) o;
|
||||
|
||||
if (id != that.id) return false;
|
||||
if (timestamp != that.timestamp) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = id;
|
||||
result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "DefaultRevisionEntity(id = " + id + ", revisionDate = " + DateFormat.getDateTimeInstance().format(getRevisionDate()) + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public enum ModificationStore {
|
||||
FULL
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Marks an entity to be created whenever a new revision is generated. The revisions entity must have
|
||||
* an integer-valued unique property (preferrably the primary id) annotated with {@link RevisionNumber}
|
||||
* and a long-valued property annotated with {@link RevisionTimestamp}. The {@link DefaultRevisionEntity}
|
||||
* already has those two fields, so you may extend it, but you may also write your own revision entity
|
||||
* from scratch.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface RevisionEntity {
|
||||
Class<? extends RevisionListener> value() default RevisionListener.class;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
/**
|
||||
* An implementation of this class, having a no-arg constructor, should be passed as an argument to the
|
||||
* {@link RevisionEntity} annotation.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface RevisionListener {
|
||||
/**
|
||||
* Called when a new revision is created.
|
||||
* @param revisionEntity An instance of the entity annotated with {@link RevisionEntity}, which will be persisted
|
||||
* after this method returns. All properties on this entity that are to be persisted should be set by this method.
|
||||
*/
|
||||
void newRevision(Object revisionEntity);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Marks a property which will hold the number of the revision in a revision entity, see
|
||||
* {@link RevisionListener}. Values of this property should form a strictly-increasing sequence
|
||||
* of numbers. The value of this property won't be set by Envers. In most cases, this should be
|
||||
* an auto-generated database-assigned primary id.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD})
|
||||
public @interface RevisionNumber {
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* Marks a property which will hold the timestamp of the revision in a revision entity, see
|
||||
* {@link RevisionListener}. The value of this property will be automatically set by Envers.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD})
|
||||
public @interface RevisionTimestamp {
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
/**
|
||||
* Type of the revision.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public enum RevisionType {
|
||||
/**
|
||||
* Indicates that the entity was added (persisted) at that revision.
|
||||
*/
|
||||
ADD((byte) 0),
|
||||
/**
|
||||
* Indicates that the entity was modified (one or more of its fields) at that revision.
|
||||
*/
|
||||
MOD((byte) 1),
|
||||
/**
|
||||
* Indicates that the entity was deleted (removed) at that revision.
|
||||
*/
|
||||
DEL((byte) 2);
|
||||
|
||||
private Byte representation;
|
||||
|
||||
RevisionType(byte representation) {
|
||||
this.representation = representation;
|
||||
}
|
||||
|
||||
public Byte getRepresentation() {
|
||||
return representation;
|
||||
}
|
||||
|
||||
public static RevisionType fromRepresentation(Object representation) {
|
||||
if (representation == null || !(representation instanceof Byte)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ((Byte) representation) {
|
||||
case 0: return ADD;
|
||||
case 1: return MOD;
|
||||
case 2: return DEL;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown representation: " + representation);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SecondaryVersionsTable {
|
||||
String secondaryTableName();
|
||||
|
||||
String secondaryVersionsTableName();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SecondaryVersionsTables {
|
||||
SecondaryVersionsTable[] value();
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* When applied to a field, indicates that this field should not be versioned.
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD, ElementType.FIELD})
|
||||
public @interface Unversioned {
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* When applied to a class, indicates that all of its properties should be versioned.
|
||||
* When applied to a field, indicates that this field should be versioned.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||
public @interface Versioned {
|
||||
ModificationStore modStore() default ModificationStore.FULL;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
public @interface VersionsJoinTable {
|
||||
/**
|
||||
* @return Name of the join table. Defaults to a concatenation of the names of the primary table of the entity
|
||||
* owning the association and of the primary table of the entity referenced by the association.
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* @return The schema of the join table. Defaults to the schema of the entity owning the association.
|
||||
*/
|
||||
String schema() default "";
|
||||
|
||||
/**
|
||||
* @return The catalog of the join table. Defaults to the catalog of the entity owning the association.
|
||||
*/
|
||||
String catalog() default "";
|
||||
|
||||
/**
|
||||
* @return The foreign key columns of the join table which reference the primary table of the entity that does not
|
||||
* own the association (i.e. the inverse side of the association).
|
||||
*/
|
||||
JoinColumn[] inverseJoinColumns() default {};
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import org.jboss.envers.exception.NotVersionedException;
|
||||
import org.jboss.envers.exception.RevisionDoesNotExistException;
|
||||
import org.jboss.envers.query.VersionsQueryCreator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface VersionsReader {
|
||||
/**
|
||||
* Find an entity by primary key at the given revision.
|
||||
* @param cls Class of the entity.
|
||||
* @param primaryKey Primary key of the entity.
|
||||
* @param revision Revision in which to get the entity.
|
||||
* @return The found entity instance at the given revision (its properties may be partially filled
|
||||
* if not all properties are versioned) or null, if an entity with that id didn't exist at that
|
||||
* revision.
|
||||
* @throws IllegalArgumentException If cls or primaryKey is null or revision is less or equal to 0.
|
||||
* @throws NotVersionedException When entities of the given class are not versioned.
|
||||
* @throws IllegalStateException If the associated entity manager is closed.
|
||||
*/
|
||||
<T> T find(Class<T> cls, Object primaryKey, Number revision) throws
|
||||
IllegalArgumentException, NotVersionedException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Get a list of revision numbers, at which an entity was modified.
|
||||
* @param cls Class of the entity.
|
||||
* @param primaryKey Primary key of the entity.
|
||||
* @return A list of revision numbers, at which the entity was modified, sorted in ascending order (so older
|
||||
* revisions come first).
|
||||
* @throws NotVersionedException When entities of the given class are not versioned.
|
||||
* @throws IllegalArgumentException If cls or primaryKey is null.
|
||||
* @throws IllegalStateException If the associated entity manager is closed.
|
||||
*/
|
||||
List<Number> getRevisions(Class<?> cls, Object primaryKey)
|
||||
throws IllegalArgumentException, NotVersionedException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Get the date, at which a revision was created.
|
||||
* @param revision Number of the revision for which to get the date.
|
||||
* @return Date of commiting the given revision.
|
||||
* @throws IllegalArgumentException If revision is less or equal to 0.
|
||||
* @throws RevisionDoesNotExistException If the revision does not exist.
|
||||
* @throws IllegalStateException If the associated entity manager is closed.
|
||||
*/
|
||||
Date getRevisionDate(Number revision) throws IllegalArgumentException, RevisionDoesNotExistException,
|
||||
IllegalStateException;
|
||||
|
||||
/**
|
||||
* Gets the revision number, that corresponds to the given date. More precisely, returns
|
||||
* the number of the highest revision, which was created on or before the given date. So:
|
||||
* <code>getRevisionDate(getRevisionNumberForDate(date)) <= date</code> and
|
||||
* <code>getRevisionDate(getRevisionNumberForDate(date)+1) > date</code>.
|
||||
* @param date Date for which to get the revision.
|
||||
* @return Revision number corresponding to the given date.
|
||||
* @throws IllegalStateException If the associated entity manager is closed.
|
||||
* @throws RevisionDoesNotExistException If the given date is before the first revision.
|
||||
* @throws IllegalArgumentException If <code>date</code> is <code>null</code>.
|
||||
*/
|
||||
Number getRevisionNumberForDate(Date date) throws IllegalStateException, RevisionDoesNotExistException,
|
||||
IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* A helper method; should be used only if a custom revision entity is used. See also {@link RevisionEntity}.
|
||||
* @param revisionEntityClass Class of the revision entity. Should be annotated with {@link RevisionEntity}.
|
||||
* @param revision Number of the revision for which to get the data.
|
||||
* @return Entity containing data for the given revision.
|
||||
* @throws IllegalArgumentException If revision is less or equal to 0 or if the class of the revision entity
|
||||
* is invalid.
|
||||
* @throws RevisionDoesNotExistException If the revision does not exist.
|
||||
* @throws IllegalStateException If the associated entity manager is closed.
|
||||
*/
|
||||
<T> T findRevision(Class<T> revisionEntityClass, Number revision) throws IllegalArgumentException,
|
||||
RevisionDoesNotExistException, IllegalStateException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A query creator, associated with this VersionsReader instance, with which queries can be
|
||||
* created and later executed. Shouldn't be used after the associated Session or EntityManager
|
||||
* is closed.
|
||||
*/
|
||||
VersionsQueryCreator createQuery();
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.event.EventListeners;
|
||||
import org.hibernate.event.PostInsertEventListener;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.event.VersionsEventListener;
|
||||
import static org.jboss.envers.tools.ArraysTools.arrayIncludesInstanceOf;
|
||||
import org.jboss.envers.reader.VersionsReaderImpl;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class VersionsReaderFactory {
|
||||
private VersionsReaderFactory() { }
|
||||
|
||||
/**
|
||||
* Create a versions reader associated with an open session.
|
||||
* <b>WARNING:</b> Using Envers with Hibernate (not with Hibernate Entity Manager/JPA) is experimental,
|
||||
* if possible, use {@link org.jboss.envers.VersionsReaderFactory#get(javax.persistence.EntityManager)}.
|
||||
* @param session An open session.
|
||||
* @return A versions reader associated with the given sesison. It shouldn't be used
|
||||
* after the session is closed.
|
||||
* @throws VersionsException When the given required listeners aren't installed.
|
||||
*/
|
||||
public static VersionsReader get(Session session) throws VersionsException {
|
||||
SessionImplementor sessionImpl = (SessionImplementor) session;
|
||||
|
||||
EventListeners listeners = sessionImpl.getListeners();
|
||||
|
||||
for (PostInsertEventListener listener : listeners.getPostInsertEventListeners()) {
|
||||
if (listener instanceof VersionsEventListener) {
|
||||
if (arrayIncludesInstanceOf(listeners.getPostUpdateEventListeners(), VersionsEventListener.class) &&
|
||||
arrayIncludesInstanceOf(listeners.getPostDeleteEventListeners(), VersionsEventListener.class)) {
|
||||
return new VersionsReaderImpl(((VersionsEventListener) listener).getVerCfg(), session,
|
||||
sessionImpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new VersionsException("You need install the org.jboss.envers.event.VersionsEventListener " +
|
||||
"class as post insert, update and delete event listener.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a versions reader associated with an open entity manager.
|
||||
* @param entityManager An open entity manager.
|
||||
* @return A versions reader associated with the given entity manager. It shouldn't be used
|
||||
* after the entity manager is closed.
|
||||
* @throws VersionsException When the given entity manager is not based on Hibernate, or if the required
|
||||
* listeners aren't installed.
|
||||
*/
|
||||
public static VersionsReader get(EntityManager entityManager) throws VersionsException {
|
||||
if (entityManager.getDelegate() instanceof Session) {
|
||||
return get((Session) entityManager.getDelegate());
|
||||
}
|
||||
|
||||
if (entityManager.getDelegate() instanceof EntityManager) {
|
||||
if (entityManager.getDelegate() instanceof Session) {
|
||||
return get((Session) entityManager.getDelegate());
|
||||
}
|
||||
}
|
||||
|
||||
throw new VersionsException("Hibernate EntityManager not present!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface VersionsTable {
|
||||
String value();
|
||||
|
||||
/**
|
||||
* @return The schema of the table. Defaults to the schema of the annotated entity.
|
||||
*/
|
||||
String schema() default "";
|
||||
|
||||
/**
|
||||
* @return The catalog of the table. Defaults to the catalog of the annotated entity.
|
||||
*/
|
||||
String catalog() default "";
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.ant;
|
||||
|
||||
import org.hibernate.tool.ant.AnnotationConfigurationTask;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class AnnotationConfigurationTaskWithEnvers extends AnnotationConfigurationTask {
|
||||
protected void doConfiguration(Configuration configuration) {
|
||||
VersionsConfiguration.getFor(configuration);
|
||||
|
||||
super.doConfiguration(configuration);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.ant;
|
||||
|
||||
import org.hibernate.tool.ant.ConfigurationTask;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ConfigurationTaskWithEnvers extends ConfigurationTask {
|
||||
protected void doConfiguration(Configuration configuration) {
|
||||
VersionsConfiguration.getFor(configuration);
|
||||
|
||||
super.doConfiguration(configuration);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.ant;
|
||||
|
||||
import org.hibernate.tool.ant.JPAConfigurationTask;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class JPAConfigurationTaskWithEnvers extends JPAConfigurationTask {
|
||||
protected void doConfiguration(Configuration configuration) {
|
||||
VersionsConfiguration.getFor(configuration);
|
||||
|
||||
super.doConfiguration(configuration);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration;
|
||||
|
||||
import org.jboss.envers.entities.EntitiesConfigurations;
|
||||
import org.jboss.envers.configuration.metadata.VersionsMetadataGenerator;
|
||||
import org.jboss.envers.configuration.metadata.PersistentClassVersioningData;
|
||||
import org.jboss.envers.configuration.metadata.AnnotationsMetadataReader;
|
||||
import org.jboss.envers.configuration.metadata.EntityXmlMappingData;
|
||||
import org.jboss.envers.tools.graph.GraphTopologicalSort;
|
||||
import org.jboss.envers.tools.reflection.YReflectionManager;
|
||||
import org.jboss.envers.tools.StringTools;
|
||||
import org.dom4j.io.DOMWriter;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Writer;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EntitiesConfigurator {
|
||||
public EntitiesConfigurations configure(Configuration cfg, YReflectionManager reflectionManager,
|
||||
GlobalConfiguration globalCfg, VersionsEntitiesConfiguration verEntCfg,
|
||||
Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) {
|
||||
VersionsMetadataGenerator versionsMetaGen = new VersionsMetadataGenerator(cfg, globalCfg, verEntCfg,
|
||||
revisionInfoRelationMapping);
|
||||
DOMWriter writer = new DOMWriter();
|
||||
|
||||
// Sorting the persistent class topologically - superclass always before subclass
|
||||
Iterator<PersistentClass> classes = GraphTopologicalSort.sort(new PersistentClassGraphDefiner(cfg)).iterator();
|
||||
|
||||
Map<PersistentClass, PersistentClassVersioningData> pcDatas =
|
||||
new HashMap<PersistentClass, PersistentClassVersioningData>();
|
||||
Map<PersistentClass, EntityXmlMappingData> xmlMappings = new HashMap<PersistentClass, EntityXmlMappingData>();
|
||||
|
||||
// First pass
|
||||
while (classes.hasNext()) {
|
||||
PersistentClass pc = classes.next();
|
||||
// Collecting information from annotations on the persistent class pc
|
||||
AnnotationsMetadataReader annotationsMetadataReader =
|
||||
new AnnotationsMetadataReader(globalCfg, reflectionManager, pc);
|
||||
PersistentClassVersioningData versioningData = annotationsMetadataReader.getVersioningData();
|
||||
|
||||
if (versioningData.isVersioned()) {
|
||||
pcDatas.put(pc, versioningData);
|
||||
|
||||
if (!StringTools.isEmpty(versioningData.versionsTable.value())) {
|
||||
verEntCfg.addCustomVersionsTableName(pc.getEntityName(), versioningData.versionsTable.value());
|
||||
}
|
||||
|
||||
EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
|
||||
versionsMetaGen.generateFirstPass(pc, versioningData, xmlMappingData);
|
||||
xmlMappings.put(pc, xmlMappingData);
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass
|
||||
for (Map.Entry<PersistentClass, PersistentClassVersioningData> pcDatasEntry : pcDatas.entrySet()) {
|
||||
EntityXmlMappingData xmlMappingData = xmlMappings.get(pcDatasEntry.getKey());
|
||||
|
||||
versionsMetaGen.generateSecondPass(pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData);
|
||||
|
||||
try {
|
||||
cfg.addDocument(writer.write(xmlMappingData.getMainXmlMapping()));
|
||||
// TODO
|
||||
//writeDocument(xmlMappingData.getMainXmlMapping());
|
||||
|
||||
for (Document additionalMapping : xmlMappingData.getAdditionalXmlMappings()) {
|
||||
cfg.addDocument(writer.write(additionalMapping));
|
||||
// TODO
|
||||
//writeDocument(additionalMapping);
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Only if there are any versioned classes
|
||||
if (pcDatas.size() > 0) {
|
||||
try {
|
||||
if (revisionInfoXmlMapping != null) {
|
||||
// TODO
|
||||
//writeDocument(revisionInfoXmlMapping);
|
||||
cfg.addDocument(writer.write(revisionInfoXmlMapping));
|
||||
}
|
||||
} catch (DocumentException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return new EntitiesConfigurations(versionsMetaGen.getEntitiesConfigurations());
|
||||
}
|
||||
|
||||
// todo
|
||||
private void writeDocument(Document e) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
Writer w = new PrintWriter(baos);
|
||||
|
||||
try {
|
||||
XMLWriter xw = new XMLWriter(w, new OutputFormat(" ", true));
|
||||
xw.write(e);
|
||||
w.flush();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("-----------");
|
||||
System.out.println(baos.toString());
|
||||
System.out.println("-----------");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Nicolas Doroskevich
|
||||
*/
|
||||
public class GlobalConfiguration {
|
||||
// Should a revision be generated when a not-owned relation field changes
|
||||
private final boolean generateRevisionsForCollections;
|
||||
|
||||
// Should a warning, instead of an error and an exception, be logged, when an unsupported type is versioned
|
||||
private final boolean warnOnUnsupportedTypes;
|
||||
|
||||
// Should the optimistic locking property of an entity be considered unversioned
|
||||
private final boolean unversionedOptimisticLockingField;
|
||||
|
||||
/*
|
||||
Which operator to use in correlated subqueries (when we want a property to be equal to the result of
|
||||
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
|
||||
Normally, this should be "=". However, HSQLDB has an issue related to that, so as a workaround,
|
||||
"in" is used. See {@link org.jboss.envers.test.various.HsqlTest}.
|
||||
*/
|
||||
private final String correlatedSubqueryOperator;
|
||||
|
||||
public GlobalConfiguration(Properties properties) {
|
||||
String generateRevisionsForCollectionsStr = properties.getProperty("org.jboss.envers.revisionOnCollectionChange",
|
||||
"true");
|
||||
generateRevisionsForCollections = Boolean.parseBoolean(generateRevisionsForCollectionsStr);
|
||||
|
||||
String warnOnUnsupportedTypesStr = properties.getProperty("org.jboss.envers.warnOnUnsupportedTypes",
|
||||
"false");
|
||||
warnOnUnsupportedTypes = Boolean.parseBoolean(warnOnUnsupportedTypesStr);
|
||||
|
||||
String ignoreOptimisticLockingPropertyStr = properties.getProperty("org.jboss.envers.unversionedOptimisticLockingField",
|
||||
"false");
|
||||
unversionedOptimisticLockingField = Boolean.parseBoolean(ignoreOptimisticLockingPropertyStr);
|
||||
|
||||
correlatedSubqueryOperator = "org.hibernate.dialect.HSQLDialect".equals(
|
||||
properties.getProperty("hibernate.dialect")) ? "in" : "=";
|
||||
}
|
||||
|
||||
public boolean isGenerateRevisionsForCollections() {
|
||||
return generateRevisionsForCollections;
|
||||
}
|
||||
|
||||
public boolean isWarnOnUnsupportedTypes() {
|
||||
return warnOnUnsupportedTypes;
|
||||
}
|
||||
|
||||
public boolean isUnversionedOptimisticLockingField() {
|
||||
return unversionedOptimisticLockingField;
|
||||
}
|
||||
|
||||
public String getCorrelatedSubqueryOperator() {
|
||||
return correlatedSubqueryOperator;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration;
|
||||
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.jboss.envers.tools.graph.GraphDefiner;
|
||||
import org.jboss.envers.tools.Tools;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Defines a graph, where the vertexes are all persistent classes, and there is an edge from
|
||||
* p.c. A to p.c. B iff A is a superclass of B.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PersistentClassGraphDefiner implements GraphDefiner<PersistentClass, String> {
|
||||
private Configuration cfg;
|
||||
|
||||
public PersistentClassGraphDefiner(Configuration cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
public String getRepresentation(PersistentClass pc) {
|
||||
return pc.getEntityName();
|
||||
}
|
||||
|
||||
public PersistentClass getValue(String entityName) {
|
||||
return cfg.getClassMapping(entityName);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addNeighbours(List<PersistentClass> neighbours, Iterator<PersistentClass> subclassIterator) {
|
||||
while (subclassIterator.hasNext()) {
|
||||
PersistentClass subclass = subclassIterator.next();
|
||||
neighbours.add(subclass);
|
||||
addNeighbours(neighbours, (Iterator<PersistentClass>) subclass.getSubclassIterator());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List<PersistentClass> getNeighbours(PersistentClass pc) {
|
||||
List<PersistentClass> neighbours = new ArrayList<PersistentClass>();
|
||||
|
||||
addNeighbours(neighbours, (Iterator<PersistentClass>) pc.getSubclassIterator());
|
||||
|
||||
return neighbours;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List<PersistentClass> getValues() {
|
||||
return Tools.iteratorToList((Iterator<PersistentClass>) cfg.getClassMappings());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration;
|
||||
|
||||
import org.jboss.envers.tools.reflection.YClass;
|
||||
import org.jboss.envers.tools.reflection.YReflectionManager;
|
||||
import org.jboss.envers.tools.reflection.YProperty;
|
||||
import org.jboss.envers.tools.MutableBoolean;
|
||||
import org.jboss.envers.*;
|
||||
import org.jboss.envers.configuration.metadata.MetadataTools;
|
||||
import org.jboss.envers.revisioninfo.*;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class RevisionInfoConfiguration {
|
||||
private String revisionInfoEntityName;
|
||||
private String revisionInfoIdName;
|
||||
private String revisionInfoTimestampName;
|
||||
private String revisionInfoTimestampType;
|
||||
|
||||
private String revisionPropType;
|
||||
|
||||
public RevisionInfoConfiguration() {
|
||||
revisionInfoEntityName = "org.jboss.envers.DefaultRevisionEntity";
|
||||
revisionInfoIdName = "id";
|
||||
revisionInfoTimestampName = "timestamp";
|
||||
revisionInfoTimestampType = "long";
|
||||
|
||||
revisionPropType = "integer";
|
||||
}
|
||||
|
||||
private Document generateDefaultRevisionInfoXmlMapping() {
|
||||
Document document = DocumentHelper.createDocument();
|
||||
|
||||
Element class_mapping = MetadataTools.createEntity(document, null, null, null, null, null);
|
||||
|
||||
class_mapping.addAttribute("name", revisionInfoEntityName);
|
||||
class_mapping.addAttribute("table", "_revisions_info");
|
||||
|
||||
Element idProperty = MetadataTools.addNativelyGeneratedId(class_mapping, revisionInfoIdName,
|
||||
revisionPropType);
|
||||
MetadataTools.addColumn(idProperty, "revision_id", null);
|
||||
|
||||
Element timestampProperty = MetadataTools.addProperty(class_mapping, revisionInfoTimestampName,
|
||||
revisionInfoTimestampType, true, false);
|
||||
MetadataTools.addColumn(timestampProperty, "revision_timestamp", null);
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
private Element generateRevisionInfoRelationMapping() {
|
||||
Document document = DocumentHelper.createDocument();
|
||||
Element rev_rel_mapping =document.addElement("key-many-to-one");
|
||||
rev_rel_mapping.addAttribute("type", revisionPropType);
|
||||
rev_rel_mapping.addAttribute("class", revisionInfoEntityName);
|
||||
|
||||
return rev_rel_mapping;
|
||||
}
|
||||
|
||||
private void searchForRevisionInfoCfgInProperties(YClass clazz, YReflectionManager reflectionManager,
|
||||
MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound,
|
||||
String accessType) {
|
||||
for (YProperty property : clazz.getDeclaredProperties(accessType)) {
|
||||
RevisionNumber revisionNumber = property.getAnnotation(RevisionNumber.class);
|
||||
RevisionTimestamp revisionTimestamp = property.getAnnotation(RevisionTimestamp.class);
|
||||
|
||||
if (revisionNumber != null) {
|
||||
if (revisionNumberFound.isSet()) {
|
||||
throw new MappingException("Only one property may be annotated with @RevisionNumber!");
|
||||
}
|
||||
|
||||
YClass revisionNumberClass = property.getType();
|
||||
if (reflectionManager.equals(revisionNumberClass, Integer.class) ||
|
||||
reflectionManager.equals(revisionNumberClass, Integer.TYPE)) {
|
||||
revisionInfoIdName = property.getName();
|
||||
revisionNumberFound.set();
|
||||
} else if (reflectionManager.equals(revisionNumberClass, Long.class) ||
|
||||
reflectionManager.equals(revisionNumberClass, Long.TYPE)) {
|
||||
revisionInfoIdName = property.getName();
|
||||
revisionNumberFound.set();
|
||||
|
||||
// The default is integer
|
||||
revisionPropType = "long";
|
||||
} else {
|
||||
throw new MappingException("The field annotated with @RevisionNumber must be of type " +
|
||||
"int, Integer, long or Long");
|
||||
}
|
||||
}
|
||||
|
||||
if (revisionTimestamp != null) {
|
||||
if (revisionTimestampFound.isSet()) {
|
||||
throw new MappingException("Only one property may be annotated with @RevisionTimestamp!");
|
||||
}
|
||||
|
||||
YClass revisionTimestampClass = property.getType();
|
||||
if (reflectionManager.equals(revisionTimestampClass, Long.class) ||
|
||||
reflectionManager.equals(revisionTimestampClass, Long.TYPE)) {
|
||||
revisionInfoTimestampName = property.getName();
|
||||
revisionTimestampFound.set();
|
||||
} else {
|
||||
throw new MappingException("The field annotated with @RevisionTimestamp must be of type " +
|
||||
"long or Long");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void searchForRevisionInfoCfg(YClass clazz, YReflectionManager reflectionManager,
|
||||
MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound) {
|
||||
YClass superclazz = clazz.getSuperclass();
|
||||
if (!"java.lang.Object".equals(superclazz.getName())) {
|
||||
searchForRevisionInfoCfg(superclazz, reflectionManager, revisionNumberFound, revisionTimestampFound);
|
||||
}
|
||||
|
||||
searchForRevisionInfoCfgInProperties(clazz, reflectionManager, revisionNumberFound, revisionTimestampFound,
|
||||
"field");
|
||||
searchForRevisionInfoCfgInProperties(clazz, reflectionManager, revisionNumberFound, revisionTimestampFound,
|
||||
"property");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public RevisionInfoConfigurationResult configure(Configuration cfg, YReflectionManager reflectionManager) {
|
||||
Iterator<PersistentClass> classes = (Iterator<PersistentClass>) cfg.getClassMappings();
|
||||
boolean revisionEntityFound = false;
|
||||
RevisionInfoGenerator revisionInfoGenerator = null;
|
||||
|
||||
Class<?> revisionInfoClass = null;
|
||||
|
||||
while (classes.hasNext()) {
|
||||
PersistentClass pc = classes.next();
|
||||
YClass clazz;
|
||||
try {
|
||||
clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
RevisionEntity revisionEntity = clazz.getAnnotation(RevisionEntity.class);
|
||||
if (revisionEntity != null) {
|
||||
if (revisionEntityFound) {
|
||||
throw new MappingException("Only one entity may be annotated with @RevisionEntity!");
|
||||
}
|
||||
|
||||
// Checking if custom revision entity isn't versioned
|
||||
if (clazz.getAnnotation(Versioned.class) != null) {
|
||||
throw new MappingException("An entity annotated with @RevisionEntity cannot be versioned!");
|
||||
}
|
||||
|
||||
revisionEntityFound = true;
|
||||
|
||||
MutableBoolean revisionNumberFound = new MutableBoolean();
|
||||
MutableBoolean revisionTimestampFound = new MutableBoolean();
|
||||
|
||||
searchForRevisionInfoCfg(clazz, reflectionManager, revisionNumberFound, revisionTimestampFound);
|
||||
|
||||
if (!revisionNumberFound.isSet()) {
|
||||
throw new MappingException("An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionNumber!");
|
||||
}
|
||||
|
||||
if (!revisionTimestampFound.isSet()) {
|
||||
throw new MappingException("An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionTimestamp!");
|
||||
}
|
||||
|
||||
revisionInfoEntityName = pc.getEntityName();
|
||||
|
||||
revisionInfoClass = pc.getMappedClass();
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
|
||||
revisionEntity.value(), revisionInfoTimestampName);
|
||||
}
|
||||
}
|
||||
|
||||
// In case of a custom revision info generator, the mapping will be null.
|
||||
Document revisionInfoXmlMapping = null;
|
||||
|
||||
if (revisionInfoGenerator == null) {
|
||||
revisionInfoClass = DefaultRevisionEntity.class;
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
|
||||
RevisionListener.class, revisionInfoTimestampName);
|
||||
revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
|
||||
}
|
||||
|
||||
return new RevisionInfoConfigurationResult(
|
||||
revisionInfoGenerator, revisionInfoXmlMapping,
|
||||
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdName, revisionInfoTimestampName),
|
||||
generateRevisionInfoRelationMapping(),
|
||||
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdName), revisionInfoEntityName);
|
||||
}
|
||||
}
|
||||
|
||||
class RevisionInfoConfigurationResult {
|
||||
private final RevisionInfoGenerator revisionInfoGenerator;
|
||||
private final Document revisionInfoXmlMapping;
|
||||
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
||||
private final Element revisionInfoRelationMapping;
|
||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||
private final String revisionInfoEntityName;
|
||||
|
||||
RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
|
||||
Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
|
||||
Element revisionInfoRelationMapping,
|
||||
RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName) {
|
||||
this.revisionInfoGenerator = revisionInfoGenerator;
|
||||
this.revisionInfoXmlMapping = revisionInfoXmlMapping;
|
||||
this.revisionInfoQueryCreator = revisionInfoQueryCreator;
|
||||
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
||||
this.revisionInfoNumberReader = revisionInfoNumberReader;
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
}
|
||||
|
||||
public RevisionInfoGenerator getRevisionInfoGenerator() {
|
||||
return revisionInfoGenerator;
|
||||
}
|
||||
|
||||
public Document getRevisionInfoXmlMapping() {
|
||||
return revisionInfoXmlMapping;
|
||||
}
|
||||
|
||||
public RevisionInfoQueryCreator getRevisionInfoQueryCreator() {
|
||||
return revisionInfoQueryCreator;
|
||||
}
|
||||
|
||||
public Element getRevisionInfoRelationMapping() {
|
||||
return revisionInfoRelationMapping;
|
||||
}
|
||||
|
||||
public RevisionInfoNumberReader getRevisionInfoNumberReader() {
|
||||
return revisionInfoNumberReader;
|
||||
}
|
||||
|
||||
public String getRevisionInfoEntityName() {
|
||||
return revisionInfoEntityName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.jboss.envers.entities.EntitiesConfigurations;
|
||||
import org.jboss.envers.synchronization.VersionsSyncManager;
|
||||
import org.jboss.envers.tools.reflection.YReflectionManager;
|
||||
import org.jboss.envers.revisioninfo.RevisionInfoQueryCreator;
|
||||
import org.jboss.envers.revisioninfo.RevisionInfoNumberReader;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class VersionsConfiguration {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final VersionsEntitiesConfiguration verEntCfg;
|
||||
private final VersionsSyncManager versionsSyncManager;
|
||||
private final EntitiesConfigurations entCfg;
|
||||
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||
|
||||
public VersionsEntitiesConfiguration getVerEntCfg() {
|
||||
return verEntCfg;
|
||||
}
|
||||
|
||||
public VersionsSyncManager getSyncManager() {
|
||||
return versionsSyncManager;
|
||||
}
|
||||
|
||||
public GlobalConfiguration getGlobalCfg() {
|
||||
return globalCfg;
|
||||
}
|
||||
|
||||
public EntitiesConfigurations getEntCfg() {
|
||||
return entCfg;
|
||||
}
|
||||
|
||||
public RevisionInfoQueryCreator getRevisionInfoQueryCreator() {
|
||||
return revisionInfoQueryCreator;
|
||||
}
|
||||
|
||||
public RevisionInfoNumberReader getRevisionInfoNumberReader() {
|
||||
return revisionInfoNumberReader;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public VersionsConfiguration(Configuration cfg) {
|
||||
Properties properties = cfg.getProperties();
|
||||
|
||||
YReflectionManager reflectionManager = YReflectionManager.get(cfg);
|
||||
RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
|
||||
RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
|
||||
verEntCfg = new VersionsEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
||||
globalCfg = new GlobalConfiguration(properties);
|
||||
versionsSyncManager = new VersionsSyncManager(revInfoCfgResult.getRevisionInfoGenerator());
|
||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, verEntCfg,
|
||||
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private static Map<Configuration, VersionsConfiguration> cfgs
|
||||
= new WeakHashMap<Configuration, VersionsConfiguration>();
|
||||
|
||||
public synchronized static VersionsConfiguration getFor(Configuration cfg) {
|
||||
VersionsConfiguration verCfg = cfgs.get(cfg);
|
||||
|
||||
if (verCfg == null) {
|
||||
verCfg = new VersionsConfiguration(cfg);
|
||||
cfgs.put(cfg, verCfg);
|
||||
|
||||
cfg.buildMappings();
|
||||
}
|
||||
|
||||
return verCfg;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Configuration of versions entities - names of fields, entities and tables created to store versioning information.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class VersionsEntitiesConfiguration {
|
||||
private final String versionsTablePrefix;
|
||||
private final String versionsTableSuffix;
|
||||
|
||||
private final String originalIdPropName;
|
||||
|
||||
private final String revisionPropName;
|
||||
private final String revisionPropPath;
|
||||
|
||||
private final String revisionTypePropName;
|
||||
private final String revisionTypePropType;
|
||||
|
||||
private final String revisionInfoEntityName;
|
||||
|
||||
private final Map<String, String> customVersionsTablesNames;
|
||||
|
||||
public VersionsEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
|
||||
versionsTablePrefix = properties.getProperty("org.jboss.envers.versionsTablePrefix", "");
|
||||
versionsTableSuffix = properties.getProperty("org.jboss.envers.versionsTableSuffix", "_versions");
|
||||
|
||||
originalIdPropName = "originalId";
|
||||
|
||||
revisionPropName = properties.getProperty("org.jboss.envers.revisionFieldName", "_revision");
|
||||
|
||||
revisionTypePropName = properties.getProperty("org.jboss.envers.revisionTypeFieldName", "_revision_type");
|
||||
revisionTypePropType = "byte";
|
||||
|
||||
customVersionsTablesNames = new HashMap<String, String>();
|
||||
|
||||
revisionPropPath = originalIdPropName + "." + revisionPropName + ".id";
|
||||
}
|
||||
|
||||
public String getOriginalIdPropName() {
|
||||
return originalIdPropName;
|
||||
}
|
||||
|
||||
public String getRevisionPropName() {
|
||||
return revisionPropName;
|
||||
}
|
||||
|
||||
public String getRevisionPropPath() {
|
||||
return revisionPropPath;
|
||||
}
|
||||
|
||||
public String getRevisionTypePropName() {
|
||||
return revisionTypePropName;
|
||||
}
|
||||
|
||||
public String getRevisionTypePropType() {
|
||||
return revisionTypePropType;
|
||||
}
|
||||
|
||||
public String getRevisionInfoEntityName() {
|
||||
return revisionInfoEntityName;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public void addCustomVersionsTableName(String entityName, String tableName) {
|
||||
customVersionsTablesNames.put(entityName, tableName);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public String getVersionsEntityName(String entityName) {
|
||||
return versionsTablePrefix + entityName + versionsTableSuffix;
|
||||
}
|
||||
|
||||
public String getVersionsTableName(String entityName, String tableName) {
|
||||
String customHistoryTableName = customVersionsTablesNames.get(entityName);
|
||||
if (customHistoryTableName == null) {
|
||||
return versionsTablePrefix + tableName + versionsTableSuffix;
|
||||
}
|
||||
|
||||
return customHistoryTableName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import javax.persistence.Version;
|
||||
import javax.persistence.MapKey;
|
||||
|
||||
import org.jboss.envers.configuration.GlobalConfiguration;
|
||||
import org.jboss.envers.tools.reflection.YClass;
|
||||
import org.jboss.envers.tools.reflection.YProperty;
|
||||
import org.jboss.envers.tools.reflection.YReflectionManager;
|
||||
import org.jboss.envers.*;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.MappingException;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* A helper class to read versioning meta-data from annotations on a persistent class.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public final class AnnotationsMetadataReader {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final YReflectionManager reflectionManager;
|
||||
private final PersistentClass pc;
|
||||
|
||||
/**
|
||||
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
|
||||
* method.
|
||||
*/
|
||||
private final PersistentClassVersioningData versioningData;
|
||||
|
||||
public AnnotationsMetadataReader(GlobalConfiguration globalCfg, YReflectionManager reflectionManager,
|
||||
PersistentClass pc) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.reflectionManager = reflectionManager;
|
||||
this.pc = pc;
|
||||
|
||||
versioningData = new PersistentClassVersioningData();
|
||||
}
|
||||
|
||||
private void addPropertyVersioned(YProperty property) {
|
||||
Versioned ver = property.getAnnotation(Versioned.class);
|
||||
if (ver != null) {
|
||||
versioningData.propertyStoreInfo.propertyStores.put(property.getName(), ver.modStore());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyMapKey(YProperty property) {
|
||||
MapKey mapKey = property.getAnnotation(MapKey.class);
|
||||
if (mapKey != null) {
|
||||
versioningData.mapKeys.put(property.getName(), mapKey.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyUnversioned(YProperty property) {
|
||||
// check if a property is declared as unversioned to exclude it
|
||||
// useful if a class is versioned but some properties should be excluded
|
||||
Unversioned unVer = property.getAnnotation(Unversioned.class);
|
||||
if (unVer != null) {
|
||||
versioningData.unversionedProperties.add(property.getName());
|
||||
} else {
|
||||
// if the optimistic locking field has to be unversioned and the current property
|
||||
// is the optimistic locking field, add it to the unversioned properties list
|
||||
if (globalCfg.isUnversionedOptimisticLockingField()) {
|
||||
Version jpaVer = property.getAnnotation(Version.class);
|
||||
if (jpaVer != null) {
|
||||
versioningData.unversionedProperties.add(property.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyJoinTables(YProperty property) {
|
||||
VersionsJoinTable joinTable = property.getAnnotation(VersionsJoinTable.class);
|
||||
if (joinTable != null) {
|
||||
versioningData.versionsJoinTables.put(property.getName(), joinTable);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFromProperties(Iterable<YProperty> properties) {
|
||||
for (YProperty property : properties) {
|
||||
addPropertyVersioned(property);
|
||||
addPropertyUnversioned(property);
|
||||
addPropertyJoinTables(property);
|
||||
addPropertyMapKey(property);
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertiesFromClass(YClass clazz) {
|
||||
YClass superclazz = clazz.getSuperclass();
|
||||
if (!"java.lang.Object".equals(superclazz.getName())) {
|
||||
addPropertiesFromClass(superclazz);
|
||||
}
|
||||
|
||||
addFromProperties(clazz.getDeclaredProperties("field"));
|
||||
addFromProperties(clazz.getDeclaredProperties("property"));
|
||||
}
|
||||
|
||||
private void addDefaultVersioned(YClass clazz) {
|
||||
Versioned defaultVersioned = clazz.getAnnotation(Versioned.class);
|
||||
|
||||
if (defaultVersioned != null) {
|
||||
versioningData.propertyStoreInfo.defaultStore = defaultVersioned.modStore();
|
||||
}
|
||||
}
|
||||
|
||||
private void addVersionsTable(YClass clazz) {
|
||||
VersionsTable versionsTable = clazz.getAnnotation(VersionsTable.class);
|
||||
if (versionsTable != null) {
|
||||
versioningData.versionsTable = versionsTable;
|
||||
} else {
|
||||
versioningData.versionsTable = getDefaultVersionsTable();
|
||||
}
|
||||
}
|
||||
|
||||
private void addVersionsSecondaryTables(YClass clazz) {
|
||||
// Getting information on secondary tables
|
||||
SecondaryVersionsTable secondaryVersionsTable1 = clazz.getAnnotation(SecondaryVersionsTable.class);
|
||||
if (secondaryVersionsTable1 != null) {
|
||||
versioningData.secondaryTableDictionary.put(secondaryVersionsTable1.secondaryTableName(),
|
||||
secondaryVersionsTable1.secondaryVersionsTableName());
|
||||
}
|
||||
|
||||
SecondaryVersionsTables secondaryVersionsTables = clazz.getAnnotation(SecondaryVersionsTables.class);
|
||||
if (secondaryVersionsTables != null) {
|
||||
for (SecondaryVersionsTable secondaryVersionsTable2 : secondaryVersionsTables.value()) {
|
||||
versioningData.secondaryTableDictionary.put(secondaryVersionsTable2.secondaryTableName(),
|
||||
secondaryVersionsTable2.secondaryVersionsTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PersistentClassVersioningData getVersioningData() {
|
||||
if (pc.getClassName() == null) {
|
||||
return versioningData;
|
||||
}
|
||||
|
||||
try {
|
||||
YClass clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
|
||||
|
||||
addDefaultVersioned(clazz);
|
||||
addPropertiesFromClass(clazz);
|
||||
addVersionsTable(clazz);
|
||||
addVersionsSecondaryTables(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
return versioningData;
|
||||
}
|
||||
|
||||
private VersionsTable getDefaultVersionsTable() {
|
||||
return new VersionsTable() {
|
||||
public String value() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.mapping.*;
|
||||
import org.hibernate.type.*;
|
||||
import org.hibernate.util.StringHelper;
|
||||
import org.jboss.envers.entities.mapper.SimpleMapperBuilder;
|
||||
import org.jboss.envers.entities.mapper.CompositeMapperBuilder;
|
||||
import org.jboss.envers.ModificationStore;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Generates metadata for basic properties: immutable types (including enums) and components
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class BasicMetadataGenerator {
|
||||
boolean addBasic(Element parent, String name, Value value, CompositeMapperBuilder mapper,
|
||||
ModificationStore store, String entityName, boolean insertable, boolean key) {
|
||||
Type type = value.getType();
|
||||
|
||||
if (type instanceof ComponentType) {
|
||||
addComponent(parent, name, value, mapper, entityName, key);
|
||||
return true;
|
||||
} else {
|
||||
return addBasicNoComponent(parent, name, value, mapper, store, insertable, key);
|
||||
}
|
||||
}
|
||||
|
||||
boolean addBasicNoComponent(Element parent, String name, Value value, SimpleMapperBuilder mapper,
|
||||
ModificationStore store, boolean insertable, boolean key) {
|
||||
Type type = value.getType();
|
||||
|
||||
if (type instanceof ImmutableType || type instanceof MutableType) {
|
||||
addSimpleValue(parent, name, value, mapper, store, insertable, key);
|
||||
} else if (type instanceof CustomType || type instanceof CompositeCustomType) {
|
||||
addCustomValue(parent, name, value, mapper, store, insertable, key);
|
||||
} else if ("org.hibernate.type.PrimitiveByteArrayBlobType".equals(type.getClass().getName())) {
|
||||
addSimpleValue(parent, name, value, mapper, store, insertable, key);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addSimpleValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
|
||||
ModificationStore store, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, name,
|
||||
value.getType().getName(), insertable, key);
|
||||
MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
|
||||
}
|
||||
|
||||
// A null mapper means that we only want to add xml mappings
|
||||
if (mapper != null) {
|
||||
mapper.add(name, store);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addCustomValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
|
||||
ModificationStore store, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, name,
|
||||
null, insertable, key);
|
||||
|
||||
//CustomType propertyType = (CustomType) value.getType();
|
||||
|
||||
Element type_mapping = prop_mapping.addElement("type");
|
||||
type_mapping.addAttribute("name", value.getType().getName());
|
||||
|
||||
if (value instanceof SimpleValue) {
|
||||
Properties typeParameters = ((SimpleValue) value).getTypeParameters();
|
||||
if (typeParameters != null) {
|
||||
for (java.util.Map.Entry paramKeyValue : typeParameters.entrySet()) {
|
||||
Element type_param = type_mapping.addElement("param");
|
||||
type_param.addAttribute("name", (String) paramKeyValue.getKey());
|
||||
type_param.setText((String) paramKeyValue.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
|
||||
}
|
||||
|
||||
if (mapper != null) {
|
||||
mapper.add(name, store);
|
||||
}
|
||||
}
|
||||
|
||||
private void addComponentClassName(Element any_mapping, Component comp) {
|
||||
if (StringHelper.isNotEmpty(comp.getComponentClassName())) {
|
||||
any_mapping.addAttribute("class", comp.getComponentClassName());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addComponent(Element parent, String name, Value value, CompositeMapperBuilder mapper,
|
||||
String entityName, boolean key) {
|
||||
Element component_mapping = null;
|
||||
Component prop_component = (Component) value;
|
||||
|
||||
if (parent != null) {
|
||||
/*
|
||||
TODO: investigate relations inside components
|
||||
if (!firstPass) {
|
||||
// The required element already exists.
|
||||
Iterator<Element> iter = parent.elementIterator("component");
|
||||
while (iter.hasNext()) {
|
||||
Element child = iter.next();
|
||||
if (child.attribute("name").getText().equals(name)) {
|
||||
component_mapping = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (component_mapping == null) {
|
||||
throw new VersionsException("Element for component not found during second pass!");
|
||||
}
|
||||
} else {
|
||||
*/
|
||||
|
||||
component_mapping = parent.addElement("component");
|
||||
component_mapping.addAttribute("name", name);
|
||||
|
||||
addComponentClassName(component_mapping, prop_component);
|
||||
}
|
||||
|
||||
CompositeMapperBuilder componentMapper = mapper.addComposite(name);
|
||||
|
||||
Iterator<Property> properties = (Iterator<Property>) prop_component.getPropertyIterator();
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
addBasic(component_mapping, property.getName(), property.getValue(), componentMapper,
|
||||
ModificationStore.FULL, entityName, property.isInsertable(), key);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,490 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.hibernate.mapping.*;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.type.*;
|
||||
import org.jboss.envers.entities.mapper.CompositeMapperBuilder;
|
||||
import org.jboss.envers.entities.mapper.relation.*;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.proxy.*;
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.query.OneVersionsEntityQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.component.*;
|
||||
import org.jboss.envers.entities.EntityConfiguration;
|
||||
import org.jboss.envers.entities.IdMappingData;
|
||||
import org.jboss.envers.tools.Tools;
|
||||
import org.jboss.envers.tools.StringTools;
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.VersionsJoinTable;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import java.util.*;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* Generates metadata for a collection-valued property.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class CollectionMetadataGenerator {
|
||||
private final VersionsMetadataGenerator mainGenerator;
|
||||
private final String propertyName;
|
||||
private final Collection propertyValue;
|
||||
private final CompositeMapperBuilder currentMapper;
|
||||
private final String referencingEntityName;
|
||||
private final EntityXmlMappingData xmlMappingData;
|
||||
private final VersionsJoinTable joinTable;
|
||||
private final String mapKey;
|
||||
|
||||
private final EntityConfiguration referencingEntityConfiguration;
|
||||
/**
|
||||
* Null if this collection isn't a relation to another entity.
|
||||
*/
|
||||
private final String referencedEntityName;
|
||||
|
||||
/**
|
||||
* @param mainGenerator Main generator, giving access to configuration and the basic mapper.
|
||||
* @param propertyName Name of the property that references the collection in the referencing entity.
|
||||
* @param propertyValue Value of the collection, as mapped by Hibernate.
|
||||
* @param currentMapper Mapper, to which the appropriate {@link org.jboss.envers.entities.mapper.PropertyMapper}
|
||||
* will be added.
|
||||
* @param referencingEntityName Name of the entity that owns this collection.
|
||||
* @param xmlMappingData In case this collection requires a middle table, additional mapping documents will
|
||||
* be created using this object.
|
||||
* @param joinTable User data for the middle (join) table. <code>null</code> if the user didn't specify it.
|
||||
* @param mapKey The value of the name() property of the MapKey annotation on this property. Null, if this
|
||||
* property isn't annotated with this annotation.
|
||||
*/
|
||||
public CollectionMetadataGenerator(VersionsMetadataGenerator mainGenerator, String propertyName,
|
||||
Collection propertyValue, CompositeMapperBuilder currentMapper,
|
||||
String referencingEntityName, EntityXmlMappingData xmlMappingData,
|
||||
VersionsJoinTable joinTable, String mapKey) {
|
||||
this.mainGenerator = mainGenerator;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyValue = propertyValue;
|
||||
this.currentMapper = currentMapper;
|
||||
this.referencingEntityName = referencingEntityName;
|
||||
this.xmlMappingData = xmlMappingData;
|
||||
this.joinTable = joinTable == null ? getDefaultVersionsJoinTable() : joinTable;
|
||||
this.mapKey = mapKey;
|
||||
|
||||
referencingEntityConfiguration = mainGenerator.getEntitiesConfigurations().get(referencingEntityName);
|
||||
if (referencingEntityConfiguration == null) {
|
||||
throw new MappingException("Unable to read versioning configuration for " + referencingEntityName + "!");
|
||||
}
|
||||
|
||||
referencedEntityName = getReferencedEntityName(propertyValue.getElement());
|
||||
}
|
||||
|
||||
private String getReferencedEntityName(Value value) {
|
||||
if (value instanceof ToOne) {
|
||||
return ((ToOne) value).getReferencedEntityName();
|
||||
} else if (value instanceof OneToMany) {
|
||||
return ((OneToMany) value).getReferencedEntityName();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void addCollection() {
|
||||
Type type = propertyValue.getType();
|
||||
|
||||
if ((type instanceof BagType || type instanceof SetType || type instanceof MapType) &&
|
||||
(propertyValue.getElement() instanceof OneToMany) && (propertyValue.isInverse())) {
|
||||
// A one-to-many relation mapped using @ManyToOne and @OneToMany(mappedBy="...")
|
||||
addOneToManyAttached();
|
||||
} else {
|
||||
// All other kinds of relations require a middle (join) table.
|
||||
addWithMiddleTable();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addOneToManyAttached() {
|
||||
String mappedBy = getMappedBy(propertyValue);
|
||||
|
||||
EntityConfiguration referencedEntityConfiguration = mainGenerator.getEntitiesConfigurations()
|
||||
.get(referencedEntityName);
|
||||
|
||||
IdMappingData referencedIdMapping = referencedEntityConfiguration.getIdMappingData();
|
||||
IdMappingData referencingIdMapping = referencingEntityConfiguration.getIdMappingData();
|
||||
|
||||
// Generating the id mappers data for the referencing side of the relation.
|
||||
MiddleIdData referencingIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencingIdMapping,
|
||||
mappedBy + "_", referencingEntityName);
|
||||
|
||||
// And for the referenced side. The prefixed mapper won't be used (as this collection isn't persisted
|
||||
// in a join table, so the prefix value is arbitrary).
|
||||
MiddleIdData referencedIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencedIdMapping,
|
||||
null, referencedEntityName);
|
||||
|
||||
// Generating the element mapping.
|
||||
MiddleComponentData elementComponentData = new MiddleComponentData(
|
||||
new MiddleRelatedComponentMapper(referencedIdData), 0);
|
||||
|
||||
// Generating the index mapping, if an index exists. It can only exists in case a javax.persistence.MapKey
|
||||
// annotation is present on the entity. So the middleEntityXml will be not be used. The queryGeneratorBuilder
|
||||
// will only be checked for nullnes.
|
||||
MiddleComponentData indexComponentData = addIndex(null, null);
|
||||
|
||||
// Generating the query generator - it should read directly from the related entity.
|
||||
RelationQueryGenerator queryGenerator = new OneVersionsEntityQueryGenerator(mainGenerator.getGlobalCfg(),
|
||||
mainGenerator.getVerEntCfg(), referencingIdData, referencedEntityName,
|
||||
referencedIdMapping.getIdMapper());
|
||||
|
||||
// Creating common mapper data.
|
||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), referencedEntityName, propertyName,
|
||||
referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
|
||||
|
||||
// Storing information about this relation.
|
||||
referencingEntityConfiguration.addToManyNotOwningRelation(propertyName, mappedBy,
|
||||
referencedEntityName, referencingIdData.getPrefixedMapper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds mapping of the id of a related entity to the given xml mapping, prefixing the id with the given prefix.
|
||||
* @param xmlMapping Mapping, to which to add the xml.
|
||||
* @param prefix Prefix for the names of properties which will be prepended to properties that form the id.
|
||||
* @param columnNameIterator Iterator over the column names that will be used for properties that form the id.
|
||||
* @param relatedIdMapping Id mapping data of the related entity.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addRelatedToXmlMapping(Element xmlMapping, String prefix,
|
||||
MetadataTools.ColumnNameIterator columnNameIterator,
|
||||
IdMappingData relatedIdMapping) {
|
||||
Element properties = (Element) relatedIdMapping.getXmlRelationMapping().clone();
|
||||
MetadataTools.prefixNamesInPropertyElement(properties, prefix, columnNameIterator, true);
|
||||
for (Element idProperty : (java.util.List<Element>) properties.elements()) {
|
||||
xmlMapping.add((Element) idProperty.clone());
|
||||
}
|
||||
}
|
||||
|
||||
private String getMiddleTableName(Collection value, String entityName) {
|
||||
// We check how Hibernate maps the collection.
|
||||
if (value.getElement() instanceof OneToMany && !value.isInverse()) {
|
||||
// This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a
|
||||
// middle table for mapping this relation.
|
||||
return StringTools.getLastComponent(entityName) + "_" + StringTools.getLastComponent(getReferencedEntityName(value.getElement()));
|
||||
} else {
|
||||
// Hibernate uses a middle table for mapping this relation, so we get it's name directly.
|
||||
return value.getCollectionTable().getName();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addWithMiddleTable() {
|
||||
// Generating the name of the middle table
|
||||
String versionsMiddleTableName;
|
||||
String versionsMiddleEntityName;
|
||||
if (!StringTools.isEmpty(joinTable.name())) {
|
||||
versionsMiddleTableName = joinTable.name();
|
||||
versionsMiddleEntityName = joinTable.name();
|
||||
} else {
|
||||
String middleTableName = getMiddleTableName(propertyValue, referencingEntityName);
|
||||
versionsMiddleTableName = mainGenerator.getVerEntCfg().getVersionsTableName(null, middleTableName);
|
||||
versionsMiddleEntityName = mainGenerator.getVerEntCfg().getVersionsEntityName(middleTableName);
|
||||
}
|
||||
|
||||
// Generating the XML mapping for the middle entity, only if the relation isn't inverse.
|
||||
// If the relation is inverse, will be later checked by comparing middleEntityXml with null.
|
||||
Element middleEntityXml;
|
||||
if (!propertyValue.isInverse()) {
|
||||
middleEntityXml = createMiddleEntityXml(versionsMiddleTableName, versionsMiddleEntityName);
|
||||
} else {
|
||||
middleEntityXml = null;
|
||||
}
|
||||
|
||||
// ******
|
||||
// Generating the mapping for the referencing entity (it must be an entity).
|
||||
// ******
|
||||
// Getting the id-mapping data of the referencing entity (the entity that "owns" this collection).
|
||||
IdMappingData referencingIdMapping = referencingEntityConfiguration.getIdMappingData();
|
||||
|
||||
// Only valid for an inverse relation; null otherwise.
|
||||
String mappedBy;
|
||||
|
||||
// The referencing prefix is always for a related entity. So it has always the "_" at the end added.
|
||||
String referencingPrefixRelated;
|
||||
String referencedPrefix;
|
||||
|
||||
if (propertyValue.isInverse()) {
|
||||
// If the relation is inverse, then referencedEntityName is not null.
|
||||
mappedBy = getMappedBy(propertyValue.getCollectionTable(), mainGenerator.getCfg().getClassMapping(referencedEntityName));
|
||||
|
||||
referencingPrefixRelated = mappedBy + "_";
|
||||
referencedPrefix = StringTools.getLastComponent(referencedEntityName);
|
||||
} else {
|
||||
mappedBy = null;
|
||||
|
||||
referencingPrefixRelated = StringTools.getLastComponent(referencingEntityName) + "_";
|
||||
referencedPrefix = referencedEntityName == null ? "element" : propertyName;
|
||||
}
|
||||
|
||||
// Storing the id data of the referencing entity: original mapper, prefixed mapper and entity name.
|
||||
MiddleIdData referencingIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencingIdMapping,
|
||||
referencingPrefixRelated, referencingEntityName);
|
||||
|
||||
// Creating a query generator builder, to which additional id data will be added, in case this collection
|
||||
// references some entities (either from the element or index). At the end, this will be used to build
|
||||
// a query generator to read the raw data collection from the middle table.
|
||||
QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(),
|
||||
mainGenerator.getVerEntCfg(), referencingIdData, versionsMiddleEntityName);
|
||||
|
||||
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
||||
if (middleEntityXml != null) {
|
||||
// Adding related-entity (in this case: the referencing's entity id) id mapping to the xml.
|
||||
addRelatedToXmlMapping(middleEntityXml, referencingPrefixRelated,
|
||||
MetadataTools.getColumnNameIterator(propertyValue.getKey().getColumnIterator()),
|
||||
referencingIdMapping);
|
||||
}
|
||||
|
||||
// ******
|
||||
// Generating the element mapping.
|
||||
// ******
|
||||
MiddleComponentData elementComponentData = addValueToMiddleTable(propertyValue.getElement(), middleEntityXml,
|
||||
queryGeneratorBuilder, referencedPrefix, joinTable.inverseJoinColumns());
|
||||
|
||||
// ******
|
||||
// Generating the index mapping, if an index exists.
|
||||
// ******
|
||||
MiddleComponentData indexComponentData = addIndex(middleEntityXml, queryGeneratorBuilder);
|
||||
|
||||
// ******
|
||||
// Generating the property mapper.
|
||||
// ******
|
||||
// Building the query generator.
|
||||
RelationQueryGenerator queryGenerator = queryGeneratorBuilder.build(elementComponentData, indexComponentData);
|
||||
|
||||
// Creating common data
|
||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), versionsMiddleEntityName, propertyName, referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
|
||||
|
||||
// ******
|
||||
// Storing information about this relation.
|
||||
// ******
|
||||
storeMiddleEntityRelationInformation(mappedBy);
|
||||
}
|
||||
|
||||
private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
|
||||
if (propertyValue instanceof IndexedCollection) {
|
||||
IndexedCollection indexedValue = (IndexedCollection) propertyValue;
|
||||
if (mapKey == null) {
|
||||
// This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
|
||||
return addValueToMiddleTable(indexedValue.getIndex(), middleEntityXml,
|
||||
queryGeneratorBuilder, "mapkey", null);
|
||||
} else {
|
||||
IdMappingData referencedIdMapping = mainGenerator.getEntitiesConfigurations()
|
||||
.get(referencedEntityName).getIdMappingData();
|
||||
int currentIndex = queryGeneratorBuilder == null ? 0 : queryGeneratorBuilder.getCurrentIndex();
|
||||
if ("".equals(mapKey)) {
|
||||
// The key of the map is the id of the entity.
|
||||
return new MiddleComponentData(new MiddleMapKeyIdComponentMapper(mainGenerator.getVerEntCfg(),
|
||||
referencedIdMapping.getIdMapper()), currentIndex);
|
||||
} else {
|
||||
// The key of the map is a property of the entity.
|
||||
return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey), currentIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No index - creating a dummy mapper.
|
||||
return new MiddleComponentData(new MiddleDummyComponentMapper(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param value Value, which should be mapped to the middle-table, either as a relation to another entity,
|
||||
* or as a simple value.
|
||||
* @param xmlMapping If not <code>null</code>, xml mapping for this value is added to this element.
|
||||
* @param queryGeneratorBuilder In case <code>value</code> is a relation to another entity, information about it
|
||||
* should be added to the given.
|
||||
* @param prefix Prefix for proeprty names of related entities identifiers.
|
||||
* @param joinColumns Names of columns to use in the xml mapping, if this array isn't null and has any elements.
|
||||
* @return Data for mapping this component.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private MiddleComponentData addValueToMiddleTable(Value value, Element xmlMapping,
|
||||
QueryGeneratorBuilder queryGeneratorBuilder,
|
||||
String prefix, JoinColumn[] joinColumns) {
|
||||
Type type = value.getType();
|
||||
if (type instanceof ManyToOneType) {
|
||||
String prefixRelated = prefix + "_";
|
||||
|
||||
String referencedEntityName = getReferencedEntityName(value);
|
||||
IdMappingData referencedIdMapping = mainGenerator.getEntitiesConfigurations()
|
||||
.get(referencedEntityName).getIdMappingData();
|
||||
|
||||
// Adding related-entity (in this case: the referenced entities id) id mapping to the xml only if the
|
||||
// relation isn't inverse (so when <code>xmlMapping</code> is not null).
|
||||
if (xmlMapping != null) {
|
||||
addRelatedToXmlMapping(xmlMapping, prefixRelated,
|
||||
joinColumns != null && joinColumns.length > 0
|
||||
? MetadataTools.getColumnNameIterator(joinColumns)
|
||||
: MetadataTools.getColumnNameIterator(value.getColumnIterator()),
|
||||
referencedIdMapping);
|
||||
}
|
||||
|
||||
// Storing the id data of the referenced entity: original mapper, prefixed mapper and entity name.
|
||||
MiddleIdData referencedIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencedIdMapping,
|
||||
prefixRelated, referencedEntityName);
|
||||
// And adding it to the generator builder.
|
||||
queryGeneratorBuilder.addRelation(referencedIdData);
|
||||
|
||||
return new MiddleComponentData(new MiddleRelatedComponentMapper(referencedIdData),
|
||||
queryGeneratorBuilder.getCurrentIndex());
|
||||
} else {
|
||||
// Last but one parameter: collection components are always insertable
|
||||
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(xmlMapping, prefix, value, null,
|
||||
ModificationStore.FULL, true, true);
|
||||
|
||||
if (mapped) {
|
||||
// Simple values are always stored in the first item of the array returned by the query generator.
|
||||
return new MiddleComponentData(new MiddleSimpleComponentMapper(mainGenerator.getVerEntCfg(), prefix), 0);
|
||||
} else {
|
||||
mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
|
||||
// Impossible to get here.
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData,
|
||||
MiddleComponentData indexComponentData) {
|
||||
Type type = propertyValue.getType();
|
||||
if (type instanceof SortedSetType) {
|
||||
currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
TreeSet.class, SortedSetProxy.class, elementComponentData));
|
||||
} else if (type instanceof SetType) {
|
||||
currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
HashSet.class, SetProxy.class, elementComponentData));
|
||||
} else if (type instanceof SortedMapType) {
|
||||
// Indexed collection, so <code>indexComponentData</code> is not null.
|
||||
currentMapper.addComposite(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
TreeMap.class, SortedMapProxy.class, elementComponentData, indexComponentData));
|
||||
} else if (type instanceof MapType) {
|
||||
// Indexed collection, so <code>indexComponentData</code> is not null.
|
||||
currentMapper.addComposite(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
HashMap.class, MapProxy.class, elementComponentData, indexComponentData));
|
||||
} else if (type instanceof BagType) {
|
||||
currentMapper.addComposite(propertyName, new BasicCollectionMapper<List>(commonCollectionMapperData,
|
||||
ArrayList.class, ListProxy.class, elementComponentData));
|
||||
} else if (type instanceof ListType) {
|
||||
// Indexed collection, so <code>indexComponentData</code> is not null.
|
||||
currentMapper.addComposite(propertyName, new ListCollectionMapper(commonCollectionMapperData,
|
||||
elementComponentData, indexComponentData));
|
||||
} else {
|
||||
mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
private void storeMiddleEntityRelationInformation(String mappedBy) {
|
||||
// Only if this is a relation (when there is a referenced entity).
|
||||
if (referencedEntityName != null) {
|
||||
if (propertyValue.isInverse()) {
|
||||
referencingEntityConfiguration.addToManyMiddleNotOwningRelation(propertyName, mappedBy, referencedEntityName);
|
||||
} else {
|
||||
referencingEntityConfiguration.addToManyMiddleRelation(propertyName, referencedEntityName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Element createMiddleEntityXml(String versionsMiddleTableName, String versionsMiddleEntityName) {
|
||||
String schema = StringTools.isEmpty(joinTable.schema()) ? propertyValue.getCollectionTable().getSchema() : joinTable.schema();
|
||||
String catalog = StringTools.isEmpty(joinTable.catalog()) ? propertyValue.getCollectionTable().getCatalog() : joinTable.catalog();
|
||||
|
||||
Element middleEntityXml = MetadataTools.createEntity(xmlMappingData.newAdditionalMapping(),
|
||||
versionsMiddleEntityName, versionsMiddleTableName, schema, catalog, null);
|
||||
Element middleEntityXmlId = middleEntityXml.addElement("composite-id");
|
||||
|
||||
middleEntityXmlId.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
|
||||
|
||||
// Adding the revision number as a foreign key to the revision info entity to the composite id of the
|
||||
// middle table.
|
||||
mainGenerator.addRevisionInfoRelation(middleEntityXmlId);
|
||||
|
||||
// Adding the revision type property to the entity xml.
|
||||
mainGenerator.addRevisionType(middleEntityXml);
|
||||
|
||||
// All other properties should also be part of the primary key of the middle entity.
|
||||
return middleEntityXmlId;
|
||||
}
|
||||
|
||||
private VersionsJoinTable getDefaultVersionsJoinTable() {
|
||||
return new VersionsJoinTable() {
|
||||
public String name() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public JoinColumn[] inverseJoinColumns() { return new JoinColumn[0]; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String getMappedBy(Collection collectionValue) {
|
||||
Iterator<Property> assocClassProps =
|
||||
((OneToMany) collectionValue.getElement()).getAssociatedClass().getPropertyIterator();
|
||||
|
||||
while (assocClassProps.hasNext()) {
|
||||
Property property = assocClassProps.next();
|
||||
|
||||
if (Tools.iteratorsContentEqual(property.getValue().getColumnIterator(),
|
||||
collectionValue.getKey().getColumnIterator())) {
|
||||
return property.getName();
|
||||
}
|
||||
}
|
||||
|
||||
throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
|
||||
+ referencingEntityName + "!");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String getMappedBy(Table collectionTable, PersistentClass referencedClass) {
|
||||
Iterator<Property> properties = referencedClass.getPropertyIterator();
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
if (property.getValue() instanceof Collection) {
|
||||
// The equality is intentional. We want to find a collection property with the same collection table.
|
||||
//noinspection ObjectEquality
|
||||
if (((Collection) property.getValue()).getCollectionTable() == collectionTable) {
|
||||
return property.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
|
||||
+ referencingEntityName + "!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EntityXmlMappingData {
|
||||
private Document mainXmlMapping;
|
||||
private List<Document> additionalXmlMappings;
|
||||
|
||||
public EntityXmlMappingData() {
|
||||
mainXmlMapping = DocumentHelper.createDocument();
|
||||
additionalXmlMappings = new ArrayList<Document>();
|
||||
}
|
||||
|
||||
public Document getMainXmlMapping() {
|
||||
return mainXmlMapping;
|
||||
}
|
||||
|
||||
public List<Document> getAdditionalXmlMappings() {
|
||||
return additionalXmlMappings;
|
||||
}
|
||||
|
||||
public Document newAdditionalMapping() {
|
||||
Document additionalMapping = DocumentHelper.createDocument();
|
||||
additionalXmlMappings.add(additionalMapping);
|
||||
|
||||
return additionalMapping;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.tree.DefaultElement;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.ImmutableType;
|
||||
import org.hibernate.MappingException;
|
||||
import org.jboss.envers.entities.mapper.SimpleMapperBuilder;
|
||||
import org.jboss.envers.entities.mapper.id.SimpleIdMapperBuilder;
|
||||
import org.jboss.envers.entities.mapper.id.MultipleIdMapper;
|
||||
import org.jboss.envers.entities.mapper.id.EmbeddedIdMapper;
|
||||
import org.jboss.envers.entities.mapper.id.SingleIdMapper;
|
||||
import org.jboss.envers.entities.IdMappingData;
|
||||
import org.jboss.envers.ModificationStore;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Generates metadata for primary identifiers (ids) of versions entities.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class IdMetadataGenerator {
|
||||
private final VersionsMetadataGenerator mainGenerator;
|
||||
|
||||
IdMetadataGenerator(VersionsMetadataGenerator versionsMetadataGenerator) {
|
||||
mainGenerator = versionsMetadataGenerator;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addIdProperties(Element parent, Iterator<Property> properties, SimpleMapperBuilder mapper, boolean key) {
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
Type propertyType = property.getType();
|
||||
if (!"_identifierMapper".equals(property.getName())) {
|
||||
if (propertyType instanceof ImmutableType) {
|
||||
// Last but one parameter: ids are always insertable
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(parent, property.getName(),
|
||||
property.getValue(), mapper, ModificationStore.FULL, true, key);
|
||||
} else {
|
||||
throw new MappingException("Type not supported: " + propertyType.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
IdMappingData addId(PersistentClass pc) {
|
||||
// Xml mapping which will be used for relations
|
||||
Element rel_id_mapping = new DefaultElement("properties");
|
||||
// Xml mapping which will be used for the primary key of the versions table
|
||||
Element orig_id_mapping = new DefaultElement("composite-id");
|
||||
|
||||
Property id_prop = pc.getIdentifierProperty();
|
||||
Component id_mapper = pc.getIdentifierMapper();
|
||||
|
||||
SimpleIdMapperBuilder mapper;
|
||||
if (id_mapper != null) {
|
||||
// Multiple id
|
||||
|
||||
mapper = new MultipleIdMapper(((Component) pc.getIdentifier()).getComponentClassName());
|
||||
addIdProperties(rel_id_mapping, (Iterator<Property>) id_mapper.getPropertyIterator(), mapper, false);
|
||||
|
||||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
addIdProperties(orig_id_mapping, (Iterator<Property>) id_mapper.getPropertyIterator(), null, true);
|
||||
} else if (id_prop.isComposite()) {
|
||||
// Embedded id
|
||||
|
||||
Component id_component = (Component) id_prop.getValue();
|
||||
|
||||
mapper = new EmbeddedIdMapper(id_prop.getName(), id_component.getComponentClassName());
|
||||
addIdProperties(rel_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), mapper, false);
|
||||
|
||||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
addIdProperties(orig_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), null, true);
|
||||
} else {
|
||||
// Single id
|
||||
|
||||
mapper = new SingleIdMapper();
|
||||
|
||||
// Last but one parameter: ids are always insertable
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(rel_id_mapping, id_prop.getName(),
|
||||
id_prop.getValue(), mapper, ModificationStore.FULL, true, false);
|
||||
|
||||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(orig_id_mapping, id_prop.getName(),
|
||||
id_prop.getValue(), null, ModificationStore.FULL, true, true);
|
||||
}
|
||||
|
||||
orig_id_mapping.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
|
||||
|
||||
// Adding a relation to the revision entity (effectively: the "revision number" property)
|
||||
mainGenerator.addRevisionInfoRelation(orig_id_mapping);
|
||||
|
||||
return new IdMappingData(mapper, orig_id_mapping, rel_id_mapping);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.hibernate.mapping.*;
|
||||
import org.hibernate.MappingException;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public enum InheritanceType {
|
||||
NONE,
|
||||
JOINED,
|
||||
SINGLE,
|
||||
TABLE_PER_CLASS;
|
||||
|
||||
/**
|
||||
* @param pc The class for which to get the inheritance type.
|
||||
* @return The inheritance type of this class. NONE, if this class does not inherit from
|
||||
* another persisten class.
|
||||
*/
|
||||
public static InheritanceType get(PersistentClass pc) {
|
||||
PersistentClass superclass = pc.getSuperclass();
|
||||
if (superclass == null) {
|
||||
return InheritanceType.NONE;
|
||||
}
|
||||
|
||||
// We assume that every subclass is of the same type.
|
||||
Subclass subclass = (Subclass) superclass.getSubclassIterator().next();
|
||||
|
||||
if (subclass instanceof SingleTableSubclass) {
|
||||
return InheritanceType.SINGLE;
|
||||
} else if (subclass instanceof JoinedSubclass) {
|
||||
return InheritanceType.JOINED;
|
||||
} else if (subclass instanceof UnionSubclass) {
|
||||
return InheritanceType.TABLE_PER_CLASS;
|
||||
}
|
||||
|
||||
throw new MappingException("Unknown subclass class: " + subclass.getClass());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Attribute;
|
||||
import org.jboss.envers.tools.StringTools;
|
||||
import org.hibernate.mapping.Column;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MetadataTools {
|
||||
public static Element addNativelyGeneratedId(Element parent, String name, String type) {
|
||||
Element id_mapping = parent.addElement("id");
|
||||
id_mapping.addAttribute("name", name).addAttribute("type", type);
|
||||
|
||||
Element generator_mapping = id_mapping.addElement("generator");
|
||||
generator_mapping.addAttribute("class", "native");
|
||||
/*generator_mapping.addAttribute("class", "sequence");
|
||||
generator_mapping.addElement("param").addAttribute("name", "sequence").setText("custom");*/
|
||||
|
||||
return id_mapping;
|
||||
}
|
||||
|
||||
public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
|
||||
Element prop_mapping;
|
||||
if (key) {
|
||||
prop_mapping = parent.addElement("key-property");
|
||||
} else {
|
||||
prop_mapping = parent.addElement("property");
|
||||
}
|
||||
|
||||
prop_mapping.addAttribute("name", name);
|
||||
prop_mapping.addAttribute("insert", Boolean.toString(insertable));
|
||||
|
||||
if (type != null) {
|
||||
prop_mapping.addAttribute("type", type);
|
||||
}
|
||||
|
||||
return prop_mapping;
|
||||
}
|
||||
|
||||
public static Element addColumn(Element parent, String name, Integer length) {
|
||||
Element column_mapping = parent.addElement("column");
|
||||
|
||||
column_mapping.addAttribute("name", name);
|
||||
if (length != null) {
|
||||
column_mapping.addAttribute("length", length.toString());
|
||||
}
|
||||
|
||||
return column_mapping;
|
||||
}
|
||||
|
||||
private static Element createEntityCommon(Document document, String type, String entityName,
|
||||
String tableName, String schema, String catalog,
|
||||
String discriminatorValue) {
|
||||
Element hibernate_mapping = document.addElement("hibernate-mapping");
|
||||
hibernate_mapping.addAttribute("auto-import", "false");
|
||||
|
||||
Element class_mapping = hibernate_mapping.addElement(type);
|
||||
|
||||
if (entityName != null) {
|
||||
class_mapping.addAttribute("entity-name", entityName);
|
||||
}
|
||||
|
||||
if (discriminatorValue != null) {
|
||||
class_mapping.addAttribute("discriminator-value", discriminatorValue);
|
||||
}
|
||||
|
||||
if (!StringTools.isEmpty(tableName)) {
|
||||
class_mapping.addAttribute("table", tableName);
|
||||
}
|
||||
|
||||
if (!StringTools.isEmpty(schema)) {
|
||||
class_mapping.addAttribute("schema", schema);
|
||||
}
|
||||
|
||||
if (!StringTools.isEmpty(catalog)) {
|
||||
class_mapping.addAttribute("catalog", catalog);
|
||||
}
|
||||
|
||||
return class_mapping;
|
||||
}
|
||||
|
||||
public static Element createEntity(Document document, String entityName, String tableName,
|
||||
String schema, String catalog, String discriminatorValue) {
|
||||
return createEntityCommon(document, "class", entityName, tableName, schema, catalog, discriminatorValue);
|
||||
}
|
||||
|
||||
public static Element createSubclassEntity(Document document, String entityName, String tableName,
|
||||
String schema, String catalog, String extendsEntityName,
|
||||
String discriminatorValue) {
|
||||
Element class_mapping = createEntityCommon(document, "subclass", entityName, tableName, schema, catalog,
|
||||
discriminatorValue);
|
||||
|
||||
class_mapping.addAttribute("extends", extendsEntityName);
|
||||
|
||||
return class_mapping;
|
||||
}
|
||||
|
||||
public static Element createJoin(Element parent, String tableName,
|
||||
String schema, String catalog) {
|
||||
Element join_mapping = parent.addElement("join");
|
||||
|
||||
join_mapping.addAttribute("table", tableName);
|
||||
|
||||
if (!StringTools.isEmpty(schema)) {
|
||||
join_mapping.addAttribute("schema", schema);
|
||||
}
|
||||
|
||||
if (!StringTools.isEmpty(catalog)) {
|
||||
join_mapping.addAttribute("catalog", catalog);
|
||||
}
|
||||
|
||||
return join_mapping;
|
||||
}
|
||||
|
||||
public static void addColumns(Element any_mapping, Iterator<Column> columns) {
|
||||
while (columns.hasNext()) {
|
||||
Column column = columns.next();
|
||||
addColumn(any_mapping, column.getName(), column.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private static void changeNamesInColumnElement(Element element, ColumnNameIterator columnNameIterator) {
|
||||
Iterator<Element> properties = element.elementIterator();
|
||||
while (properties.hasNext()) {
|
||||
Element property = properties.next();
|
||||
|
||||
if ("column".equals(property.getName())) {
|
||||
Attribute nameAttr = property.attribute("name");
|
||||
if (nameAttr != null) {
|
||||
nameAttr.setText(columnNameIterator.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static void prefixNamesInPropertyElement(Element element, String prefix, ColumnNameIterator columnNameIterator,
|
||||
boolean changeToKey) {
|
||||
Iterator<Element> properties = element.elementIterator();
|
||||
while (properties.hasNext()) {
|
||||
Element property = properties.next();
|
||||
|
||||
if ("property".equals(property.getName())) {
|
||||
Attribute nameAttr = property.attribute("name");
|
||||
if (nameAttr != null) {
|
||||
nameAttr.setText(prefix + nameAttr.getText());
|
||||
}
|
||||
|
||||
changeNamesInColumnElement(property, columnNameIterator);
|
||||
|
||||
if (changeToKey) {
|
||||
property.setName("key-property");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An iterator over column names.
|
||||
*/
|
||||
public static abstract class ColumnNameIterator implements Iterator<String> { }
|
||||
|
||||
public static ColumnNameIterator getColumnNameIterator(final Iterator<Column> columnIterator) {
|
||||
return new ColumnNameIterator() {
|
||||
public boolean hasNext() { return columnIterator.hasNext(); }
|
||||
public String next() { return columnIterator.next().getName(); }
|
||||
public void remove() { columnIterator.remove(); }
|
||||
};
|
||||
}
|
||||
|
||||
public static ColumnNameIterator getColumnNameIterator(final JoinColumn[] joinColumns) {
|
||||
return new ColumnNameIterator() {
|
||||
int counter = 0;
|
||||
public boolean hasNext() { return counter < joinColumns.length; }
|
||||
public String next() { return joinColumns[counter++].name(); }
|
||||
public void remove() { throw new UnsupportedOperationException(); }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.VersionsJoinTable;
|
||||
import org.jboss.envers.VersionsTable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public class PersistentClassVersioningData {
|
||||
public PersistentClassVersioningData() {
|
||||
propertyStoreInfo = new PropertyStoreInfo(new HashMap<String, ModificationStore>());
|
||||
secondaryTableDictionary = new HashMap<String, String>();
|
||||
unversionedProperties = new ArrayList<String>();
|
||||
versionsJoinTables = new HashMap<String, VersionsJoinTable>();
|
||||
mapKeys = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
public PropertyStoreInfo propertyStoreInfo;
|
||||
public VersionsTable versionsTable;
|
||||
public Map<String, String> secondaryTableDictionary;
|
||||
public List<String> unversionedProperties;
|
||||
/**
|
||||
* A map from property names to custom join tables definitions.
|
||||
*/
|
||||
public Map<String, VersionsJoinTable> versionsJoinTables;
|
||||
/**
|
||||
* A map from property names to the value of the related property names in a map key annotation. An empty string,
|
||||
* if the property name is not specified in the mapkey annotation.
|
||||
*/
|
||||
public Map<String, String> mapKeys;
|
||||
|
||||
public boolean isVersioned() {
|
||||
if (propertyStoreInfo.propertyStores.size() > 0) { return true; }
|
||||
if (propertyStoreInfo.defaultStore != null) { return true; }
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PropertyStoreInfo {
|
||||
// Not null if the whole class is versioned
|
||||
public ModificationStore defaultStore;
|
||||
|
||||
// Maps property names to their stores defined in per-field versioned annotations
|
||||
public Map<String, ModificationStore> propertyStores;
|
||||
|
||||
public PropertyStoreInfo(Map<String, ModificationStore> propertyStores) {
|
||||
this.propertyStores = propertyStores;
|
||||
}
|
||||
|
||||
public PropertyStoreInfo(ModificationStore defaultStore, Map<String, ModificationStore> propertyStores) {
|
||||
this.defaultStore = defaultStore;
|
||||
this.propertyStores = propertyStores;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.query.OneEntityQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.query.ThreeEntityQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.query.TwoEntityQueryGenerator;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.configuration.GlobalConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Builds query generators, for reading collection middle tables, along with any related entities.
|
||||
* The related entities information can be added gradually, and when complete, the query generator can be built.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class QueryGeneratorBuilder {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final VersionsEntitiesConfiguration verEntCfg;
|
||||
private final MiddleIdData referencingIdData;
|
||||
private final String versionsMiddleEntityName;
|
||||
private final List<MiddleIdData> idDatas;
|
||||
|
||||
QueryGeneratorBuilder(GlobalConfiguration globalCfg, VersionsEntitiesConfiguration verEntCfg,
|
||||
MiddleIdData referencingIdData, String versionsMiddleEntityName) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.referencingIdData = referencingIdData;
|
||||
this.versionsMiddleEntityName = versionsMiddleEntityName;
|
||||
|
||||
idDatas = new ArrayList<MiddleIdData>();
|
||||
}
|
||||
|
||||
void addRelation(MiddleIdData idData) {
|
||||
idDatas.add(idData);
|
||||
}
|
||||
|
||||
RelationQueryGenerator build(MiddleComponentData... componentDatas) {
|
||||
if (idDatas.size() == 0) {
|
||||
return new OneEntityQueryGenerator(verEntCfg, versionsMiddleEntityName, referencingIdData,
|
||||
componentDatas);
|
||||
} else if (idDatas.size() == 1) {
|
||||
return new TwoEntityQueryGenerator(globalCfg, verEntCfg, versionsMiddleEntityName, referencingIdData,
|
||||
idDatas.get(0), componentDatas);
|
||||
} else if (idDatas.size() == 2) {
|
||||
return new ThreeEntityQueryGenerator(globalCfg, verEntCfg, versionsMiddleEntityName, referencingIdData,
|
||||
idDatas.get(0), idDatas.get(1), componentDatas);
|
||||
} else {
|
||||
throw new IllegalStateException("Illegal number of related entities.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current index of data in the array, which will be the element of a list, returned when executing a query
|
||||
* generated by the built query generator.
|
||||
*/
|
||||
int getCurrentIndex() {
|
||||
return idDatas.size();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.MappingException;
|
||||
import org.jboss.envers.entities.mapper.CompositeMapperBuilder;
|
||||
import org.jboss.envers.entities.mapper.relation.ToOneIdMapper;
|
||||
import org.jboss.envers.entities.mapper.relation.OneToOneNotOwningMapper;
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.jboss.envers.entities.EntityConfiguration;
|
||||
import org.jboss.envers.entities.IdMappingData;
|
||||
|
||||
/**
|
||||
* Generates metadata for to-one relations (reference-valued properties).
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class ToOneRelationMetadataGenerator {
|
||||
private final VersionsMetadataGenerator mainGenerator;
|
||||
|
||||
ToOneRelationMetadataGenerator(VersionsMetadataGenerator versionsMetadataGenerator) {
|
||||
mainGenerator = versionsMetadataGenerator;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addToOne(Element parent, String name, Value value, CompositeMapperBuilder mapper, String entityName) {
|
||||
String referencedEntityName = ((ToOne) value).getReferencedEntityName();
|
||||
|
||||
EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(referencedEntityName);
|
||||
if (configuration == null) {
|
||||
throw new MappingException("A versioned relation to a non-versioned entity " + referencedEntityName + "!");
|
||||
}
|
||||
|
||||
IdMappingData idMapping = configuration.getIdMappingData();
|
||||
|
||||
String lastPropertyPrefix = name + "_";
|
||||
|
||||
// Generating the id mapper for the relation
|
||||
IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
|
||||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(name, referencedEntityName, relMapper);
|
||||
|
||||
// Adding an element to the mapping corresponding to the references entity id's
|
||||
Element properties = (Element) idMapping.getXmlRelationMapping().clone();
|
||||
properties.addAttribute("name", name);
|
||||
|
||||
MetadataTools.prefixNamesInPropertyElement(properties, lastPropertyPrefix,
|
||||
MetadataTools.getColumnNameIterator(value.getColumnIterator()), false);
|
||||
parent.add(properties);
|
||||
|
||||
// Adding mapper for the id
|
||||
mapper.addComposite(name, new ToOneIdMapper(relMapper, name, referencedEntityName));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addOneToOneNotOwning(String name, Value value, CompositeMapperBuilder mapper, String entityName) {
|
||||
OneToOne propertyValue = (OneToOne) value;
|
||||
|
||||
String owningReferencePropertyName = propertyValue.getReferencedPropertyName(); // mappedBy
|
||||
|
||||
EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(entityName);
|
||||
if (configuration == null) {
|
||||
throw new MappingException("A versioned relation to a non-versioned entity " + entityName + "!");
|
||||
}
|
||||
|
||||
IdMappingData ownedIdMapping = configuration.getIdMappingData();
|
||||
|
||||
if (ownedIdMapping == null) {
|
||||
throw new MappingException("A versioned relation to a non-versioned entity " + entityName + "!");
|
||||
}
|
||||
|
||||
String lastPropertyPrefix = owningReferencePropertyName + "_";
|
||||
String referencedEntityName = propertyValue.getReferencedEntityName();
|
||||
|
||||
// Generating the id mapper for the relation
|
||||
IdMapper ownedIdMapper = ownedIdMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
|
||||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(name, owningReferencePropertyName,
|
||||
referencedEntityName, ownedIdMapper);
|
||||
|
||||
// Adding mapper for the id
|
||||
mapper.addComposite(name, new OneToOneNotOwningMapper(owningReferencePropertyName,
|
||||
referencedEntityName, name));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,372 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.configuration.metadata;
|
||||
|
||||
import org.hibernate.type.*;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.mapping.*;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.dom4j.Element;
|
||||
import org.jboss.envers.entities.EntityConfiguration;
|
||||
import org.jboss.envers.entities.IdMappingData;
|
||||
import org.jboss.envers.configuration.GlobalConfiguration;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.entities.mapper.*;
|
||||
import org.jboss.envers.tools.StringTools;
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.VersionsJoinTable;
|
||||
import org.jboss.envers.entity.VersionsInheritanceEntityPersister;
|
||||
import org.jboss.envers.tools.log.YLog;
|
||||
import org.jboss.envers.tools.log.YLogManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public final class VersionsMetadataGenerator {
|
||||
private final Configuration cfg;
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final VersionsEntitiesConfiguration verEntCfg;
|
||||
private final Element revisionInfoRelationMapping;
|
||||
|
||||
private final BasicMetadataGenerator basicMetadataGenerator;
|
||||
private final IdMetadataGenerator idMetadataGenerator;
|
||||
private final ToOneRelationMetadataGenerator toOneRelationMetadataGenerator;
|
||||
|
||||
private final Map<String, EntityConfiguration> entitiesConfigurations;
|
||||
|
||||
// Map entity name -> (join descriptor -> element describing the "versioned" join)
|
||||
private final Map<String, Map<Join, Element>> entitiesJoins;
|
||||
|
||||
private YLog log = YLogManager.getLogManager().getLog(VersionsMetadataGenerator.class);
|
||||
|
||||
public VersionsMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
|
||||
VersionsEntitiesConfiguration verEntCfg,
|
||||
Element revisionInfoRelationMapping) {
|
||||
this.cfg = cfg;
|
||||
this.globalCfg = globalCfg;
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
||||
|
||||
this.basicMetadataGenerator = new BasicMetadataGenerator();
|
||||
this.idMetadataGenerator = new IdMetadataGenerator(this);
|
||||
this.toOneRelationMetadataGenerator = new ToOneRelationMetadataGenerator(this);
|
||||
|
||||
entitiesConfigurations = new HashMap<String, EntityConfiguration>();
|
||||
entitiesJoins = new HashMap<String, Map<Join, Element>>();
|
||||
}
|
||||
|
||||
void addRevisionInfoRelation(Element any_mapping) {
|
||||
Element rev_mapping = (Element) revisionInfoRelationMapping.clone();
|
||||
rev_mapping.addAttribute("name", verEntCfg.getRevisionPropName());
|
||||
MetadataTools.addColumn(rev_mapping, verEntCfg.getRevisionPropName(), null);
|
||||
|
||||
any_mapping.add(rev_mapping);
|
||||
}
|
||||
|
||||
void addRevisionType(Element any_mapping) {
|
||||
Element revTypeProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionTypePropName(),
|
||||
verEntCfg.getRevisionTypePropType(), true, false);
|
||||
revTypeProperty.addAttribute("type", "org.jboss.envers.entities.RevisionTypeType");
|
||||
}
|
||||
|
||||
private ModificationStore getStoreForProperty(Property property, PropertyStoreInfo propertyStoreInfo,
|
||||
List<String> unversionedProperties) {
|
||||
/*
|
||||
* Checks if a property is versioned, which is when:
|
||||
* - the property isn't unversioned
|
||||
* - the whole entity is versioned, then the default store is not null
|
||||
* - there is a store defined for this entity, which is when this property is annotated
|
||||
*/
|
||||
|
||||
if (unversionedProperties.contains(property.getName())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ModificationStore store = propertyStoreInfo.propertyStores.get(property.getName());
|
||||
|
||||
if (store == null) {
|
||||
return propertyStoreInfo.defaultStore;
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addValue(Element parent, String name, Value value, CompositeMapperBuilder currentMapper,
|
||||
ModificationStore store, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
VersionsJoinTable joinTable, String mapKey, boolean insertable, boolean firstPass) {
|
||||
Type type = value.getType();
|
||||
|
||||
// only first pass
|
||||
if (firstPass) {
|
||||
if (basicMetadataGenerator.addBasic(parent, name, value, currentMapper, store, entityName, insertable,
|
||||
false)) {
|
||||
// The property was mapped by the basic generator.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (type instanceof ManyToOneType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
toOneRelationMetadataGenerator.addToOne(parent, name, value, currentMapper, entityName);
|
||||
}
|
||||
} else if (type instanceof OneToOneType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(name, value, currentMapper, entityName);
|
||||
}
|
||||
} else if (type instanceof CollectionType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
|
||||
name, (Collection) value, currentMapper, entityName, xmlMappingData, joinTable, mapKey);
|
||||
collectionMetadataGenerator.addCollection();
|
||||
}
|
||||
} else {
|
||||
if (firstPass) {
|
||||
// If we got here in the first pass, it means the basic mapper didn't map it, and none of the
|
||||
// above branches either.
|
||||
throwUnsupportedTypeException(type, entityName, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
|
||||
PersistentClassVersioningData versioningData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
boolean firstPass) {
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
if (!"_identifierMapper".equals(property.getName())) {
|
||||
ModificationStore store = getStoreForProperty(property, versioningData.propertyStoreInfo,
|
||||
versioningData.unversionedProperties);
|
||||
|
||||
if (store != null) {
|
||||
addValue(parent, property.getName(), property.getValue(), currentMapper, store, entityName,
|
||||
xmlMappingData, versioningData.versionsJoinTables.get(property.getName()),
|
||||
versioningData.mapKeys.get(property.getName()), property.isInsertable(), firstPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void createJoins(PersistentClass pc, Element parent, PersistentClassVersioningData versioningData) {
|
||||
Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
Map<Join, Element> joinElements = new HashMap<Join, Element>();
|
||||
entitiesJoins.put(pc.getEntityName(), joinElements);
|
||||
|
||||
while (joins.hasNext()) {
|
||||
Join join = joins.next();
|
||||
|
||||
// Determining the table name. If there is no entry in the dictionary, just constructing the table name
|
||||
// as if it was an entity (by appending/prepending configured strings).
|
||||
String originalTableName = join.getTable().getName();
|
||||
String versionedTableName = versioningData.secondaryTableDictionary.get(originalTableName);
|
||||
if (versionedTableName == null) {
|
||||
versionedTableName = verEntCfg.getVersionsEntityName(originalTableName);
|
||||
}
|
||||
|
||||
String schema = versioningData.versionsTable.schema();
|
||||
if (StringTools.isEmpty(schema)) {
|
||||
schema = join.getTable().getSchema();
|
||||
}
|
||||
|
||||
String catalog = versioningData.versionsTable.catalog();
|
||||
if (StringTools.isEmpty(catalog)) {
|
||||
catalog = join.getTable().getCatalog();
|
||||
}
|
||||
|
||||
Element joinElement = MetadataTools.createJoin(parent, versionedTableName, schema, catalog);
|
||||
joinElements.put(join, joinElement);
|
||||
|
||||
Element joinKey = joinElement.addElement("key");
|
||||
MetadataTools.addColumns(joinKey, join.getKey().getColumnIterator());
|
||||
MetadataTools.addColumn(joinKey, verEntCfg.getRevisionPropName(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassVersioningData versioningData,
|
||||
String entityName, EntityXmlMappingData xmlMappingData,boolean firstPass) {
|
||||
Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
while (joins.hasNext()) {
|
||||
Join join = joins.next();
|
||||
Element joinElement = entitiesJoins.get(entityName).get(join);
|
||||
|
||||
addProperties(joinElement, join.getPropertyIterator(), currentMapper, versioningData, entityName,
|
||||
xmlMappingData, firstPass);
|
||||
}
|
||||
}
|
||||
|
||||
private void addPersisterHack(Element class_mapping) {
|
||||
class_mapping.addAttribute("persister", VersionsInheritanceEntityPersister.class.getName() );
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateFirstPass(PersistentClass pc, PersistentClassVersioningData versioningData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
String schema = versioningData.versionsTable.schema();
|
||||
if (StringTools.isEmpty(schema)) {
|
||||
schema = pc.getTable().getSchema();
|
||||
}
|
||||
|
||||
String catalog = versioningData.versionsTable.catalog();
|
||||
if (StringTools.isEmpty(catalog)) {
|
||||
catalog = pc.getTable().getCatalog();
|
||||
}
|
||||
|
||||
String entityName = pc.getEntityName();
|
||||
String versionsEntityName = verEntCfg.getVersionsEntityName(entityName);
|
||||
String versionsTableName = verEntCfg.getVersionsTableName(entityName, pc.getTable().getName());
|
||||
|
||||
// Generating a mapping for the id
|
||||
IdMappingData idMapper = idMetadataGenerator.addId(pc);
|
||||
|
||||
Element class_mapping;
|
||||
ExtendedPropertyMapper propertyMapper;
|
||||
|
||||
InheritanceType inheritanceType = InheritanceType.get(pc);
|
||||
String parentEntityName = null;
|
||||
|
||||
switch (inheritanceType) {
|
||||
case NONE:
|
||||
class_mapping = MetadataTools.createEntity(xmlMappingData.getMainXmlMapping(), versionsEntityName, versionsTableName,
|
||||
schema, catalog, pc.getDiscriminatorValue());
|
||||
propertyMapper = new MultiPropertyMapper();
|
||||
|
||||
// Checking if there is a discriminator column
|
||||
if (pc.getDiscriminator() != null) {
|
||||
Element discriminator_element = class_mapping.addElement("discriminator");
|
||||
MetadataTools.addColumns(discriminator_element, pc.getDiscriminator().getColumnIterator());
|
||||
discriminator_element.addAttribute("type", pc.getDiscriminator().getType().getName());
|
||||
|
||||
// If so, there is some inheritance scheme -> using the persister hack.
|
||||
addPersisterHack(class_mapping);
|
||||
}
|
||||
|
||||
// Adding the id mapping
|
||||
class_mapping.add((Element) idMapper.getXmlMapping().clone());
|
||||
|
||||
// Adding the "revision type" property
|
||||
addRevisionType(class_mapping);
|
||||
|
||||
break;
|
||||
case SINGLE:
|
||||
String extendsEntityName = verEntCfg.getVersionsEntityName(pc.getSuperclass().getEntityName());
|
||||
class_mapping = MetadataTools.createSubclassEntity(xmlMappingData.getMainXmlMapping(), versionsEntityName,
|
||||
versionsTableName, schema, catalog, extendsEntityName, pc.getDiscriminatorValue());
|
||||
|
||||
addPersisterHack(class_mapping);
|
||||
|
||||
// The id and revision type is already mapped in the parent
|
||||
|
||||
// Getting the property mapper of the parent - when mapping properties, they need to be included
|
||||
parentEntityName = pc.getSuperclass().getEntityName();
|
||||
ExtendedPropertyMapper parentPropertyMapper = entitiesConfigurations.get(parentEntityName).getPropertyMapper();
|
||||
propertyMapper = new SubclassPropertyMapper(new MultiPropertyMapper(), parentPropertyMapper);
|
||||
|
||||
break;
|
||||
case JOINED:
|
||||
throw new MappingException("Joined inheritance strategy not supported for versioning!");
|
||||
case TABLE_PER_CLASS:
|
||||
throw new MappingException("Table-per-class inheritance strategy not supported for versioning!");
|
||||
default:
|
||||
throw new AssertionError("Impossible enum value.");
|
||||
}
|
||||
|
||||
// Mapping unjoined properties
|
||||
addProperties(class_mapping, (Iterator<Property>) pc.getUnjoinedPropertyIterator(), propertyMapper,
|
||||
versioningData, pc.getEntityName(), xmlMappingData,
|
||||
true);
|
||||
|
||||
// Creating and mapping joins (first pass)
|
||||
createJoins(pc, class_mapping, versioningData);
|
||||
addJoins(pc, propertyMapper, versioningData, pc.getEntityName(), xmlMappingData, true);
|
||||
|
||||
// Storing the generated configuration
|
||||
EntityConfiguration entityCfg = new EntityConfiguration(versionsEntityName, idMapper,
|
||||
propertyMapper, parentEntityName);
|
||||
entitiesConfigurations.put(pc.getEntityName(), entityCfg);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateSecondPass(PersistentClass pc, PersistentClassVersioningData versioningData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
String entityName = pc.getEntityName();
|
||||
|
||||
CompositeMapperBuilder propertyMapper = entitiesConfigurations.get(entityName).getPropertyMapper();
|
||||
|
||||
// Mapping unjoined properties
|
||||
Element parent = xmlMappingData.getMainXmlMapping().getRootElement().element("class");
|
||||
if (parent == null) {
|
||||
parent = xmlMappingData.getMainXmlMapping().getRootElement().element("subclass");
|
||||
}
|
||||
|
||||
addProperties(parent, (Iterator<Property>) pc.getUnjoinedPropertyIterator(),
|
||||
propertyMapper, versioningData, entityName, xmlMappingData, false);
|
||||
|
||||
// Mapping joins (second pass)
|
||||
addJoins(pc, propertyMapper, versioningData, entityName, xmlMappingData, false);
|
||||
}
|
||||
|
||||
public Map<String, EntityConfiguration> getEntitiesConfigurations() {
|
||||
return entitiesConfigurations;
|
||||
}
|
||||
|
||||
// Getters for generators and configuration
|
||||
|
||||
BasicMetadataGenerator getBasicMetadataGenerator() {
|
||||
return basicMetadataGenerator;
|
||||
}
|
||||
|
||||
Configuration getCfg() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
GlobalConfiguration getGlobalCfg() {
|
||||
return globalCfg;
|
||||
}
|
||||
|
||||
VersionsEntitiesConfiguration getVerEntCfg() {
|
||||
return verEntCfg;
|
||||
}
|
||||
|
||||
void throwUnsupportedTypeException(Type type, String entityName, String propertyName) {
|
||||
String message = "Type not supported for versioning: " + type.getClass().getName() +
|
||||
", on entity " + entityName + ", property '" + propertyName + "'.";
|
||||
if (globalCfg.isWarnOnUnsupportedTypes()) {
|
||||
log.warn(message);
|
||||
} else {
|
||||
throw new MappingException(message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Configuration of the user entities: property mapping of the entities, relations, inheritance.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EntitiesConfigurations {
|
||||
private Map<String, EntityConfiguration> entitiesConfigurations;
|
||||
|
||||
// Map versions entity name -> entity name
|
||||
private Map<String, String> entityNamesForVersionsEntityNames = new HashMap<String, String>();
|
||||
|
||||
public EntitiesConfigurations(Map<String, EntityConfiguration> entitiesConfigurations) {
|
||||
this.entitiesConfigurations = entitiesConfigurations;
|
||||
|
||||
generateBidirectionRelationInfo();
|
||||
generateVersionsEntityToEntityNames();
|
||||
}
|
||||
|
||||
private void generateVersionsEntityToEntityNames() {
|
||||
entityNamesForVersionsEntityNames = new HashMap<String, String>();
|
||||
|
||||
for (String entityName : entitiesConfigurations.keySet()) {
|
||||
entityNamesForVersionsEntityNames.put(entitiesConfigurations.get(entityName).getVersionsEntityName(),
|
||||
entityName);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateBidirectionRelationInfo() {
|
||||
// Checking each relation if it is bidirectional. If so, storing that information.
|
||||
for (String entityName : entitiesConfigurations.keySet()) {
|
||||
EntityConfiguration entCfg = entitiesConfigurations.get(entityName);
|
||||
// Iterating over all relations from that entity
|
||||
for (RelationDescription relDesc : entCfg.getRelationsIterator()) {
|
||||
// If this is an "owned" relation, checking the related entity, if it has a relation that has
|
||||
// a mapped-by attribute to the currently checked. If so, this is a bidirectional relation.
|
||||
if (relDesc.getRelationType() == RelationType.TO_ONE ||
|
||||
relDesc.getRelationType() == RelationType.TO_MANY_MIDDLE) {
|
||||
for (RelationDescription other : entitiesConfigurations.get(relDesc.getToEntityName()).getRelationsIterator()) {
|
||||
if (relDesc.getFromPropertyName().equals(other.getMappedByPropertyName()) &&
|
||||
(entityName.equals(other.getToEntityName()))) {
|
||||
relDesc.setBidirectional(true);
|
||||
other.setBidirectional(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EntityConfiguration get(String entityName) {
|
||||
return entitiesConfigurations.get(entityName);
|
||||
}
|
||||
|
||||
public String getEntityNameForVersionsEntityName(String versionsEntityName) {
|
||||
return entityNamesForVersionsEntityNames.get(versionsEntityName);
|
||||
}
|
||||
|
||||
public boolean isVersioned(String entityName) {
|
||||
return get(entityName) != null;
|
||||
}
|
||||
|
||||
public RelationDescription getRelationDescription(String entityName, String propertyName) {
|
||||
EntityConfiguration entCfg = entitiesConfigurations.get(entityName);
|
||||
RelationDescription relDesc = entCfg.getRelationDescription(propertyName);
|
||||
if (relDesc != null) {
|
||||
return relDesc;
|
||||
} else if (entCfg.getParentEntityName() != null) {
|
||||
// The field may be declared in a superclass ...
|
||||
return getRelationDescription(entCfg.getParentEntityName(), propertyName);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
import org.jboss.envers.entities.mapper.ExtendedPropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EntityConfiguration {
|
||||
private String versionsEntityName;
|
||||
private IdMappingData idMappingData;
|
||||
private ExtendedPropertyMapper propertyMapper;
|
||||
// Maps from property name
|
||||
private Map<String, RelationDescription> relations;
|
||||
private String parentEntityName;
|
||||
|
||||
public EntityConfiguration(String versionsEntityName, IdMappingData idMappingData,
|
||||
ExtendedPropertyMapper propertyMapper, String parentEntityName) {
|
||||
this.versionsEntityName = versionsEntityName;
|
||||
this.idMappingData = idMappingData;
|
||||
this.propertyMapper = propertyMapper;
|
||||
this.parentEntityName = parentEntityName;
|
||||
|
||||
this.relations = new HashMap<String, RelationDescription>();
|
||||
}
|
||||
|
||||
public void addToOneRelation(String fromPropertyName, String toEntityName, IdMapper idMapper) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_ONE,
|
||||
toEntityName, null, idMapper));
|
||||
}
|
||||
|
||||
public void addToOneNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName,
|
||||
IdMapper idMapper) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_ONE_NOT_OWNING,
|
||||
toEntityName, mappedByPropertyName, idMapper));
|
||||
}
|
||||
|
||||
public void addToManyNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName,
|
||||
IdMapper idMapper) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_NOT_OWNING,
|
||||
toEntityName, mappedByPropertyName, idMapper));
|
||||
}
|
||||
|
||||
public void addToManyMiddleRelation(String fromPropertyName, String toEntityName) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_MIDDLE,
|
||||
toEntityName, null, null));
|
||||
}
|
||||
|
||||
public void addToManyMiddleNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_MIDDLE_NOT_OWNING,
|
||||
toEntityName, mappedByPropertyName, null));
|
||||
}
|
||||
|
||||
public boolean isRelation(String propertyName) {
|
||||
return relations.get(propertyName) != null;
|
||||
}
|
||||
|
||||
public RelationDescription getRelationDescription(String propertyName) {
|
||||
return relations.get(propertyName);
|
||||
}
|
||||
|
||||
public IdMappingData getIdMappingData() {
|
||||
return idMappingData;
|
||||
}
|
||||
|
||||
public IdMapper getIdMapper() {
|
||||
return idMappingData.getIdMapper();
|
||||
}
|
||||
|
||||
public ExtendedPropertyMapper getPropertyMapper() {
|
||||
return propertyMapper;
|
||||
}
|
||||
|
||||
// For use by EntitiesConfigurations
|
||||
|
||||
String getParentEntityName() {
|
||||
return parentEntityName;
|
||||
}
|
||||
|
||||
String getVersionsEntityName() {
|
||||
return versionsEntityName;
|
||||
}
|
||||
|
||||
Iterable<RelationDescription> getRelationsIterator() {
|
||||
return relations.values();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EntityInstantiator {
|
||||
private final VersionsConfiguration verCfg;
|
||||
private final VersionsReaderImplementor versionsReader;
|
||||
|
||||
public EntityInstantiator(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader) {
|
||||
this.verCfg = verCfg;
|
||||
this.versionsReader = versionsReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an entity instance based on an entry from the versions table.
|
||||
* @param entityName Name of the entity, which instances should be read
|
||||
* @param versionsEntity An entry in the versions table, from which data should be mapped.
|
||||
* @param revision Revision at which this entity was read.
|
||||
* @return An entity instance, with versioned properties set as in the versionsEntity map, and proxies
|
||||
* created for collections.
|
||||
*/
|
||||
public Object createInstanceFromVersionsEntity(String entityName, Map versionsEntity, Number revision) {
|
||||
if (versionsEntity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// The $type$ property holds the name of the (versions) entity
|
||||
String type = verCfg.getEntCfg().getEntityNameForVersionsEntityName((String) versionsEntity.get("$type$"));
|
||||
|
||||
if (type != null) {
|
||||
entityName = type;
|
||||
}
|
||||
|
||||
// First mapping the primary key
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(entityName).getIdMapper();
|
||||
Map originalId = (Map) versionsEntity.get(verCfg.getVerEntCfg().getOriginalIdPropName());
|
||||
|
||||
Object primaryKey = idMapper.mapToIdFromMap(originalId);
|
||||
|
||||
// Checking if the entity is in cache
|
||||
if (versionsReader.getFirstLevelCache().contains(entityName, revision, primaryKey)) {
|
||||
return versionsReader.getFirstLevelCache().get(entityName, revision, primaryKey);
|
||||
}
|
||||
|
||||
// If it is not in the cache, creating a new entity instance
|
||||
Object ret;
|
||||
try {
|
||||
Class<?> cls = ReflectionTools.loadClass(entityName);
|
||||
ret = cls.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
|
||||
// Putting the newly created entity instance into the first level cache, in case a one-to-one bidirectional
|
||||
// relation is present (which is eagerly loaded).
|
||||
versionsReader.getFirstLevelCache().put(entityName, revision, primaryKey, ret);
|
||||
|
||||
verCfg.getEntCfg().get(entityName).getPropertyMapper().mapToEntityFromMap(verCfg, ret, versionsEntity, primaryKey,
|
||||
versionsReader, revision);
|
||||
idMapper.mapToEntityFromMap(ret, originalId);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void addInstancesFromVersionsEntities(String entityName, Collection addTo, List<Map> versionsEntities, Number revision) {
|
||||
for (Map versionsEntity : versionsEntities) {
|
||||
addTo.add(createInstanceFromVersionsEntity(entityName, versionsEntity, revision));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.dom4j.Element;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class IdMappingData {
|
||||
private final IdMapper idMapper;
|
||||
// Mapping which will be used to generate the entity
|
||||
private final Element xmlMapping;
|
||||
// Mapping which will be used to generate references to the entity in related entities
|
||||
private final Element xmlRelationMapping;
|
||||
|
||||
public IdMappingData(IdMapper idMapper, Element xmlMapping, Element xmlRelationMapping) {
|
||||
this.idMapper = idMapper;
|
||||
this.xmlMapping = xmlMapping;
|
||||
this.xmlRelationMapping = xmlRelationMapping;
|
||||
}
|
||||
|
||||
public IdMapper getIdMapper() {
|
||||
return idMapper;
|
||||
}
|
||||
|
||||
public Element getXmlMapping() {
|
||||
return xmlMapping;
|
||||
}
|
||||
|
||||
public Element getXmlRelationMapping() {
|
||||
return xmlRelationMapping;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class RelationDescription {
|
||||
private final String fromPropertyName;
|
||||
private final RelationType relationType;
|
||||
private final String toEntityName;
|
||||
private final String mappedByPropertyName;
|
||||
private final IdMapper idMapper;
|
||||
private boolean bidirectional;
|
||||
|
||||
public RelationDescription(String fromPropertyName, RelationType relationType, String toEntityName,
|
||||
String mappedByPropertyName, IdMapper idMapper) {
|
||||
this.fromPropertyName = fromPropertyName;
|
||||
this.relationType = relationType;
|
||||
this.toEntityName = toEntityName;
|
||||
this.mappedByPropertyName = mappedByPropertyName;
|
||||
this.idMapper = idMapper;
|
||||
|
||||
this.bidirectional = false;
|
||||
}
|
||||
|
||||
public String getFromPropertyName() {
|
||||
return fromPropertyName;
|
||||
}
|
||||
|
||||
public RelationType getRelationType() {
|
||||
return relationType;
|
||||
}
|
||||
|
||||
public String getToEntityName() {
|
||||
return toEntityName;
|
||||
}
|
||||
|
||||
public String getMappedByPropertyName() {
|
||||
return mappedByPropertyName;
|
||||
}
|
||||
|
||||
public IdMapper getIdMapper() {
|
||||
return idMapper;
|
||||
}
|
||||
|
||||
public boolean isBidirectional() {
|
||||
return bidirectional;
|
||||
}
|
||||
|
||||
void setBidirectional(boolean bidirectional) {
|
||||
this.bidirectional = bidirectional;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
/**
|
||||
* Type of a relation between two entities.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public enum RelationType {
|
||||
/**
|
||||
* A single-reference-valued relation. The entity owns the relation.
|
||||
*/
|
||||
TO_ONE,
|
||||
/**
|
||||
* A single-reference-valued relation. The entity doesn't own the relation. It is directly mapped in the related
|
||||
* entity.
|
||||
*/
|
||||
TO_ONE_NOT_OWNING,
|
||||
/**
|
||||
* A collection-of-references-valued relation. The entity doesn't own the relation. It is directly mapped in the
|
||||
* related entity.
|
||||
*/
|
||||
TO_MANY_NOT_OWNING,
|
||||
/**
|
||||
* A collection-of-references-valued relation. The entity owns the relation. It is mapped using a middle table.
|
||||
*/
|
||||
TO_MANY_MIDDLE,
|
||||
/**
|
||||
* A collection-of-references-valued relation. The entity doesn't own the relation. It is mapped using a middle
|
||||
* table.
|
||||
*/
|
||||
TO_MANY_MIDDLE_NOT_OWNING
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities;
|
||||
|
||||
import org.hibernate.usertype.UserType;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.jboss.envers.RevisionType;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Types;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A hibernate type for the {@link RevisionType} enum.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class RevisionTypeType implements UserType {
|
||||
private static final int[] SQL_TYPES = { Types.TINYINT };
|
||||
|
||||
public int[] sqlTypes() {
|
||||
return SQL_TYPES;
|
||||
}
|
||||
|
||||
public Class returnedClass() {
|
||||
return RevisionType.class;
|
||||
}
|
||||
|
||||
public RevisionType nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
|
||||
byte representation = (byte) resultSet.getInt(names[0]);
|
||||
RevisionType result = null;
|
||||
|
||||
if (!resultSet.wasNull()) {
|
||||
result = RevisionType.fromRepresentation(representation);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
|
||||
if (null == value) {
|
||||
preparedStatement.setNull(index, Types.TINYINT);
|
||||
} else {
|
||||
preparedStatement.setInt(index, ((RevisionType) value).getRepresentation());
|
||||
}
|
||||
}
|
||||
|
||||
public Object deepCopy(Object value) throws HibernateException{
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object assemble(Serializable cached, Object owner) throws HibernateException {
|
||||
return cached;
|
||||
}
|
||||
|
||||
public Serializable disassemble(Object value) throws HibernateException {
|
||||
return (Serializable)value;
|
||||
}
|
||||
|
||||
public Object replace(Object original, Object target, Object owner) throws HibernateException {
|
||||
return original;
|
||||
}
|
||||
|
||||
public int hashCode(Object x) throws HibernateException {
|
||||
return x.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object x, Object y) throws HibernateException {
|
||||
//noinspection ObjectEquality
|
||||
if (x == y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (null == x || null == y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.equals(y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface CompositeMapperBuilder extends SimpleMapperBuilder {
|
||||
public CompositeMapperBuilder addComposite(String propertyName);
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface ExtendedPropertyMapper extends PropertyMapper, CompositeMapperBuilder {
|
||||
public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MapPropertyMapper implements PropertyMapper, CompositeMapperBuilder {
|
||||
private String propertyName;
|
||||
private ExtendedPropertyMapper delegate;
|
||||
|
||||
public MapPropertyMapper(String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
this.delegate = new MultiPropertyMapper();
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
delegate.add(propertyName, modStore);
|
||||
}
|
||||
|
||||
public CompositeMapperBuilder addComposite(String propertyName) {
|
||||
return delegate.addComposite(propertyName);
|
||||
}
|
||||
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
|
||||
delegate.addComposite(propertyName, propertyMapper);
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
Map<String, Object> newData = new HashMap<String, Object>();
|
||||
data.put(propertyName, newData);
|
||||
|
||||
return delegate.mapToMapFromEntity(newData, newObj, oldObj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
|
||||
if (data == null || obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), propertyName);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
|
||||
try {
|
||||
Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
|
||||
setter.set(obj, subObj, null);
|
||||
delegate.mapToEntityFromMap(verCfg, subObj, (Map) data.get(propertyName), primaryKey, versionsReader, revision);
|
||||
} catch (Exception e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
return delegate.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
||||
protected Map<String, PropertyMapper> properties;
|
||||
|
||||
public MultiPropertyMapper() {
|
||||
properties = new HashMap<String, PropertyMapper>();
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
SinglePropertyMapper single = new SinglePropertyMapper();
|
||||
single.add(propertyName, modStore);
|
||||
properties.put(propertyName, single);
|
||||
}
|
||||
|
||||
public CompositeMapperBuilder addComposite(String propertyName) {
|
||||
if (properties.get(propertyName) != null) {
|
||||
throw new MappingException("Mapping for " + propertyName + " already added!");
|
||||
}
|
||||
|
||||
MapPropertyMapper mapperBuilder = new MapPropertyMapper(propertyName);
|
||||
properties.put(propertyName, mapperBuilder);
|
||||
|
||||
return mapperBuilder;
|
||||
}
|
||||
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
|
||||
properties.put(propertyName, propertyMapper);
|
||||
}
|
||||
|
||||
private Object getAtIndexOrNull(Object[] array, int index) { return array == null ? null : array[index]; }
|
||||
|
||||
public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
|
||||
boolean ret = false;
|
||||
for (int i=0; i<propertyNames.length; i++) {
|
||||
String propertyName = propertyNames[i];
|
||||
|
||||
if (properties.containsKey(propertyName)) {
|
||||
ret |= properties.get(propertyName).mapToMapFromEntity(data,
|
||||
getAtIndexOrNull(newState, i),
|
||||
getAtIndexOrNull(oldState, i));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
boolean ret = false;
|
||||
for (String propertyName : properties.keySet()) {
|
||||
Getter getter;
|
||||
if (newObj != null) {
|
||||
getter = ReflectionTools.getGetter(newObj.getClass(), propertyName);
|
||||
} else if (oldObj != null) {
|
||||
getter = ReflectionTools.getGetter(oldObj.getClass(), propertyName);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret |= properties.get(propertyName).mapToMapFromEntity(data,
|
||||
newObj == null ? null : getter.get(newObj),
|
||||
oldObj == null ? null : getter.get(oldObj));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
|
||||
for (String propertyName : properties.keySet()) {
|
||||
properties.get(propertyName).mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
PropertyMapper mapper = properties.get(referencingPropertyName);
|
||||
if (mapper != null) {
|
||||
return mapper.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Data describing the change of a single object in a persisten collection (when the object was added, removed or
|
||||
* modified in the collection).
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PersistentCollectionChangeData {
|
||||
private final String entityName;
|
||||
private final Map<String, Object> data;
|
||||
private final Object changedElement;
|
||||
|
||||
public PersistentCollectionChangeData(String entityName, Map<String, Object> data, Object changedElement) {
|
||||
this.entityName = entityName;
|
||||
this.data = data;
|
||||
this.changedElement = changedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Name of the (middle) entity that holds the collection data.
|
||||
*/
|
||||
public String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
public Map<String, Object> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* For use by bi-directional associations.
|
||||
* @return The affected element, which was changed (added, removed, modified) in the collection.
|
||||
*/
|
||||
public Object getChangedElement() {
|
||||
return changedElement;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface PropertyMapper {
|
||||
/**
|
||||
* Maps properties to the given map, basing on differences between properties of new and old objects.
|
||||
* @param data Data to map to.
|
||||
* @param newObj New state of the entity.
|
||||
* @param oldObj Old state of the entity.
|
||||
* @return True if there are any differences between the states represented by newObj and oldObj.
|
||||
*/
|
||||
boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj);
|
||||
|
||||
/**
|
||||
* Maps properties from the given map to the given object.
|
||||
* @param verCfg Versions configuration.
|
||||
* @param obj Object to map to.
|
||||
* @param data Data to map from.
|
||||
* @param primaryKey Primary key of the object to which we map (for relations)
|
||||
* @param versionsReader VersionsReader for reading relations
|
||||
* @param revision Revision at which the object is read, for reading relations
|
||||
*/
|
||||
void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
VersionsReaderImplementor versionsReader, Number revision);
|
||||
|
||||
/**
|
||||
* Maps collection changes
|
||||
* @param referencingPropertyName Name of the field, which holds the collection in the entity.
|
||||
* @param newColl New collection, after updates.
|
||||
* @param oldColl Old collection, before updates.
|
||||
* @param id Id of the object owning the collection.
|
||||
* @return List of changes that need to be performed on the persistent store.
|
||||
*/
|
||||
List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl, Serializable id);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface SimpleMapperBuilder {
|
||||
public void add(String propertyName, ModificationStore modStore);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.tools.Tools;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* TODO: diff
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
|
||||
private String propertyName;
|
||||
|
||||
public SinglePropertyMapper() { }
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
if (this.propertyName != null) {
|
||||
throw new VersionsException("Only one property can be added!");
|
||||
}
|
||||
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
data.put(propertyName, newObj);
|
||||
|
||||
return !Tools.objectsEqual(newObj, oldObj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
|
||||
if (data == null || obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
setter.set(obj, data.get(propertyName), null);
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper;
|
||||
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A mapper which maps from a parent mapper and a "main" one, but adds only to the "main". The "main" mapper
|
||||
* should be the mapper of the subclass.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SubclassPropertyMapper implements ExtendedPropertyMapper {
|
||||
private ExtendedPropertyMapper main;
|
||||
private ExtendedPropertyMapper parentMapper;
|
||||
|
||||
public SubclassPropertyMapper(ExtendedPropertyMapper main, ExtendedPropertyMapper parentMapper) {
|
||||
this.main = main;
|
||||
this.parentMapper = parentMapper;
|
||||
}
|
||||
|
||||
public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
|
||||
boolean parentDiffs = parentMapper.map(data, propertyNames, newState, oldState);
|
||||
boolean mainDiffs = main.map(data, propertyNames, newState, oldState);
|
||||
|
||||
return parentDiffs || mainDiffs;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
boolean parentDiffs = parentMapper.mapToMapFromEntity(data, newObj, oldObj);
|
||||
boolean mainDiffs = main.mapToMapFromEntity(data, newObj, oldObj);
|
||||
|
||||
return parentDiffs || mainDiffs;
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
|
||||
parentMapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||
main.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
List<PersistentCollectionChangeData> collectionChanges = parentMapper.mapCollectionChanges(
|
||||
referencingPropertyName, newColl, oldColl, id);
|
||||
|
||||
if (collectionChanges == null) {
|
||||
return main.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
|
||||
} else {
|
||||
return collectionChanges;
|
||||
}
|
||||
}
|
||||
|
||||
public CompositeMapperBuilder addComposite(String propertyName) {
|
||||
return main.addComposite(propertyName);
|
||||
}
|
||||
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
|
||||
main.addComposite(propertyName, propertyMapper);
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
main.add(propertyName, modStore);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractCompositeIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
|
||||
protected Map<String, SingleIdMapper> ids;
|
||||
protected String compositeIdClass;
|
||||
|
||||
protected AbstractCompositeIdMapper(String compositeIdClass) {
|
||||
ids = new LinkedHashMap<String, SingleIdMapper>();
|
||||
|
||||
this.compositeIdClass = compositeIdClass;
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
ids.put(propertyName, new SingleIdMapper(propertyName));
|
||||
}
|
||||
|
||||
public Object mapToIdFromMap(Map data) {
|
||||
Object ret;
|
||||
try {
|
||||
ret = Thread.currentThread().getContextClassLoader().loadClass(compositeIdClass).newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
|
||||
for (SingleIdMapper mapper : ids.values()) {
|
||||
mapper.mapToEntityFromMap(ret, data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractIdMapper implements IdMapper {
|
||||
private Parameters getParametersToUse(Parameters parameters, List<QueryParameterData> paramDatas) {
|
||||
if (paramDatas.size() > 1) {
|
||||
return parameters.addSubParameters("and");
|
||||
} else {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
public void addIdsEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
List<QueryParameterData> paramDatas = mapToQueryParametersFromId(null);
|
||||
|
||||
Parameters parametersToUse = getParametersToUse(parameters, paramDatas);
|
||||
|
||||
for (QueryParameterData paramData : paramDatas) {
|
||||
parametersToUse.addWhere(paramData.getProperty(prefix1), false, "=", paramData.getProperty(prefix2), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void addIdsEqualToQuery(Parameters parameters, String prefix1, IdMapper mapper2, String prefix2) {
|
||||
List<QueryParameterData> paramDatas1 = mapToQueryParametersFromId(null);
|
||||
List<QueryParameterData> paramDatas2 = mapper2.mapToQueryParametersFromId(null);
|
||||
|
||||
Parameters parametersToUse = getParametersToUse(parameters, paramDatas1);
|
||||
|
||||
Iterator<QueryParameterData> paramDataIter1 = paramDatas1.iterator();
|
||||
Iterator<QueryParameterData> paramDataIter2 = paramDatas2.iterator();
|
||||
while (paramDataIter1.hasNext()) {
|
||||
QueryParameterData paramData1 = paramDataIter1.next();
|
||||
QueryParameterData paramData2 = paramDataIter2.next();
|
||||
|
||||
parametersToUse.addWhere(paramData1.getProperty(prefix1), false, "=", paramData2.getProperty(prefix2), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void addIdEqualsToQuery(Parameters parameters, Object id, String prefix, boolean equals) {
|
||||
List<QueryParameterData> paramDatas = mapToQueryParametersFromId(id);
|
||||
|
||||
Parameters parametersToUse = getParametersToUse(parameters, paramDatas);
|
||||
|
||||
for (QueryParameterData paramData : paramDatas) {
|
||||
parametersToUse.addWhereWithParam(paramData.getProperty(prefix), equals ? "=" : "<>", paramData.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void addNamedIdEqualsToQuery(Parameters parameters, String prefix, boolean equals) {
|
||||
List<QueryParameterData> paramDatas = mapToQueryParametersFromId(null);
|
||||
|
||||
Parameters parametersToUse = getParametersToUse(parameters, paramDatas);
|
||||
|
||||
for (QueryParameterData paramData : paramDatas) {
|
||||
parametersToUse.addWhereWithNamedParam(paramData.getProperty(prefix), equals ? "=" : "<>", paramData.getQueryParameterName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
|
||||
private String idPropertyName;
|
||||
|
||||
public EmbeddedIdMapper(String idPropertyName, String compositeIdClass) {
|
||||
super(compositeIdClass);
|
||||
|
||||
this.idPropertyName = idPropertyName;
|
||||
}
|
||||
|
||||
public void mapToMapFromId(Map<String, Object> data, Object obj) {
|
||||
for (IdMapper idMapper : ids.values()) {
|
||||
idMapper.mapToMapFromEntity(data, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
|
||||
mapToMapFromId(data, getter.get(obj));
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(Object obj, Map data) {
|
||||
if (data == null || obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), idPropertyName);
|
||||
|
||||
try {
|
||||
Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
|
||||
setter.set(obj, subObj, null);
|
||||
|
||||
for (IdMapper idMapper : ids.values()) {
|
||||
idMapper.mapToEntityFromMap(subObj, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public IdMapper prefixMappedProperties(String prefix) {
|
||||
EmbeddedIdMapper ret = new EmbeddedIdMapper(idPropertyName, compositeIdClass);
|
||||
|
||||
for (String propertyName : ids.keySet()) {
|
||||
ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Object mapToIdFromEntity(Object data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(data.getClass(), idPropertyName);
|
||||
return getter.get(data);
|
||||
}
|
||||
|
||||
public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
|
||||
Map<String, Object> data = new LinkedHashMap<String, Object>();
|
||||
mapToMapFromId(data, obj);
|
||||
|
||||
List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
|
||||
|
||||
for (Map.Entry<String, Object> propertyData : data.entrySet()) {
|
||||
ret.add(new QueryParameterData(propertyData.getKey(), propertyData.getValue()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface IdMapper {
|
||||
void mapToMapFromId(Map<String, Object> data, Object obj);
|
||||
|
||||
void mapToMapFromEntity(Map<String, Object> data, Object obj);
|
||||
|
||||
void mapToEntityFromMap(Object obj, Map data);
|
||||
|
||||
Object mapToIdFromEntity(Object data);
|
||||
|
||||
Object mapToIdFromMap(Map data);
|
||||
|
||||
/**
|
||||
* Creates a mapper with all mapped properties prefixed. A mapped property is a property which
|
||||
* is directly mapped to values (not composite).
|
||||
* @param prefix Prefix to add to mapped properties
|
||||
* @return A copy of the current property mapper, with mapped properties prefixed.
|
||||
*/
|
||||
IdMapper prefixMappedProperties(String prefix);
|
||||
|
||||
/**
|
||||
* @param obj Id from which to map.
|
||||
* @return A set parameter data, needed to build a query basing on the given id.
|
||||
*/
|
||||
List<QueryParameterData> mapToQueryParametersFromId(Object obj);
|
||||
|
||||
/**
|
||||
* Adds query statements, which contains restrictions, which express the property that the id of the entity
|
||||
* with alias prefix1, is equal to the id of the entity with alias prefix2 (the entity is the same).
|
||||
* @param parameters Parameters, to which to add the statements.
|
||||
* @param prefix1 First alias of the entity + prefix to add to the properties.
|
||||
* @param prefix2 Second alias of the entity + prefix to add to the properties.
|
||||
*/
|
||||
void addIdsEqualToQuery(Parameters parameters, String prefix1, String prefix2);
|
||||
|
||||
/**
|
||||
* Adds query statements, which contains restrictions, which express the property that the id of the entity
|
||||
* with alias prefix1, is equal to the id of the entity with alias prefix2 mapped by the second mapper
|
||||
* (the second mapper must be for the same entity, but it can have, for example, prefixed properties).
|
||||
* @param parameters Parameters, to which to add the statements.
|
||||
* @param prefix1 First alias of the entity + prefix to add to the properties.
|
||||
* @param mapper2 Second mapper for the same entity, which will be used to get properties for the right side
|
||||
* of the equation.
|
||||
* @param prefix2 Second alias of the entity + prefix to add to the properties.
|
||||
*/
|
||||
void addIdsEqualToQuery(Parameters parameters, String prefix1, IdMapper mapper2, String prefix2);
|
||||
|
||||
/**
|
||||
* Adds query statements, which contains restrictions, which express the property that the id of the entity
|
||||
* with alias prefix, is equal to the given object.
|
||||
* @param parameters Parameters, to which to add the statements.
|
||||
* @param id Value of id.
|
||||
* @param prefix Prefix to add to the properties (may be null).
|
||||
* @param equals Should this query express the "=" relation or the "<>" relation.
|
||||
*/
|
||||
void addIdEqualsToQuery(Parameters parameters, Object id, String prefix, boolean equals);
|
||||
|
||||
/**
|
||||
* Adds query statements, which contains named parameters, which express the property that the id of the entity
|
||||
* with alias prefix, is equal to the given object. It is the responsibility of the using method to read
|
||||
* parameter values from the id and specify them on the final query object.
|
||||
* @param parameters Parameters, to which to add the statements.
|
||||
* @param prefix Prefix to add to the properties (may be null).
|
||||
* @param equals Should this query express the "=" relation or the "<>" relation.
|
||||
*/
|
||||
void addNamedIdEqualsToQuery(Parameters parameters, String prefix, boolean equals);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MultipleIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
|
||||
public MultipleIdMapper(String compositeIdClass) {
|
||||
super(compositeIdClass);
|
||||
}
|
||||
|
||||
public void mapToMapFromId(Map<String, Object> data, Object obj) {
|
||||
for (IdMapper idMapper : ids.values()) {
|
||||
idMapper.mapToMapFromEntity(data, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
|
||||
mapToMapFromId(data, obj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(Object obj, Map data) {
|
||||
for (IdMapper idMapper : ids.values()) {
|
||||
idMapper.mapToEntityFromMap(obj, data);
|
||||
}
|
||||
}
|
||||
|
||||
public IdMapper prefixMappedProperties(String prefix) {
|
||||
MultipleIdMapper ret = new MultipleIdMapper(compositeIdClass);
|
||||
|
||||
for (String propertyName : ids.keySet()) {
|
||||
ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Object mapToIdFromEntity(Object data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object ret;
|
||||
try {
|
||||
ret = Thread.currentThread().getContextClassLoader().loadClass(compositeIdClass).newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
|
||||
for (SingleIdMapper mapper : ids.values()) {
|
||||
mapper.mapToEntityFromEntity(ret, data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
|
||||
Map<String, Object> data = new LinkedHashMap<String, Object>();
|
||||
mapToMapFromId(data, obj);
|
||||
|
||||
List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
|
||||
|
||||
for (Map.Entry<String, Object> propertyData : data.entrySet()) {
|
||||
ret.add(new QueryParameterData(propertyData.getKey(), propertyData.getValue()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.hibernate.Query;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class QueryParameterData {
|
||||
private String flatEntityPropertyName;
|
||||
private Object value;
|
||||
|
||||
public QueryParameterData(String flatEntityPropertyName, Object value) {
|
||||
this.flatEntityPropertyName = flatEntityPropertyName;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getProperty(String prefix) {
|
||||
if (prefix != null) {
|
||||
return prefix + "." + flatEntityPropertyName;
|
||||
} else {
|
||||
return flatEntityPropertyName;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setParameterValue(Query query) {
|
||||
query.setParameter(flatEntityPropertyName, value);
|
||||
}
|
||||
|
||||
public String getQueryParameterName() {
|
||||
return flatEntityPropertyName;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof QueryParameterData)) return false;
|
||||
|
||||
QueryParameterData that = (QueryParameterData) o;
|
||||
|
||||
if (flatEntityPropertyName != null ? !flatEntityPropertyName.equals(that.flatEntityPropertyName) : that.flatEntityPropertyName != null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (flatEntityPropertyName != null ? flatEntityPropertyName.hashCode() : 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.jboss.envers.entities.mapper.SimpleMapperBuilder;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface SimpleIdMapperBuilder extends IdMapper, SimpleMapperBuilder {
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.id;
|
||||
|
||||
import org.jboss.envers.ModificationStore;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.property.Getter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
|
||||
private String beanPropertyName;
|
||||
private String propertyName;
|
||||
|
||||
public SingleIdMapper() {
|
||||
}
|
||||
|
||||
public SingleIdMapper(String beanPropertyName, String propertyName) {
|
||||
this.beanPropertyName = beanPropertyName;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public SingleIdMapper(String propertyName) {
|
||||
this.beanPropertyName = propertyName;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
if (this.propertyName != null) {
|
||||
throw new VersionsException("Only one property can be added!");
|
||||
}
|
||||
|
||||
this.propertyName = propertyName;
|
||||
this.beanPropertyName = propertyName;
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(Object obj, Map data) {
|
||||
if (data == null || obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), beanPropertyName);
|
||||
setter.set(obj, data.get(propertyName), null);
|
||||
}
|
||||
|
||||
public Object mapToIdFromMap(Map data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return data.get(propertyName);
|
||||
}
|
||||
|
||||
public Object mapToIdFromEntity(Object data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(data.getClass(), beanPropertyName);
|
||||
return getter.get(data);
|
||||
}
|
||||
|
||||
public void mapToMapFromId(Map<String, Object> data, Object obj) {
|
||||
if (data != null) {
|
||||
data.put(propertyName, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
|
||||
if (obj == null) {
|
||||
data.put(propertyName, null);
|
||||
} else {
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), beanPropertyName);
|
||||
data.put(propertyName, getter.get(obj));
|
||||
}
|
||||
}
|
||||
|
||||
public void mapToEntityFromEntity(Object objTo, Object objFrom) {
|
||||
if (objTo == null || objFrom == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(objFrom.getClass(), beanPropertyName);
|
||||
Setter setter = ReflectionTools.getSetter(objTo.getClass(), beanPropertyName);
|
||||
setter.set(objTo, getter.get(objFrom), null);
|
||||
}
|
||||
|
||||
public IdMapper prefixMappedProperties(String prefix) {
|
||||
return new SingleIdMapper(propertyName, prefix + propertyName);
|
||||
}
|
||||
|
||||
public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
|
||||
List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
|
||||
|
||||
ret.add(new QueryParameterData(propertyName, obj));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
import org.jboss.envers.entities.mapper.PropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
import org.jboss.envers.RevisionType;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Setter;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
||||
protected final CommonCollectionMapperData commonCollectionMapperData;
|
||||
protected final Class<? extends T> collectionClass;
|
||||
|
||||
private final Constructor<? extends T> proxyConstructor;
|
||||
|
||||
protected AbstractCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
|
||||
Class<? extends T> collectionClass, Class<? extends T> proxyClass) {
|
||||
this.commonCollectionMapperData = commonCollectionMapperData;
|
||||
this.collectionClass = collectionClass;
|
||||
|
||||
try {
|
||||
proxyConstructor = proxyClass.getConstructor(Initializor.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Collection getNewCollectionContent(PersistentCollection newCollection);
|
||||
protected abstract Collection getOldCollectionContent(Serializable oldCollection);
|
||||
protected abstract Object getElement(Object changedObject);
|
||||
|
||||
/**
|
||||
* Maps the changed collection element to the given map.
|
||||
* @param data Where to map the data.
|
||||
* @param changed The changed collection element to map.
|
||||
*/
|
||||
protected abstract void mapToMapFromObject(Map<String, Object> data, Object changed);
|
||||
|
||||
private void addCollectionChanges(List<PersistentCollectionChangeData> collectionChanges, Set<Object> changed,
|
||||
RevisionType revisionType, Serializable id) {
|
||||
for (Object changedObj : changed) {
|
||||
Map<String, Object> entityData = new HashMap<String, Object>();
|
||||
Map<String, Object> originalId = new HashMap<String, Object>();
|
||||
entityData.put(commonCollectionMapperData.getVerEntCfg().getOriginalIdPropName(), originalId);
|
||||
|
||||
collectionChanges.add(new PersistentCollectionChangeData(
|
||||
commonCollectionMapperData.getVersionsMiddleEntityName(), entityData, getElement(changedObj)));
|
||||
// Mapping the collection owner's id.
|
||||
commonCollectionMapperData.getReferencingIdData().getPrefixedMapper().mapToMapFromId(originalId, id);
|
||||
|
||||
// Mapping collection element and index (if present).
|
||||
mapToMapFromObject(originalId, changedObj);
|
||||
|
||||
entityData.put(commonCollectionMapperData.getVerEntCfg().getRevisionTypePropName(), revisionType);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl, Serializable id) {
|
||||
if (!commonCollectionMapperData.getCollectionReferencingPropertyName().equals(referencingPropertyName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<PersistentCollectionChangeData> collectionChanges = new ArrayList<PersistentCollectionChangeData>();
|
||||
|
||||
// Comparing new and old collection content.
|
||||
Collection newCollection = getNewCollectionContent(newColl);
|
||||
Collection oldCollection = getOldCollectionContent(oldColl);
|
||||
|
||||
Set<Object> added = new HashSet<Object>();
|
||||
if (newColl != null) { added.addAll(newCollection); }
|
||||
if (oldColl != null) { added.removeAll(oldCollection); }
|
||||
|
||||
addCollectionChanges(collectionChanges, added, RevisionType.ADD, id);
|
||||
|
||||
Set<Object> deleted = new HashSet<Object>();
|
||||
if (oldColl != null) { deleted.addAll(oldCollection); }
|
||||
if (newColl != null) { deleted.removeAll(newCollection); }
|
||||
|
||||
addCollectionChanges(collectionChanges, deleted, RevisionType.DEL, id);
|
||||
|
||||
return collectionChanges;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
// Changes are mapped in the "mapCollectionChanges" method.
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract Initializor<T> getInitializor(VersionsConfiguration verCfg,
|
||||
VersionsReaderImplementor versionsReader, Object primaryKey,
|
||||
Number revision);
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
VersionsReaderImplementor versionsReader, Number revision) {
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(),
|
||||
commonCollectionMapperData.getCollectionReferencingPropertyName());
|
||||
try {
|
||||
setter.set(obj, proxyConstructor.newInstance(getInitializor(verCfg, versionsReader, primaryKey, revision)), null);
|
||||
} catch (InstantiationException e) {
|
||||
throw new VersionsException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new VersionsException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.PropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.BasicCollectionInitializor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class BasicCollectionMapper<T extends Collection> extends AbstractCollectionMapper<T> implements PropertyMapper {
|
||||
private final MiddleComponentData elementComponentData;
|
||||
|
||||
public BasicCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
|
||||
Class<? extends T> collectionClass, Class<? extends T> proxyClass,
|
||||
MiddleComponentData elementComponentData) {
|
||||
super(commonCollectionMapperData, collectionClass, proxyClass);
|
||||
this.elementComponentData = elementComponentData;
|
||||
}
|
||||
|
||||
protected Initializor<T> getInitializor(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
|
||||
Object primaryKey, Number revision) {
|
||||
return new BasicCollectionInitializor<T>(verCfg, versionsReader, commonCollectionMapperData.getQueryGenerator(),
|
||||
primaryKey, revision, collectionClass, elementComponentData);
|
||||
}
|
||||
|
||||
protected Collection getNewCollectionContent(PersistentCollection newCollection) {
|
||||
return (Collection) newCollection;
|
||||
}
|
||||
|
||||
protected Collection getOldCollectionContent(Serializable oldCollection) {
|
||||
if (oldCollection == null) {
|
||||
return null;
|
||||
} else if (oldCollection instanceof Map) {
|
||||
return ((Map) oldCollection).keySet();
|
||||
} else {
|
||||
return (Collection) oldCollection;
|
||||
}
|
||||
}
|
||||
|
||||
protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
|
||||
elementComponentData.getComponentMapper().mapToMapFromObject(data, changed);
|
||||
}
|
||||
|
||||
protected Object getElement(Object changedObject) {
|
||||
return changedObject;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
|
||||
/**
|
||||
* Data that is used by all collection mappers, regardless of the type.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class CommonCollectionMapperData {
|
||||
private final VersionsEntitiesConfiguration verEntCfg;
|
||||
private final String versionsMiddleEntityName;
|
||||
private final String collectionReferencingPropertyName;
|
||||
private final MiddleIdData referencingIdData;
|
||||
private final RelationQueryGenerator queryGenerator;
|
||||
|
||||
public CommonCollectionMapperData(VersionsEntitiesConfiguration verEntCfg, String versionsMiddleEntityName,
|
||||
String collectionReferencingPropertyName, MiddleIdData referencingIdData,
|
||||
RelationQueryGenerator queryGenerator) {
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.versionsMiddleEntityName = versionsMiddleEntityName;
|
||||
this.collectionReferencingPropertyName = collectionReferencingPropertyName;
|
||||
this.referencingIdData = referencingIdData;
|
||||
this.queryGenerator = queryGenerator;
|
||||
}
|
||||
|
||||
public VersionsEntitiesConfiguration getVerEntCfg() {
|
||||
return verEntCfg;
|
||||
}
|
||||
|
||||
public String getVersionsMiddleEntityName() {
|
||||
return versionsMiddleEntityName;
|
||||
}
|
||||
|
||||
public String getCollectionReferencingPropertyName() {
|
||||
return collectionReferencingPropertyName;
|
||||
}
|
||||
|
||||
public MiddleIdData getReferencingIdData() {
|
||||
return referencingIdData;
|
||||
}
|
||||
|
||||
public RelationQueryGenerator getQueryGenerator() {
|
||||
return queryGenerator;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.PropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.proxy.ListProxy;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.tools.Tools;
|
||||
import org.jboss.envers.tools.Pair;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class ListCollectionMapper extends AbstractCollectionMapper<List> implements PropertyMapper {
|
||||
private final MiddleComponentData elementComponentData;
|
||||
private final MiddleComponentData indexComponentData;
|
||||
|
||||
public ListCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
|
||||
MiddleComponentData elementComponentData, MiddleComponentData indexComponentData) {
|
||||
super(commonCollectionMapperData, List.class, ListProxy.class);
|
||||
this.elementComponentData = elementComponentData;
|
||||
this.indexComponentData = indexComponentData;
|
||||
}
|
||||
|
||||
protected Initializor<List> getInitializor(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
|
||||
Object primaryKey, Number revision) {
|
||||
return new ListCollectionInitializor(verCfg, versionsReader, commonCollectionMapperData.getQueryGenerator(),
|
||||
primaryKey, revision, elementComponentData, indexComponentData);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected Collection getNewCollectionContent(PersistentCollection newCollection) {
|
||||
if (newCollection == null) {
|
||||
return null;
|
||||
} else {
|
||||
return Tools.listToIndexElementPairList((List<Object>) newCollection);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected Collection getOldCollectionContent(Serializable oldCollection) {
|
||||
if (oldCollection == null) {
|
||||
return null;
|
||||
} else {
|
||||
return Tools.listToIndexElementPairList((List<Object>) oldCollection);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
|
||||
Pair<Integer, Object> indexValuePair = (Pair<Integer, Object>) changed;
|
||||
elementComponentData.getComponentMapper().mapToMapFromObject(data, indexValuePair.getSecond());
|
||||
indexComponentData.getComponentMapper().mapToMapFromObject(data, indexValuePair.getFirst());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected Object getElement(Object changedObject) {
|
||||
return ((Pair<Integer, Object>) changedObject).getFirst();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.PropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.MapCollectionInitializor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MapCollectionMapper<T extends Map> extends AbstractCollectionMapper<T> implements PropertyMapper {
|
||||
private final MiddleComponentData elementComponentData;
|
||||
private final MiddleComponentData indexComponentData;
|
||||
|
||||
public MapCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
|
||||
Class<? extends T> collectionClass, Class<? extends T> proxyClass,
|
||||
MiddleComponentData elementComponentData, MiddleComponentData indexComponentData) {
|
||||
super(commonCollectionMapperData, collectionClass, proxyClass);
|
||||
this.elementComponentData = elementComponentData;
|
||||
this.indexComponentData = indexComponentData;
|
||||
}
|
||||
|
||||
protected Initializor<T> getInitializor(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
|
||||
Object primaryKey, Number revision) {
|
||||
return new MapCollectionInitializor<T>(verCfg, versionsReader, commonCollectionMapperData.getQueryGenerator(),
|
||||
primaryKey, revision, collectionClass, elementComponentData, indexComponentData);
|
||||
}
|
||||
|
||||
protected Collection getNewCollectionContent(PersistentCollection newCollection) {
|
||||
if (newCollection == null) {
|
||||
return null;
|
||||
} else {
|
||||
return ((Map) newCollection).entrySet();
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection getOldCollectionContent(Serializable oldCollection) {
|
||||
if (oldCollection == null) {
|
||||
return null;
|
||||
} else {
|
||||
return ((Map) oldCollection).entrySet();
|
||||
}
|
||||
}
|
||||
|
||||
protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
|
||||
elementComponentData.getComponentMapper().mapToMapFromObject(data, ((Map.Entry) changed).getValue());
|
||||
indexComponentData.getComponentMapper().mapToMapFromObject(data, ((Map.Entry) changed).getKey());
|
||||
}
|
||||
|
||||
protected Object getElement(Object changedObject) {
|
||||
return ((Map.Entry) changedObject).getValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.component.MiddleComponentMapper;
|
||||
|
||||
/**
|
||||
* A data holder for a middle relation component (which is either the collection element or index):
|
||||
* - component mapper used to map the component to and from versions entities
|
||||
* - an index, which specifies in which element of the array returned by the query for reading the collection the data
|
||||
* of the component is
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleComponentData {
|
||||
private final MiddleComponentMapper componentMapper;
|
||||
private final int componentIndex;
|
||||
|
||||
public MiddleComponentData(MiddleComponentMapper componentMapper, int componentIndex) {
|
||||
this.componentMapper = componentMapper;
|
||||
this.componentIndex = componentIndex;
|
||||
}
|
||||
|
||||
public MiddleComponentMapper getComponentMapper() {
|
||||
return componentMapper;
|
||||
}
|
||||
|
||||
public int getComponentIndex() {
|
||||
return componentIndex;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.jboss.envers.entities.IdMappingData;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
|
||||
/**
|
||||
* A class holding information about ids, which form a virtual "relation" from a middle-table. Middle-tables are used
|
||||
* when mapping collections.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleIdData {
|
||||
/**
|
||||
* Original id mapper of the related entity.
|
||||
*/
|
||||
private final IdMapper originalMapper;
|
||||
/**
|
||||
* Prefixed id mapper (with the names for the id fields that are used in the middle table) of the related entity.
|
||||
*/
|
||||
private final IdMapper prefixedMapper;
|
||||
/**
|
||||
* Name of the related entity.
|
||||
*/
|
||||
private final String entityName;
|
||||
/**
|
||||
* Versions name of the related entity.
|
||||
*/
|
||||
private final String versionsEntityName;
|
||||
|
||||
public MiddleIdData(VersionsEntitiesConfiguration verEntCfg, IdMappingData mappingData, String prefix,
|
||||
String entityName) {
|
||||
this.originalMapper = mappingData.getIdMapper();
|
||||
this.prefixedMapper = mappingData.getIdMapper().prefixMappedProperties(prefix);
|
||||
this.entityName = entityName;
|
||||
this.versionsEntityName = verEntCfg.getVersionsEntityName(entityName);
|
||||
}
|
||||
|
||||
public IdMapper getOriginalMapper() {
|
||||
return originalMapper;
|
||||
}
|
||||
|
||||
public IdMapper getPrefixedMapper() {
|
||||
return prefixedMapper;
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
public String getVersionsEntityName() {
|
||||
return versionsEntityName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.PropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.query.VersionsRestrictions;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.NonUniqueResultException;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import javax.persistence.NoResultException;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class OneToOneNotOwningMapper implements PropertyMapper {
|
||||
private String owningReferencePropertyName;
|
||||
private String owningEntityName;
|
||||
private String propertyName;
|
||||
|
||||
public OneToOneNotOwningMapper(String owningReferencePropertyName, String owningEntityName, String propertyName) {
|
||||
this.owningReferencePropertyName = owningReferencePropertyName;
|
||||
this.owningEntityName = owningEntityName;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> entityClass = ReflectionTools.loadClass(owningEntityName);
|
||||
|
||||
Object value;
|
||||
|
||||
try {
|
||||
value = versionsReader.createQuery().forEntitiesAtRevision(entityClass, revision)
|
||||
.add(VersionsRestrictions.relatedIdEq(owningReferencePropertyName, primaryKey)).getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
value = null;
|
||||
} catch (NonUniqueResultException e) {
|
||||
throw new VersionsException("Many versions results for one-to-one relationship: (" + owningEntityName +
|
||||
", " + owningReferencePropertyName + ")");
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
setter.set(obj, value, null);
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation;
|
||||
|
||||
import org.jboss.envers.entities.mapper.PropertyMapper;
|
||||
import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.jboss.envers.tools.Tools;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ToOneIdMapper implements PropertyMapper {
|
||||
private final IdMapper delegate;
|
||||
private final String propertyName;
|
||||
private final String referencedEntityName;
|
||||
|
||||
public ToOneIdMapper(IdMapper delegate, String propertyName, String referencedEntityName) {
|
||||
this.delegate = delegate;
|
||||
this.propertyName = propertyName;
|
||||
this.referencedEntityName = referencedEntityName;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
HashMap<String, Object> newData = new HashMap<String, Object>();
|
||||
data.put(propertyName, newData);
|
||||
|
||||
delegate.mapToMapFromEntity(newData, newObj);
|
||||
|
||||
return !Tools.objectsEqual(newObj, oldObj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
VersionsReaderImplementor versionsReader, Number revision) {
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyName));
|
||||
Object value;
|
||||
if (entityId == null) {
|
||||
value = null;
|
||||
} else {
|
||||
if (versionsReader.getFirstLevelCache().contains(referencedEntityName, revision, entityId)) {
|
||||
value = versionsReader.getFirstLevelCache().get(referencedEntityName, revision, entityId);
|
||||
} else {
|
||||
Class<?> entityClass = ReflectionTools.loadClass(referencedEntityName);
|
||||
|
||||
value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
|
||||
createProxy(null, new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision));
|
||||
}
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
setter.set(obj, value, null);
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.component;
|
||||
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface MiddleComponentMapper {
|
||||
/**
|
||||
* Maps from full object data, contained in the given map (or object representation of the map, if
|
||||
* available), to an object.
|
||||
* @param entityInstantiator An entity instatiator bound with an open versions reader.
|
||||
* @param data Full object data.
|
||||
* @param dataObject An optional object representation of the data.
|
||||
* @param revision Revision at which the data is read.
|
||||
* @return An object with data corresponding to the one found in the given map.
|
||||
*/
|
||||
Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision);
|
||||
|
||||
/**
|
||||
* Maps from an object to the object's map representation (for an entity - only its id).
|
||||
* @param data Map to which data should be added.
|
||||
* @param obj Object to map from.
|
||||
*/
|
||||
void mapToMapFromObject(Map<String, Object> data, Object obj);
|
||||
|
||||
/**
|
||||
* Adds query statements, which contains restrictions, which express the property that part of the middle
|
||||
* entity with alias prefix1, is equal to part of the middle entity with alias prefix2 (the entity is the same).
|
||||
* The part is the component's representation in the middle entity.
|
||||
* @param parameters Parameters, to which to add the statements.
|
||||
* @param prefix1 First alias of the entity + prefix to add to the properties.
|
||||
* @param prefix2 Second alias of the entity + prefix to add to the properties.
|
||||
*/
|
||||
void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.component;
|
||||
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleDummyComponentMapper implements MiddleComponentMapper {
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
}
|
||||
|
||||
public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.component;
|
||||
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A component mapper for the @MapKey mapping: the value of the map's key is the id of the entity. This
|
||||
* doesn't have an effect on the data stored in the versions tables, so <code>mapToMapFromObject</code> is
|
||||
* empty.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleMapKeyIdComponentMapper implements MiddleComponentMapper {
|
||||
private final VersionsEntitiesConfiguration verEntCfg;
|
||||
private final IdMapper relatedIdMapper;
|
||||
|
||||
public MiddleMapKeyIdComponentMapper(VersionsEntitiesConfiguration verEntCfg, IdMapper relatedIdMapper) {
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.relatedIdMapper = relatedIdMapper;
|
||||
}
|
||||
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
return relatedIdMapper.mapToIdFromMap((Map) data.get(verEntCfg.getOriginalIdPropName()));
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
// Doing nothing.
|
||||
}
|
||||
|
||||
public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
// Doing nothing.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.component;
|
||||
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
import org.jboss.envers.tools.reflection.ReflectionTools;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A component mapper for the @MapKey mapping with the name parameter specified: the value of the map's key
|
||||
* is a property of the entity. This doesn't have an effect on the data stored in the versions tables,
|
||||
* so <code>mapToMapFromObject</code> is empty.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper {
|
||||
private final String propertyName;
|
||||
|
||||
public MiddleMapKeyPropertyComponentMapper(String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
// dataObject is not null, as this mapper can only be used in an index.
|
||||
return ReflectionTools.getGetter(dataObject.getClass(), propertyName).get(dataObject);
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
// Doing nothing.
|
||||
}
|
||||
|
||||
public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
// Doing nothing.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.component;
|
||||
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleRelatedComponentMapper implements MiddleComponentMapper {
|
||||
private final MiddleIdData relatedIdData;
|
||||
|
||||
public MiddleRelatedComponentMapper(MiddleIdData relatedIdData) {
|
||||
this.relatedIdData = relatedIdData;
|
||||
}
|
||||
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
return entityInstantiator.createInstanceFromVersionsEntity(relatedIdData.getEntityName(), data, revision);
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
relatedIdData.getPrefixedMapper().mapToMapFromEntity(data, obj);
|
||||
}
|
||||
|
||||
public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
relatedIdData.getPrefixedMapper().addIdsEqualToQuery(parameters, prefix1, prefix2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.component;
|
||||
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleSimpleComponentMapper implements MiddleComponentMapper {
|
||||
private final String propertyName;
|
||||
private final VersionsEntitiesConfiguration verEntCfg;
|
||||
|
||||
public MiddleSimpleComponentMapper(VersionsEntitiesConfiguration verEntCfg, String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
this.verEntCfg = verEntCfg;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
return ((Map<String, Object>) data.get(verEntCfg.getOriginalIdPropName())).get(propertyName);
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
data.put(propertyName, obj);
|
||||
}
|
||||
|
||||
public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
parameters.addWhere(prefix1 + "." + propertyName, false, "=", prefix2 + "." + propertyName, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy;
|
||||
|
||||
import org.hibernate.engine.*;
|
||||
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
||||
import org.hibernate.*;
|
||||
import org.hibernate.event.EventListeners;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.loader.custom.CustomQuery;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.impl.CriteriaImpl;
|
||||
import org.hibernate.jdbc.Batcher;
|
||||
import org.hibernate.jdbc.JDBCContext;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractDelegateSessionImplementor implements SessionImplementor {
|
||||
private SessionImplementor delegate;
|
||||
|
||||
public AbstractDelegateSessionImplementor(SessionImplementor delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public abstract Object doImmediateLoad(String entityName);
|
||||
|
||||
public Object immediateLoad(String entityName, Serializable id) throws HibernateException {
|
||||
return doImmediateLoad(entityName);
|
||||
}
|
||||
|
||||
// Delegate methods
|
||||
|
||||
public LoadQueryInfluencers getLoadQueryInfluencers() {
|
||||
return delegate.getLoadQueryInfluencers();
|
||||
}
|
||||
|
||||
public Interceptor getInterceptor() {
|
||||
return delegate.getInterceptor();
|
||||
}
|
||||
|
||||
public void setAutoClear(boolean enabled) {
|
||||
delegate.setAutoClear(enabled);
|
||||
}
|
||||
|
||||
public boolean isTransactionInProgress() {
|
||||
return delegate.isTransactionInProgress();
|
||||
}
|
||||
|
||||
public void initializeCollection(PersistentCollection collection, boolean writing) throws HibernateException {
|
||||
delegate.initializeCollection(collection, writing);
|
||||
}
|
||||
|
||||
public Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) throws HibernateException {
|
||||
return delegate.internalLoad(entityName, id, eager, nullable);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return delegate.getTimestamp();
|
||||
}
|
||||
|
||||
public SessionFactoryImplementor getFactory() {
|
||||
return delegate.getFactory();
|
||||
}
|
||||
|
||||
public Batcher getBatcher() {
|
||||
return delegate.getBatcher();
|
||||
}
|
||||
|
||||
public List list(String query, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.list(query, queryParameters);
|
||||
}
|
||||
|
||||
public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.iterate(query, queryParameters);
|
||||
}
|
||||
|
||||
public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.scroll(query, queryParameters);
|
||||
}
|
||||
|
||||
public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode) {
|
||||
return delegate.scroll(criteria, scrollMode);
|
||||
}
|
||||
|
||||
public List list(CriteriaImpl criteria) {
|
||||
return delegate.list(criteria);
|
||||
}
|
||||
|
||||
public List listFilter(Object collection, String filter, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.listFilter(collection, filter, queryParameters);
|
||||
}
|
||||
|
||||
public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.iterateFilter(collection, filter, queryParameters);
|
||||
}
|
||||
|
||||
public EntityPersister getEntityPersister(String entityName, Object object) throws HibernateException {
|
||||
return delegate.getEntityPersister(entityName, object);
|
||||
}
|
||||
|
||||
public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException {
|
||||
return delegate.getEntityUsingInterceptor(key);
|
||||
}
|
||||
|
||||
public void afterTransactionCompletion(boolean successful, Transaction tx) {
|
||||
delegate.afterTransactionCompletion(successful, tx);
|
||||
}
|
||||
|
||||
public void beforeTransactionCompletion(Transaction tx) {
|
||||
delegate.beforeTransactionCompletion(tx);
|
||||
}
|
||||
|
||||
public Serializable getContextEntityIdentifier(Object object) {
|
||||
return delegate.getContextEntityIdentifier(object);
|
||||
}
|
||||
|
||||
public String bestGuessEntityName(Object object) {
|
||||
return delegate.bestGuessEntityName(object);
|
||||
}
|
||||
|
||||
public String guessEntityName(Object entity) throws HibernateException {
|
||||
return delegate.guessEntityName(entity);
|
||||
}
|
||||
|
||||
public Object instantiate(String entityName, Serializable id) throws HibernateException {
|
||||
return delegate.instantiate(entityName, id);
|
||||
}
|
||||
|
||||
public List listCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.listCustomQuery(customQuery, queryParameters);
|
||||
}
|
||||
|
||||
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.scrollCustomQuery(customQuery, queryParameters);
|
||||
}
|
||||
|
||||
public List list(NativeSQLQuerySpecification spec, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.list(spec, queryParameters);
|
||||
}
|
||||
|
||||
public ScrollableResults scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.scroll(spec, queryParameters);
|
||||
}
|
||||
|
||||
public Object getFilterParameterValue(String filterParameterName) {
|
||||
return delegate.getFilterParameterValue(filterParameterName);
|
||||
}
|
||||
|
||||
public Type getFilterParameterType(String filterParameterName) {
|
||||
return delegate.getFilterParameterType(filterParameterName);
|
||||
}
|
||||
|
||||
public Map getEnabledFilters() {
|
||||
return delegate.getEnabledFilters();
|
||||
}
|
||||
|
||||
public int getDontFlushFromFind() {
|
||||
return delegate.getDontFlushFromFind();
|
||||
}
|
||||
|
||||
public EventListeners getListeners() {
|
||||
return delegate.getListeners();
|
||||
}
|
||||
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return delegate.getPersistenceContext();
|
||||
}
|
||||
|
||||
public int executeUpdate(String query, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.executeUpdate(query, queryParameters);
|
||||
}
|
||||
|
||||
public int executeNativeUpdate(NativeSQLQuerySpecification specification, QueryParameters queryParameters) throws HibernateException {
|
||||
return delegate.executeNativeUpdate(specification, queryParameters);
|
||||
}
|
||||
|
||||
public EntityMode getEntityMode() {
|
||||
return delegate.getEntityMode();
|
||||
}
|
||||
|
||||
public CacheMode getCacheMode() {
|
||||
return delegate.getCacheMode();
|
||||
}
|
||||
|
||||
public void setCacheMode(CacheMode cm) {
|
||||
delegate.setCacheMode(cm);
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return delegate.isOpen();
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return delegate.isConnected();
|
||||
}
|
||||
|
||||
public FlushMode getFlushMode() {
|
||||
return delegate.getFlushMode();
|
||||
}
|
||||
|
||||
public void setFlushMode(FlushMode fm) {
|
||||
delegate.setFlushMode(fm);
|
||||
}
|
||||
|
||||
public Connection connection() {
|
||||
return delegate.connection();
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
delegate.flush();
|
||||
}
|
||||
|
||||
public Query getNamedQuery(String name) {
|
||||
return delegate.getNamedQuery(name);
|
||||
}
|
||||
|
||||
public Query getNamedSQLQuery(String name) {
|
||||
return delegate.getNamedSQLQuery(name);
|
||||
}
|
||||
|
||||
public boolean isEventSource() {
|
||||
return delegate.isEventSource();
|
||||
}
|
||||
|
||||
public void afterScrollOperation() {
|
||||
delegate.afterScrollOperation();
|
||||
}
|
||||
|
||||
public void setFetchProfile(String name) {
|
||||
delegate.setFetchProfile(name);
|
||||
}
|
||||
|
||||
public String getFetchProfile() {
|
||||
return delegate.getFetchProfile();
|
||||
}
|
||||
|
||||
public JDBCContext getJDBCContext() {
|
||||
return delegate.getJDBCContext();
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return delegate.isClosed();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImplementor {
|
||||
private final VersionsReaderImplementor versionsReader;
|
||||
private final Class<?> entityClass;
|
||||
private final Object entityId;
|
||||
private final Number revision;
|
||||
|
||||
public ToOneDelegateSessionImplementor(VersionsReaderImplementor versionsReader,
|
||||
Class<?> entityClass, Object entityId, Number revision) {
|
||||
super(versionsReader.getSessionImplementor());
|
||||
this.versionsReader = versionsReader;
|
||||
this.entityClass = entityClass;
|
||||
this.entityId = entityId;
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
public Object doImmediateLoad(String entityName) throws HibernateException {
|
||||
return versionsReader.find(entityClass, entityId, revision);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.initializor;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.EntityInstantiator;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Initializes a persistent collection.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractCollectionInitializor<T> implements Initializor<T> {
|
||||
private final VersionsReaderImplementor versionsReader;
|
||||
private final RelationQueryGenerator queryGenerator;
|
||||
private final Object primaryKey;
|
||||
|
||||
protected final Number revision;
|
||||
protected final EntityInstantiator entityInstantiator;
|
||||
|
||||
public AbstractCollectionInitializor(VersionsConfiguration verCfg,
|
||||
VersionsReaderImplementor versionsReader,
|
||||
RelationQueryGenerator queryGenerator,
|
||||
Object primaryKey, Number revision) {
|
||||
this.versionsReader = versionsReader;
|
||||
this.queryGenerator = queryGenerator;
|
||||
this.primaryKey = primaryKey;
|
||||
this.revision = revision;
|
||||
|
||||
entityInstantiator = new EntityInstantiator(verCfg, versionsReader);
|
||||
}
|
||||
|
||||
protected abstract T initializeCollection(int size);
|
||||
|
||||
protected abstract void addToCollection(T collection, Object collectionRow);
|
||||
|
||||
public T initialize() {
|
||||
List<?> collectionContent = queryGenerator.getQuery(versionsReader, primaryKey, revision).list();
|
||||
|
||||
T collection = initializeCollection(collectionContent.size());
|
||||
|
||||
for (Object collectionRow : collectionContent) {
|
||||
addToCollection(collection, collectionRow);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.initializor;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Initializes a map.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ArrayCollectionInitializor extends AbstractCollectionInitializor<Object[]> {
|
||||
private final MiddleComponentData elementComponentData;
|
||||
private final MiddleComponentData indexComponentData;
|
||||
|
||||
public ArrayCollectionInitializor(VersionsConfiguration verCfg,
|
||||
VersionsReaderImplementor versionsReader,
|
||||
RelationQueryGenerator queryGenerator,
|
||||
Object primaryKey, Number revision,
|
||||
MiddleComponentData elementComponentData,
|
||||
MiddleComponentData indexComponentData) {
|
||||
super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
|
||||
|
||||
this.elementComponentData = elementComponentData;
|
||||
this.indexComponentData = indexComponentData;
|
||||
}
|
||||
|
||||
protected Object[] initializeCollection(int size) {
|
||||
return new Object[size];
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected void addToCollection(Object[] collection, Object collectionRow) {
|
||||
Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
|
||||
Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) elementData, null, revision);
|
||||
|
||||
Object indexData = ((List) collectionRow).get(indexComponentData.getComponentIndex());
|
||||
Object indexObj = indexComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) indexData, element, revision);
|
||||
int index = ((Number) indexObj).intValue();
|
||||
|
||||
collection[index] = element;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.initializor;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Initializes a non-indexed java collection (set or list, eventually sorted).
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class BasicCollectionInitializor<T extends Collection> extends AbstractCollectionInitializor<T> {
|
||||
private final Class<? extends T> collectionClass;
|
||||
private final MiddleComponentData elementComponentData;
|
||||
|
||||
public BasicCollectionInitializor(VersionsConfiguration verCfg,
|
||||
VersionsReaderImplementor versionsReader,
|
||||
RelationQueryGenerator queryGenerator,
|
||||
Object primaryKey, Number revision,
|
||||
Class<? extends T> collectionClass,
|
||||
MiddleComponentData elementComponentData) {
|
||||
super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
|
||||
|
||||
this.collectionClass = collectionClass;
|
||||
this.elementComponentData = elementComponentData;
|
||||
}
|
||||
|
||||
protected T initializeCollection(int size) {
|
||||
try {
|
||||
return collectionClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new VersionsException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected void addToCollection(T collection, Object collectionRow) {
|
||||
Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
|
||||
Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) elementData, null, revision);
|
||||
collection.add(element);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.initializor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface Initializor<T> {
|
||||
T initialize();
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.initializor;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Initializes a map.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ListCollectionInitializor extends AbstractCollectionInitializor<List> {
|
||||
private final MiddleComponentData elementComponentData;
|
||||
private final MiddleComponentData indexComponentData;
|
||||
|
||||
public ListCollectionInitializor(VersionsConfiguration verCfg,
|
||||
VersionsReaderImplementor versionsReader,
|
||||
RelationQueryGenerator queryGenerator,
|
||||
Object primaryKey, Number revision,
|
||||
MiddleComponentData elementComponentData,
|
||||
MiddleComponentData indexComponentData) {
|
||||
super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
|
||||
|
||||
this.elementComponentData = elementComponentData;
|
||||
this.indexComponentData = indexComponentData;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected List initializeCollection(int size) {
|
||||
// Creating a list of the given capacity with all elements null initially. This ensures that we can then
|
||||
// fill the elements safely using the <code>List.set</code> method.
|
||||
List list = new ArrayList(size);
|
||||
for (int i=0; i<size; i++) { list.add(null); }
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected void addToCollection(List collection, Object collectionRow) {
|
||||
Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
|
||||
Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) elementData, null, revision);
|
||||
|
||||
Object indexData = ((List) collectionRow).get(indexComponentData.getComponentIndex());
|
||||
Object indexObj = indexComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) indexData, element, revision);
|
||||
int index = ((Number) indexObj).intValue();
|
||||
|
||||
collection.set(index, element);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.initializor;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.exception.VersionsException;
|
||||
import org.jboss.envers.configuration.VersionsConfiguration;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Initializes a map.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MapCollectionInitializor<T extends Map> extends AbstractCollectionInitializor<T> {
|
||||
private final Class<? extends T> collectionClass;
|
||||
private final MiddleComponentData elementComponentData;
|
||||
private final MiddleComponentData indexComponentData;
|
||||
|
||||
public MapCollectionInitializor(VersionsConfiguration verCfg,
|
||||
VersionsReaderImplementor versionsReader,
|
||||
RelationQueryGenerator queryGenerator,
|
||||
Object primaryKey, Number revision,
|
||||
Class<? extends T> collectionClass,
|
||||
MiddleComponentData elementComponentData,
|
||||
MiddleComponentData indexComponentData) {
|
||||
super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
|
||||
|
||||
this.collectionClass = collectionClass;
|
||||
this.elementComponentData = elementComponentData;
|
||||
this.indexComponentData = indexComponentData;
|
||||
}
|
||||
|
||||
protected T initializeCollection(int size) {
|
||||
try {
|
||||
return collectionClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new VersionsException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new VersionsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected void addToCollection(T collection, Object collectionRow) {
|
||||
Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
|
||||
Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) elementData, null, revision);
|
||||
|
||||
Object indexData = ((List) collectionRow).get(indexComponentData.getComponentIndex());
|
||||
Object index = indexComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
|
||||
(Map<String, Object>) indexData, element, revision);
|
||||
|
||||
collection.put(index, element);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.proxy;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class CollectionProxy<U, T extends Collection<U>> implements Collection<U> {
|
||||
private org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<T> initializor;
|
||||
protected T delegate;
|
||||
|
||||
public CollectionProxy(Initializor<T> initializor) {
|
||||
this.initializor = initializor;
|
||||
}
|
||||
|
||||
protected void checkInit() {
|
||||
if (delegate == null) {
|
||||
delegate = initializor.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
checkInit();
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
checkInit();
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
checkInit();
|
||||
return delegate.contains(o);
|
||||
}
|
||||
|
||||
public Iterator<U> iterator() {
|
||||
checkInit();
|
||||
return delegate.iterator();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
checkInit();
|
||||
return delegate.toArray();
|
||||
}
|
||||
|
||||
public <V> V[] toArray(V[] a) {
|
||||
checkInit();
|
||||
return delegate.toArray(a);
|
||||
}
|
||||
|
||||
public boolean add(U o) {
|
||||
checkInit();
|
||||
return delegate.add(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
checkInit();
|
||||
return delegate.remove(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
checkInit();
|
||||
return delegate.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends U> c) {
|
||||
checkInit();
|
||||
return delegate.addAll(c);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
checkInit();
|
||||
return delegate.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
checkInit();
|
||||
return delegate.retainAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
checkInit();
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
checkInit();
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
checkInit();
|
||||
return delegate.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
checkInit();
|
||||
return delegate.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.proxy;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ListProxy<U> extends CollectionProxy<U, List<U>> implements List<U> {
|
||||
public ListProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<List<U>> initializor) {
|
||||
super(initializor);
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends U> c) {
|
||||
checkInit();
|
||||
return delegate.addAll(index, c);
|
||||
}
|
||||
|
||||
public U get(int index) {
|
||||
checkInit();
|
||||
return delegate.get(index);
|
||||
}
|
||||
|
||||
public U set(int index, U element) {
|
||||
checkInit();
|
||||
return delegate.set(index, element);
|
||||
}
|
||||
|
||||
public void add(int index, U element) {
|
||||
checkInit();
|
||||
delegate.add(index, element);
|
||||
}
|
||||
|
||||
public U remove(int index) {
|
||||
checkInit();
|
||||
return delegate.remove(index);
|
||||
}
|
||||
|
||||
public int indexOf(Object o) {
|
||||
checkInit();
|
||||
return delegate.indexOf(o);
|
||||
}
|
||||
|
||||
public int lastIndexOf(Object o) {
|
||||
checkInit();
|
||||
return delegate.lastIndexOf(o);
|
||||
}
|
||||
|
||||
public ListIterator<U> listIterator() {
|
||||
checkInit();
|
||||
return delegate.listIterator();
|
||||
}
|
||||
|
||||
public ListIterator<U> listIterator(int index) {
|
||||
checkInit();
|
||||
return delegate.listIterator(index);
|
||||
}
|
||||
|
||||
public List<U> subList(int fromIndex, int toIndex) {
|
||||
checkInit();
|
||||
return delegate.subList(fromIndex, toIndex);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.proxy;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MapProxy<K, V> implements Map<K, V> {
|
||||
private Initializor<Map<K, V>> initializor;
|
||||
protected Map<K, V> delegate;
|
||||
|
||||
public MapProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<Map<K, V>> initializor) {
|
||||
this.initializor = initializor;
|
||||
}
|
||||
|
||||
private void checkInit() {
|
||||
if (delegate == null) {
|
||||
delegate = initializor.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
checkInit();
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
checkInit();
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object o) {
|
||||
checkInit();
|
||||
return delegate.containsKey(o);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object o) {
|
||||
checkInit();
|
||||
return delegate.containsValue(o);
|
||||
}
|
||||
|
||||
public V get(Object o) {
|
||||
checkInit();
|
||||
return delegate.get(o);
|
||||
}
|
||||
|
||||
public V put(K k, V v) {
|
||||
checkInit();
|
||||
return delegate.put(k, v);
|
||||
}
|
||||
|
||||
public V remove(Object o) {
|
||||
checkInit();
|
||||
return delegate.remove(o);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> map) {
|
||||
checkInit();
|
||||
delegate.putAll(map);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
checkInit();
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
checkInit();
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
checkInit();
|
||||
return delegate.values();
|
||||
}
|
||||
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
checkInit();
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
checkInit();
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
checkInit();
|
||||
return delegate.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
checkInit();
|
||||
return delegate.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Envers. http://www.jboss.org/envers
|
||||
*
|
||||
* Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT A WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.proxy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SetProxy<U> extends CollectionProxy<U, Set<U>> implements Set<U> {
|
||||
public SetProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<Set<U>> initializor) {
|
||||
super(initializor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.proxy;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SortedMapProxy<K, V> implements SortedMap<K, V> {
|
||||
private Initializor<SortedMap<K, V>> initializor;
|
||||
protected SortedMap<K, V> delegate;
|
||||
|
||||
public SortedMapProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<SortedMap<K, V>> initializor) {
|
||||
this.initializor = initializor;
|
||||
}
|
||||
|
||||
private void checkInit() {
|
||||
if (delegate == null) {
|
||||
delegate = initializor.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
checkInit();
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
checkInit();
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object o) {
|
||||
checkInit();
|
||||
return delegate.containsKey(o);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object o) {
|
||||
checkInit();
|
||||
return delegate.containsValue(o);
|
||||
}
|
||||
|
||||
public V get(Object o) {
|
||||
checkInit();
|
||||
return delegate.get(o);
|
||||
}
|
||||
|
||||
public V put(K k, V v) {
|
||||
checkInit();
|
||||
return delegate.put(k, v);
|
||||
}
|
||||
|
||||
public V remove(Object o) {
|
||||
checkInit();
|
||||
return delegate.remove(o);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> map) {
|
||||
checkInit();
|
||||
delegate.putAll(map);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
checkInit();
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
checkInit();
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
checkInit();
|
||||
return delegate.values();
|
||||
}
|
||||
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
checkInit();
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
public Comparator<? super K> comparator() {
|
||||
checkInit();
|
||||
return delegate.comparator();
|
||||
}
|
||||
|
||||
public SortedMap<K, V> subMap(K k, K k1) {
|
||||
checkInit();
|
||||
return delegate.subMap(k, k1);
|
||||
}
|
||||
|
||||
public SortedMap<K, V> headMap(K k) {
|
||||
checkInit();
|
||||
return delegate.headMap(k);
|
||||
}
|
||||
|
||||
public SortedMap<K, V> tailMap(K k) {
|
||||
checkInit();
|
||||
return delegate.tailMap(k);
|
||||
}
|
||||
|
||||
public K firstKey() {
|
||||
checkInit();
|
||||
return delegate.firstKey();
|
||||
}
|
||||
|
||||
public K lastKey() {
|
||||
checkInit();
|
||||
return delegate.lastKey();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
|
||||
public boolean equals(Object o) {
|
||||
checkInit();
|
||||
return delegate.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
checkInit();
|
||||
return delegate.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.lazy.proxy;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SortedSetProxy<U> extends CollectionProxy<U, SortedSet<U>> implements SortedSet<U> {
|
||||
public SortedSetProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<SortedSet<U>> initializor) {
|
||||
super(initializor);
|
||||
}
|
||||
|
||||
public Comparator<? super U> comparator() {
|
||||
checkInit();
|
||||
return delegate.comparator();
|
||||
}
|
||||
|
||||
public SortedSet<U> subSet(U u, U u1) {
|
||||
checkInit();
|
||||
return delegate.subSet(u, u1);
|
||||
}
|
||||
|
||||
public SortedSet<U> headSet(U u) {
|
||||
checkInit();
|
||||
return delegate.headSet(u);
|
||||
}
|
||||
|
||||
public SortedSet<U> tailSet(U u) {
|
||||
checkInit();
|
||||
return delegate.tailSet(u);
|
||||
}
|
||||
|
||||
public U first() {
|
||||
checkInit();
|
||||
return delegate.first();
|
||||
}
|
||||
|
||||
public U last() {
|
||||
checkInit();
|
||||
return delegate.last();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.query;
|
||||
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.entities.mapper.id.QueryParameterData;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.RevisionType;
|
||||
import org.jboss.envers.tools.query.QueryBuilder;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
import org.hibernate.Query;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Selects data from a relation middle-table only.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class OneEntityQueryGenerator implements RelationQueryGenerator {
|
||||
private final String queryString;
|
||||
private final MiddleIdData referencingIdData;
|
||||
|
||||
public OneEntityQueryGenerator(VersionsEntitiesConfiguration verEntCfg,
|
||||
String versionsMiddleEntityName,
|
||||
MiddleIdData referencingIdData,
|
||||
MiddleComponentData... componentDatas) {
|
||||
this.referencingIdData = referencingIdData;
|
||||
|
||||
/*
|
||||
* The query that we need to create:
|
||||
* SELECT new list(ee) FROM middleEntity ee WHERE
|
||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||
* ee.originalId.id_ref_ing = :id_ref_ing AND
|
||||
* (the association at revision :revision)
|
||||
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
||||
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
|
||||
* (only non-deleted entities and associations)
|
||||
* ee.revision_type != DEL
|
||||
*/
|
||||
String revisionPropertyPath = verEntCfg.getRevisionPropPath();
|
||||
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
||||
|
||||
// SELECT new list(ee) FROM middleEntity ee
|
||||
QueryBuilder qb = new QueryBuilder(versionsMiddleEntityName, "ee");
|
||||
qb.addProjection("new list", "ee", false, false);
|
||||
// WHERE
|
||||
Parameters rootParameters = qb.getRootParameters();
|
||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
||||
// SELECT max(ee2.revision) FROM middleEntity ee2
|
||||
QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
|
||||
maxRevQb.addProjection("max", revisionPropertyPath, false);
|
||||
// WHERE
|
||||
Parameters maxRevQbParameters = maxRevQb.getRootParameters();
|
||||
// ee2.revision <= :revision
|
||||
maxRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
||||
// ee2.originalId.* = ee.originalId.*
|
||||
String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
|
||||
String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
|
||||
referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
||||
for (MiddleComponentData componentData : componentDatas) {
|
||||
componentData.getComponentMapper().addMiddleEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
||||
}
|
||||
// ee.revision = (SELECT max(...) ...)
|
||||
rootParameters.addWhere(revisionPropertyPath, "=", maxRevQb);
|
||||
// ee.revision_type != DEL
|
||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
qb.build(sb, Collections.<String, Object>emptyMap());
|
||||
queryString = sb.toString();
|
||||
}
|
||||
|
||||
public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
|
||||
Query query = versionsReader.getSession().createQuery(queryString);
|
||||
query.setParameter("revision", revision);
|
||||
query.setParameter("delrevisiontype", RevisionType.DEL);
|
||||
for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
|
||||
paramData.setParameterValue(query);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.query;
|
||||
|
||||
import org.jboss.envers.entities.mapper.id.QueryParameterData;
|
||||
import org.jboss.envers.entities.mapper.id.IdMapper;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.configuration.GlobalConfiguration;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.RevisionType;
|
||||
import org.jboss.envers.tools.query.QueryBuilder;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
import org.hibernate.Query;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Selects data from a versions entity.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class OneVersionsEntityQueryGenerator implements RelationQueryGenerator {
|
||||
private final String queryString;
|
||||
private final MiddleIdData referencingIdData;
|
||||
|
||||
public OneVersionsEntityQueryGenerator(GlobalConfiguration globalCfg, VersionsEntitiesConfiguration verEntCfg,
|
||||
MiddleIdData referencingIdData, String referencedEntityName,
|
||||
IdMapper referencedIdMapper) {
|
||||
this.referencingIdData = referencingIdData;
|
||||
|
||||
/*
|
||||
* The query that we need to create:
|
||||
* SELECT new list(e) FROM versionsReferencedEntity e
|
||||
* WHERE
|
||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||
* e.id_ref_ing = :id_ref_ing AND
|
||||
* (selecting e entities at revision :revision)
|
||||
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
||||
* WHERE e2.revision <= :revision AND e2.id = e.id) AND
|
||||
* (only non-deleted entities)
|
||||
* e.revision_type != DEL
|
||||
*/
|
||||
String revisionPropertyPath = verEntCfg.getRevisionPropPath();
|
||||
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
||||
|
||||
String versionsReferencedEntityName = verEntCfg.getVersionsEntityName(referencedEntityName);
|
||||
|
||||
// SELECT new list(e) FROM versionsEntity e
|
||||
QueryBuilder qb = new QueryBuilder(versionsReferencedEntityName, "e");
|
||||
qb.addProjection("new list", "e", false, false);
|
||||
// WHERE
|
||||
Parameters rootParameters = qb.getRootParameters();
|
||||
// e.id_ref_ed = :id_ref_ed
|
||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, null, true);
|
||||
|
||||
// SELECT max(e.revision) FROM versionsReferencedEntity e2
|
||||
QueryBuilder maxERevQb = qb.newSubQueryBuilder(versionsReferencedEntityName, "e2");
|
||||
maxERevQb.addProjection("max", revisionPropertyPath, false);
|
||||
// WHERE
|
||||
Parameters maxERevQbParameters = maxERevQb.getRootParameters();
|
||||
// e2.revision <= :revision
|
||||
maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
||||
// e2.id = e.id
|
||||
referencedIdMapper.addIdsEqualToQuery(maxERevQbParameters,
|
||||
"e." + originalIdPropertyName, "e2." + originalIdPropertyName);
|
||||
|
||||
// e.revision = (SELECT max(...) ...)
|
||||
rootParameters.addWhere(revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
|
||||
|
||||
// e.revision_type != DEL
|
||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
qb.build(sb, Collections.<String, Object>emptyMap());
|
||||
queryString = sb.toString();
|
||||
}
|
||||
|
||||
public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
|
||||
Query query = versionsReader.getSession().createQuery(queryString);
|
||||
query.setParameter("revision", revision);
|
||||
query.setParameter("delrevisiontype", RevisionType.DEL);
|
||||
for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
|
||||
paramData.setParameterValue(query);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.query;
|
||||
|
||||
import org.jboss.envers.tools.query.QueryBuilder;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.configuration.GlobalConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class QueryGeneratorTools {
|
||||
public static void addEntityAtRevision(GlobalConfiguration globalCfg, QueryBuilder qb, Parameters rootParameters,
|
||||
MiddleIdData idData, String revisionPropertyPath, String originalIdPropertyName,
|
||||
String alias1, String alias2) {
|
||||
// SELECT max(e.revision) FROM versionsReferencedEntity e2
|
||||
QueryBuilder maxERevQb = qb.newSubQueryBuilder(idData.getVersionsEntityName(), alias2);
|
||||
maxERevQb.addProjection("max", revisionPropertyPath, false);
|
||||
// WHERE
|
||||
Parameters maxERevQbParameters = maxERevQb.getRootParameters();
|
||||
// e2.revision <= :revision
|
||||
maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
||||
// e2.id_ref_ed = e.id_ref_ed
|
||||
idData.getOriginalMapper().addIdsEqualToQuery(maxERevQbParameters,
|
||||
alias1 + "." + originalIdPropertyName, alias2 +"." + originalIdPropertyName);
|
||||
|
||||
// e.revision = (SELECT max(...) ...)
|
||||
rootParameters.addWhere("e." + revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
|
||||
}
|
||||
|
||||
public static void addAssociationAtRevision(QueryBuilder qb, Parameters rootParameters,
|
||||
MiddleIdData referencingIdData, String versionsMiddleEntityName,
|
||||
String eeOriginalIdPropertyPath, String revisionPropertyPath,
|
||||
String originalIdPropertyName, MiddleComponentData... componentDatas) {
|
||||
// SELECT max(ee2.revision) FROM middleEntity ee2
|
||||
QueryBuilder maxEeRevQb = qb.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
|
||||
maxEeRevQb.addProjection("max", revisionPropertyPath, false);
|
||||
// WHERE
|
||||
Parameters maxEeRevQbParameters = maxEeRevQb.getRootParameters();
|
||||
// ee2.revision <= :revision
|
||||
maxEeRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
|
||||
// ee2.originalId.* = ee.originalId.*
|
||||
String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
|
||||
referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
||||
for (MiddleComponentData componentData : componentDatas) {
|
||||
componentData.getComponentMapper().addMiddleEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
|
||||
}
|
||||
|
||||
// ee.revision = (SELECT max(...) ...)
|
||||
rootParameters.addWhere(revisionPropertyPath, "=", maxEeRevQb);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.query;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
|
||||
/**
|
||||
* Implementations of this interface provide a method to generate queries on a relation table (a table used
|
||||
* for mapping relations). The query can select, apart from selecting the content of the relation table, also data of
|
||||
* other "related" entities.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface RelationQueryGenerator {
|
||||
Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision);
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
|
||||
* by the @authors tag. All rights reserved.
|
||||
*
|
||||
* See the copyright.txt in the distribution for a full listing of individual
|
||||
* contributors. This copyrighted material is made available to anyone wishing
|
||||
* to use, modify, copy, or redistribute it subject to the terms and
|
||||
* conditions of the GNU Lesser General Public License, v. 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT A WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License, v.2.1 along with this distribution; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* Red Hat Author(s): Adam Warski
|
||||
*/
|
||||
package org.jboss.envers.entities.mapper.relation.query;
|
||||
|
||||
import org.jboss.envers.entities.mapper.id.QueryParameterData;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleIdData;
|
||||
import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
|
||||
import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
|
||||
import org.jboss.envers.configuration.GlobalConfiguration;
|
||||
import org.jboss.envers.reader.VersionsReaderImplementor;
|
||||
import org.jboss.envers.RevisionType;
|
||||
import org.jboss.envers.tools.query.QueryBuilder;
|
||||
import org.jboss.envers.tools.query.Parameters;
|
||||
import org.hibernate.Query;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Selects data from a relation middle-table and a two related versions entity.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class ThreeEntityQueryGenerator implements RelationQueryGenerator {
|
||||
private final String queryString;
|
||||
private final MiddleIdData referencingIdData;
|
||||
|
||||
public ThreeEntityQueryGenerator(GlobalConfiguration globalCfg,
|
||||
VersionsEntitiesConfiguration verEntCfg,
|
||||
String versionsMiddleEntityName,
|
||||
MiddleIdData referencingIdData,
|
||||
MiddleIdData referencedIdData,
|
||||
MiddleIdData indexIdData,
|
||||
MiddleComponentData... componentDatas) {
|
||||
this.referencingIdData = referencingIdData;
|
||||
|
||||
/*
|
||||
* The query that we need to create:
|
||||
* SELECT new list(ee, e, f) FROM versionsReferencedEntity e, versionsIndexEntity f, middleEntity ee
|
||||
* WHERE
|
||||
* (entities referenced by the middle table; id_ref_ed = id of the referenced entity)
|
||||
* ee.id_ref_ed = e.id_ref_ed AND
|
||||
* (entities referenced by the middle table; id_ref_ind = id of the index entity)
|
||||
* ee.id_ref_ind = f.id_ref_ind AND
|
||||
* (only entities referenced by the association; id_ref_ing = id of the referencing entity)
|
||||
* ee.id_ref_ing = :id_ref_ing AND
|
||||
* (selecting e entities at revision :revision)
|
||||
* e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
|
||||
* WHERE e2.revision <= :revision AND e2.id_ref_ed = e.id_ref_ed) AND
|
||||
* (selecting f entities at revision :revision)
|
||||
* f.revision = (SELECT max(f2.revision) FROM versionsIndexEntity f2
|
||||
* WHERE f2.revision <= :revision AND f2.id_ref_ed = f.id_ref_ed) AND
|
||||
* (the association at revision :revision)
|
||||
* ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
|
||||
* WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
|
||||
* (only non-deleted entities and associations)
|
||||
* ee.revision_type != DEL AND
|
||||
* e.revision_type != DEL AND
|
||||
* f.revision_type != DEL
|
||||
*/
|
||||
String revisionPropertyPath = verEntCfg.getRevisionPropPath();
|
||||
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
||||
|
||||
String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
|
||||
|
||||
// SELECT new list(ee) FROM middleEntity ee
|
||||
QueryBuilder qb = new QueryBuilder(versionsMiddleEntityName, "ee");
|
||||
qb.addFrom(referencedIdData.getVersionsEntityName(), "e");
|
||||
qb.addFrom(indexIdData.getVersionsEntityName(), "f");
|
||||
qb.addProjection("new list", "ee, e, f", false, false);
|
||||
// WHERE
|
||||
Parameters rootParameters = qb.getRootParameters();
|
||||
// ee.id_ref_ed = e.id_ref_ed
|
||||
referencedIdData.getPrefixedMapper().addIdsEqualToQuery(rootParameters, eeOriginalIdPropertyPath,
|
||||
referencedIdData.getOriginalMapper(), "e." + originalIdPropertyName);
|
||||
// ee.id_ref_ind = f.id_ref_ind
|
||||
indexIdData.getPrefixedMapper().addIdsEqualToQuery(rootParameters, eeOriginalIdPropertyPath,
|
||||
indexIdData.getOriginalMapper(), "f." + originalIdPropertyName);
|
||||
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
|
||||
|
||||
// e.revision = (SELECT max(...) ...)
|
||||
QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
|
||||
originalIdPropertyName, "e", "e2");
|
||||
|
||||
// f.revision = (SELECT max(...) ...)
|
||||
QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, indexIdData, revisionPropertyPath,
|
||||
originalIdPropertyName, "f", "f2");
|
||||
|
||||
// ee.revision = (SELECT max(...) ...)
|
||||
QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
|
||||
eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
|
||||
|
||||
// ee.revision_type != DEL
|
||||
rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
|
||||
// e.revision_type != DEL
|
||||
rootParameters.addWhereWithNamedParam("e." + verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
|
||||
// f.revision_type != DEL
|
||||
rootParameters.addWhereWithNamedParam("f." + verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
qb.build(sb, Collections.<String, Object>emptyMap());
|
||||
queryString = sb.toString();
|
||||
}
|
||||
|
||||
public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
|
||||
Query query = versionsReader.getSession().createQuery(queryString);
|
||||
query.setParameter("revision", revision);
|
||||
query.setParameter("delrevisiontype", RevisionType.DEL);
|
||||
for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
|
||||
paramData.setParameterValue(query);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue