MentaBean

Compare Revisions

Ignore whitespace Rev 41 → Rev 52

/tags/menta-bean-0.9.4/src/test/java/org/mentabean/jdbc/JdbcBeanSessionTest.java
New file
0,0 → 1,990
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.BeforeClass;
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.type.EnumIdType;
import org.mentabean.type.EnumValueType;
 
public class JdbcBeanSessionTest extends AbstractBeanSessionTest {
 
private static final SimpleDateFormat BD_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
 
@BeforeClass
public static void setup() {
DefaultBeanSession.DEBUG = false; // turn on to see SQL generated
}
 
private static class User {
 
public static enum Status {
BASIC, PREMIUM, GOLD
}
 
private int id;
private String username;
private Date birthdate;
private Status status = Status.BASIC;
private boolean deleted;
private Date insertTime;
 
public User() {
}
 
public User(int id) {
this.id = id;
}
 
public User(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
 
private void createTables(Connection conn) throws SQLException {
 
execUpdate(conn, "create table Users(id integer primary key auto_increment, username varchar(25), bd datetime, status varchar(20), deleted tinyint, insert_time timestamp)");
execUpdate(conn, "create table Posts(id integer primary key auto_increment, user_id integer, title varchar(200), body text, insert_time timestamp)");
}
 
private BeanConfig getUserBeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING);
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", new EnumValueType(User.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.TIMESTAMP).defaultToNow("insertTime");
 
return config;
}
 
@Test
public void testCRUD() throws SQLException { // CRUD = ISUD = Insert, Select, Update, Delete
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
// INSERT:
 
User u = new User("saoj", "1980-03-01");
u.setStatus(User.Status.GOLD);
 
session.insert(u);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
 
// SELECT:
 
u = new User(1);
 
boolean loaded = session.load(u);
 
Assert.assertEquals(true, loaded);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
Assert.assertTrue((new Date()).getTime() >= u.getInsertTime().getTime());
 
// UPDATE:
 
u.setUsername("soliveira");
 
int modified = session.update(u);
 
Assert.assertEquals(1, modified);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("soliveira", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
Assert.assertTrue((new Date()).getTime() >= u.getInsertTime().getTime());
 
// make sure the new username was saved in the database
 
u = new User(1);
 
loaded = session.load(u);
 
Assert.assertEquals(true, loaded);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("soliveira", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
Assert.assertTrue((new Date()).getTime() >= u.getInsertTime().getTime());
 
// DELETE:
 
boolean deleted = session.delete(u);
 
Assert.assertEquals(true, deleted);
 
// make sure the bean is deleted from the database...
 
u = new User(1);
 
loaded = session.load(u);
 
Assert.assertEquals(false, loaded);
 
} finally {
 
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testDynUpdate() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
// First insert, so we can test the update after...
User u = new User("saoj", "1980-03-01");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
 
// UNATTACHED UPDATE:
 
u = new User(1); // note that bean was NOT loaded, in other words,
// it was NOT attached to session
u.setUsername("soliveira");
 
int modified = session.update(u); // only properties that are
// considered SET will be
// updated
Assert.assertEquals(1, modified);
 
// make sure it was written to the database
u = new User(1);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
 
Assert.assertEquals("soliveira", u.getUsername());
 
// ATTACHED UPDATE:
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
 
u.setUsername(u.getUsername()); // setting, but nothing is
// changing...
 
modified = session.update(u); // nothing should happen here...
Assert.assertEquals(0, modified);
 
// UNATTACHED UPDATED ALL:
 
u = new User(1); // note that bean was NOT loaded, in other words,
// it was NOT attached to session
u.setUsername("julia");
 
modified = session.updateAll(u);
 
Assert.assertEquals(1, modified);
 
// everything was written to the database, even the fields that were
// NOT set
// as a result, some fields were nullified
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals("julia", u.getUsername());
Assert.assertNull(u.getBirthdate());
Assert.assertNull(u.getInsertTime());
 
// ATTACHED UPDATE ALL:
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
 
u.setBirthdate("1980-02-02");
 
modified = session.updateAll(u);
 
Assert.assertEquals(1, modified);
 
// everything was written to the database, even the fields that were
// NOT set
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals("julia", u.getUsername());
Assert.assertEquals("1980-02-02", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertNull(u.getInsertTime());
 
} finally {
 
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testMultipleInserts() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
for (int i = 0; i < 10; i++) {
User u = new User();
u.setUsername("saoj" + (i + 1));
u.setBirthdate("1990-01-1" + i);
 
session.insert(u);
 
Assert.assertEquals(i + 1, u.getId());
}
} finally {
close(conn);
}
}
 
@Test
public void testLoadList() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
for (int i = 0; i < 10; i++) {
User u = new User();
u.setUsername("saoj" + (i + 1));
u.setBirthdate("1990-01-1" + i);
u.setStatus(User.Status.BASIC);
 
session.insert(u);
 
Assert.assertEquals(i + 1, u.getId());
}
 
// now set one user to GOLD
 
User u = new User(5);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
u.setStatus(User.Status.GOLD);
int modified = session.update(u);
Assert.assertEquals(1, modified);
 
// first count to see if we are excluding the golad...
 
u = new User();
u.setStatus(User.Status.BASIC);
 
int total = session.countList(u);
 
Assert.assertEquals(9, total);
 
// now load a list of all BASIC users
 
u = new User();
u.setStatus(User.Status.BASIC);
 
List<User> users = session.loadList(u);
 
Assert.assertEquals(9, users.size());
 
// check that the GOLD user was not loaded...
 
for (User user : users) {
Assert.assertTrue(user.getId() != 5);
}
 
} finally {
close(conn);
}
}
 
private static class Post {
 
private int id;
private int userId;
private User user;
private String title;
private String body;
private Date insertTime;
 
public Post() {
}
 
public Post(int id) {
this.id = id;
}
 
public Post(int userId, String title, String text) {
this.userId = userId;
this.title = title;
this.body = text;
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public int getUserId() {
return userId;
}
 
public void setUserId(int userId) {
this.userId = userId;
}
 
public User getUser() {
return user;
}
 
public void setUser(User user) {
this.user = user;
}
 
public String getTitle() {
return title;
}
 
public void setTitle(String title) {
this.title = title;
}
 
public String getBody() {
return body;
}
 
public void setBody(String body) {
this.body = body;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
}
 
private void getPostBeanConfig(BeanManager beanManager) {
// Fluent API
beanManager.bean(Post.class, "Posts")
.pk("id", DBTypes.AUTOINCREMENT)
.field("userId", "user_id", DBTypes.INTEGER)
.field("title", DBTypes.STRING)
.field("body", DBTypes.STRING)
.field("insertTime", "insert_time", DBTypes.TIMESTAMP).defaultToNow("insertTime");
}
 
@Test
public void testOneToOneRelationshipCRUD() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
getPostBeanConfig(beanManager);
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u = new User("saoj", "1980-01-02");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
 
// Now insert a post for this user...
Post p = new Post(1, "Test", "This is a test!");
session.insert(p);
 
Assert.assertEquals(1, p.getId());
 
// Load from the database...
p = new Post(1);
boolean loaded = session.load(p);
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, p.getUserId());
Assert.assertNull(p.getUser()); // you did NOT load any user from the database here... (we like manual lazy loading, not automatic lazy loading!)
 
// Load user for this post... (let's do our manual lazy loading)
u = new User(p.getUserId());
loaded = session.load(u);
Assert.assertEquals(true, loaded);
p.setUser(u); // manual lazy loading (forget about automatic lazy loading, you want control!)
 
// Use JOIN to load all dependencies with a single query... (you know how to make a join, right?)
 
p = new Post(1);
 
StringBuilder query = new StringBuilder(256);
query.append("select ");
query.append(session.buildSelect(Post.class, "p"));
query.append(", ");
query.append(session.buildSelect(User.class, "u"));
query.append(" from Posts p join Users u on p.user_id = u.id");
query.append(" where p.id = ?");
 
stmt = conn.prepareStatement(query.toString());
stmt.setInt(1, p.getId());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
session.populateBean(rset, p, "p");
 
u = new User();
 
session.populateBean(rset, u, "u");
 
p.setUser(u); // manual lazy loading (we prefer to have control!)
}
 
Assert.assertEquals(1, p.getId());
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", p.getUser().getUsername());
Assert.assertTrue((new Date()).getTime() >= p.getInsertTime().getTime());
 
rset.close();
stmt.close();
 
// Deleting => No cascade deletes, if you want that implement in the database level...
 
u = new User(1);
boolean deleted = session.delete(u);
Assert.assertEquals(true, deleted);
 
// Post of course is still there...
p = new Post(1);
loaded = session.load(p);
Assert.assertEquals(true, loaded);
Assert.assertEquals(1, p.getUserId()); // of course this user is gone!
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(false, loaded); // use was deleted above...
 
} finally {
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testLoadUnique() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u1 = new User("saoj", "1983-01-02");
session.insert(u1);
 
User u = new User();
u.setUsername("saoj");
 
u = session.loadUnique(u);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
 
// now add another one and try again...
 
User u2 = new User("saoj", "1967-01-03");
session.insert(u2);
 
u = new User();
u.setUsername("saoj");
 
boolean ok = false;
 
try {
 
u = session.loadUnique(u);
 
ok = true; // cannot come here...
 
} catch (BeanException e) {
 
ok = false;
}
 
Assert.assertEquals(false, ok);
 
} finally {
close(conn);
}
}
@Test
public void testSettingProperties() throws SQLException {
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
createTables(conn);
User saoj = new User("saoj", "1980-01-01");
session.insert(saoj);
User julia = new User("julia", "1980-03-03");
session.insert(julia);
// delete "saoj" by making deleted equals to false
saoj.setDeleted(true);
int modified = session.update(saoj);
Assert.assertEquals(1, modified);
// load all non-deleted users...
User u = new User();
u.setDeleted(false);
List<User> nonDeletedUsers = session.loadList(u);
Assert.assertFalse(nonDeletedUsers.size() == 1); // THIS DOES NOT WORK because isDeleted() returns a boolean primitive
Assert.assertEquals(2, nonDeletedUsers.size()); // it will return everything because the deleted = false condition was never detected
// to fix, let's change the property to return a Boolean
beanManager.addBeanConfig(getUser2BeanConfig());
// now try again
User2 u2 = new User2();
u2.setDeleted(false);
List<User2> nonDeletedUsers2 = session.loadList(u2);
Assert.assertEquals(1, nonDeletedUsers2.size()); // now only ONE is returned, the non-deleted one...
} finally {
close(conn);
}
}
private static class User2 {
 
public static enum Status {
BASIC, PREMIUM, GOLD
}
 
private int id;
private String username;
private Date birthdate;
private Status status = Status.BASIC;
private boolean deleted;
private Date insertTime;
 
public User2() {
}
 
public User2(int id) {
this.id = id;
}
 
public User2(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public Boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
private BeanConfig getUser2BeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User2.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING);
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", new EnumValueType(User2.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.TIMESTAMP).defaultToNow("insertTime");
 
return config;
}
@Test
public void testEnumIdType() throws SQLException {
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUser3BeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
execUpdate(conn, "create table Users(id integer primary key auto_increment, username varchar(25), bd datetime, status integer, deleted tinyint, insert_time timestamp)");
User3 u = new User3("saoj", "1980-03-03");
u.setStatus(User3.Status.GOLD);
session.insert(u);
// now load and see if we get the same status...
u = new User3(1);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals(User3.Status.GOLD, u.getStatus());
} finally {
close(conn);
}
}
private static class User3 {
 
public static enum Status {
BASIC(1), PREMIUM(2), GOLD(3);
private final int id;
private Status(int id) {
this.id = id;
}
public int getId() { return id; }
public static Status fromId(int id) {
for(Status s : Status.values()) {
if (s.getId() == id) return s;
}
return null;
}
}
 
private int id;
private String username;
private Date birthdate;
private Status status = Status.BASIC;
private boolean deleted;
private Date insertTime;
 
public User3() {
}
 
public User3(int id) {
this.id = id;
}
 
public User3(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public Boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
private BeanConfig getUser3BeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User3.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING);
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", new EnumIdType(User3.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.TIMESTAMP).defaultToNow("insertTime");
 
return config;
}
}
/tags/menta-bean-0.9.4/src/test/java/org/mentabean/jdbc/AbstractBeanSessionTest.java
New file
0,0 → 1,111
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public abstract class AbstractBeanSessionTest {
 
protected static Connection getConnection() {
try {
Class.forName("org.h2.Driver");
return DriverManager.getConnection("jdbc:h2:mem:MentaBean", "sa", "");
} catch (Exception e) {
throw new IllegalStateException("Cannot connect to H2 database!", e);
}
}
 
protected static void execUpdate(Connection conn, String query) throws SQLException {
 
Statement stmt = null;
 
try {
 
stmt = conn.createStatement();
 
stmt.executeUpdate(query);
 
} finally {
 
close(stmt);
}
}
 
static void close(PreparedStatement stmt) {
close(stmt, null);
}
 
static void close(PreparedStatement stmt, ResultSet rset) {
 
if (rset != null) {
try {
rset.close();
} catch (Exception e) {
e.printStackTrace();
}
}
 
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
static void close(Statement stmt) {
close(stmt, null);
}
 
static void close(Statement stmt, ResultSet rset) {
 
if (rset != null) {
try {
rset.close();
} catch (Exception e) {
e.printStackTrace();
}
}
 
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
static void close(Connection conn) {
 
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/BeanManager.java
New file
0,0 → 1,85
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import java.util.HashMap;
import java.util.Map;
 
/**
* The manager that keeps track of the configuration for all beans.
*
* @author sergio.oliveira.jr@gmail.com
*/
public class BeanManager {
 
private final Map<Class<? extends Object>, BeanConfig> beans = new HashMap<Class<? extends Object>, BeanConfig>();
 
/**
* Add a bean configuration.
*
* @param bc
* The bean configuration to add.
* @return The BeanConfig added (Fluent API)
*/
public BeanConfig bean(final BeanConfig bc) {
 
if (beans.containsKey(bc.getBeanClass())) {
throw new IllegalStateException("A configuration was already added for this bean!");
}
 
beans.put(bc.getBeanClass(), bc);
 
return bc;
}
 
/**
* Add a bean configuration.
*
* @param bc
* The bean configuration to add.
*/
public void addBeanConfig(final BeanConfig bc) {
bean(bc);
}
 
/**
* Creates a bean configuration and add to this manager.
*
* @param beanClass
* The bean class
* @param tableName
* The table name where the bean properties will be stored.
* @return The BeanConfig created (Fluent API)
*/
public BeanConfig bean(final Class<? extends Object> beanClass, final String tableName) {
 
return bean(new BeanConfig(beanClass, tableName));
}
 
/**
* Get the bean configuration for the given bean class.
*
* @param beanClass
* The bean class
* @return The bean configuration for this bean or null if it was not defined
*/
public BeanConfig getBeanConfig(final Class<? extends Object> beanClass) {
 
return beans.get(beanClass);
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/IntegerType.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class IntegerType implements DBType<Integer> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getInt(index);
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getInt(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Integer.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Integer value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.INTEGER);
 
} else {
 
stmt.setInt(index, value.intValue());
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/TimeType.java
New file
0,0 → 1,71
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class TimeType implements DBType<java.util.Date> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getTime(index);
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getTime(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return java.util.Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final java.util.Date value) throws SQLException {
 
if (value == null) {
 
stmt.setTime(index, null);
 
} else if (value instanceof java.sql.Time) {
 
final java.sql.Time t = (java.sql.Time) value;
 
stmt.setTime(index, t);
 
} else {
 
stmt.setTime(index, new java.sql.Time(value.getTime()));
 
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/LongType.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class LongType implements DBType<Long> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getLong(index);
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getLong(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Long.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Long value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.BIGINT);
 
} else {
 
stmt.setLong(index, value.longValue());
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/EnumValueType.java
New file
0,0 → 1,92
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class EnumValueType implements DBType<Enum<?>> {
 
private final Class<? extends Enum<?>> enumType;
 
public EnumValueType(final Class<? extends Enum<?>> enumType) {
 
this.enumType = enumType;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName() + ": " + enumType.getSimpleName();
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final String s = rset.getString(index);
 
if (s == null) {
return null;
}
 
return Enum.valueOf((Class) enumType, s);
 
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final String s = rset.getString(field);
 
if (s == null) {
return null;
}
 
return Enum.valueOf((Class) enumType, s);
 
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return enumType;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Enum<?> value) throws SQLException {
 
if (value == null) {
 
stmt.setString(index, null);
 
} else if (value.getClass().isAssignableFrom(enumType)) {
 
final String s = value.toString();
 
stmt.setString(index, s);
 
} else {
 
throw new IllegalArgumentException("Value is not an enum!");
}
 
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/TimestampType.java
New file
0,0 → 1,71
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class TimestampType implements DBType<java.util.Date> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getTimestamp(index);
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getTimestamp(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return java.util.Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final java.util.Date value) throws SQLException {
 
if (value == null) {
 
stmt.setTimestamp(index, null);
 
} else if (value instanceof java.sql.Timestamp) {
 
final java.sql.Timestamp t = (java.sql.Timestamp) value;
 
stmt.setTimestamp(index, t);
 
} else {
 
stmt.setTimestamp(index, new java.sql.Timestamp(value.getTime()));
 
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/FloatType.java
New file
0,0 → 1,65
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class FloatType implements DBType<Float> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Float getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getFloat(index);
}
 
@Override
public Float getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getFloat(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Float.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Float value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.FLOAT);
 
} else {
 
stmt.setFloat(index, value.floatValue());
 
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/BooleanStringType.java
New file
0,0 → 1,150
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class BooleanStringType implements DBType<Boolean> {
 
private final String sTrue;
 
private final String sFalse;
 
public BooleanStringType() {
 
this("T", "F");
}
 
public BooleanStringType(final String sTrue, final String sFalse) {
 
this.sTrue = sTrue;
 
this.sFalse = sFalse;
 
}
 
@Override
public boolean equals(final Object obj) {
 
if (obj instanceof BooleanStringType) {
 
final BooleanStringType bt = (BooleanStringType) obj;
 
if (bt.sTrue.equals(this.sTrue) && bt.sFalse.equals(this.sFalse)) {
 
return true;
}
}
 
return false;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
protected boolean getBooleanValue(final String s) throws SQLException {
 
if (s == null) {
return false;
}
 
if (s.equals("T")) {
return true;
}
 
if (s.equals("F")) {
return false;
}
 
if (s.equals("0")) {
return false;
}
 
if (s.equals("1")) {
return true;
}
 
if (s.equals("true")) {
return true;
}
 
if (s.equals("false")) {
return false;
}
 
throw new SQLException("value is not a boolean: " + s);
 
}
 
private static Boolean getBoolValue(final boolean b) {
 
if (b) {
return Boolean.TRUE;
}
 
return Boolean.FALSE;
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final String s = rset.getString(index);
 
final boolean b = getBooleanValue(s);
 
return getBoolValue(b);
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final String s = rset.getString(field);
 
final boolean b = getBooleanValue(s);
 
return getBoolValue(b);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Boolean.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Boolean value) throws SQLException {
 
if (value == null) {
 
stmt.setString(index, null);
 
} else {
 
final String s = value ? sTrue : sFalse;
 
stmt.setString(index, s);
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/StringType.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class StringType implements DBType<String> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public String getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getString(index);
}
 
@Override
public String getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getString(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return String.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final String value) throws SQLException {
 
if (value == null) {
 
stmt.setString(index, null);
 
} else {
 
stmt.setString(index, value);
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/SequenceType.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class SequenceType implements DBType<Integer> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getInt(index);
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getInt(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Integer.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Integer value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.INTEGER);
 
} else {
 
stmt.setInt(index, value.intValue());
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/DoubleType.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class DoubleType implements DBType<Double> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Double getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getDouble(index);
}
 
@Override
public Double getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getDouble(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Double.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Double value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.DOUBLE);
 
} else {
 
stmt.setDouble(index, value.doubleValue());
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/AutoIncrementType.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class AutoIncrementType implements DBType<Integer> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getInt(index);
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getInt(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Integer.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Integer value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.INTEGER);
 
} else {
 
stmt.setInt(index, value.intValue());
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/DateType.java
New file
0,0 → 1,71
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class DateType implements DBType<java.util.Date> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getDate(index);
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getDate(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return java.util.Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final java.util.Date value) throws SQLException {
 
if (value == null) {
 
stmt.setDate(index, null);
 
} else if (value instanceof java.sql.Date) {
 
final java.sql.Date d = (java.sql.Date) value;
 
stmt.setDate(index, d);
 
} else {
 
stmt.setDate(index, new java.sql.Date(value.getTime()));
 
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/BigDecimalType.java
New file
0,0 → 1,65
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class BigDecimalType implements DBType<BigDecimal> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public BigDecimal getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getBigDecimal(index);
}
 
@Override
public BigDecimal getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getBigDecimal(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return BigDecimal.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final BigDecimal value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.DECIMAL);
 
} else {
 
stmt.setBigDecimal(index, value);
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/EnumIdType.java
New file
0,0 → 1,164
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
 
import org.mentabean.BeanException;
import org.mentabean.DBType;
 
public class EnumIdType implements DBType<Enum<?>> {
 
private final Class<? extends Enum<?>> enumType;
private final Method fromIdMethod;
private final Method getIdMethod;
 
public EnumIdType(final Class<? extends Enum<?>> enumType) {
 
this.enumType = enumType;
this.fromIdMethod = getFromIdMethod(enumType);
this.getIdMethod = getGetIdMethod(enumType);
}
private static Method getFromIdMethod(Class<? extends Enum<?>> enumType) {
try {
return enumType.getMethod("fromId", int.class);
} catch(Exception e) {
throw new BeanException("Cannot find fromId(int) method from enum class: " + enumType, e);
}
}
private static Method getGetIdMethod(Class<? extends Enum<?>> enumType) {
try {
return enumType.getMethod("getId", (Class[]) null);
} catch(Exception e) {
throw new BeanException("Cannot find getId() method from enum class: " + enumType, e);
}
}
private Enum<?> fromId(int id) {
try {
return (Enum<?>) fromIdMethod.invoke(null, id);
} catch(Exception e) {
throw new BeanException(e);
}
}
private int getId(Enum<?> theEnum) {
try {
return (Integer) getIdMethod.invoke(theEnum, (Object[]) null);
} catch(Exception e) {
throw new BeanException(e);
}
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName() + ": " + enumType.getSimpleName();
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final int id = rset.getInt(index);
 
if (rset.wasNull()) {
return null;
}
 
return fromId(id);
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final int id = rset.getInt(field);
 
if (rset.wasNull()) {
return null;
}
 
return fromId(id);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return enumType;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Enum<?> value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, Types.INTEGER);
 
} else if (value.getClass().isAssignableFrom(enumType)) {
 
final int id = getId(value);
 
stmt.setInt(index, id);
 
} else {
 
throw new IllegalArgumentException("Value is not an enum!");
}
}
public static enum Test {
T1(1), T2(2), T3(3);
private final int id;
private Test(int id) {
this.id = id;
}
public int getId() { return id; }
public static Test fromId(int id) {
for(Test t : Test.values()) {
if (t.getId() == id) return t;
}
return null;
}
}
public static void main(String[] args) throws Exception {
 
EnumIdType eit = new EnumIdType(Test.class);
System.out.println(eit.fromId(2));
System.out.println(eit.getId(Test.T3));
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/BooleanIntType.java
New file
0,0 → 1,84
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class BooleanIntType implements DBType<Boolean> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
private static Boolean getBoolValue(final int x) throws SQLException {
 
if (x == 1) {
return Boolean.TRUE;
}
 
if (x == 0) {
return Boolean.FALSE;
}
 
throw new SQLException("integer is not 0 or 1: " + x);
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final int x = rset.getInt(index);
 
return getBoolValue(x);
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final int x = rset.getInt(field);
 
return getBoolValue(x);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Boolean.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Boolean value) throws SQLException {
 
if (value == null) {
 
stmt.setInt(index, 0);
 
} else if (value instanceof Boolean) {
 
final int x = value ? 1 : 0;
 
stmt.setInt(index, x);
}
 
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/type/AutoTimestampType.java
New file
0,0 → 1,58
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
 
import org.mentabean.DBType;
 
public class AutoTimestampType implements DBType<Date> {
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getTimestamp(index);
}
 
@Override
public Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getTimestamp(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Date value) throws SQLException {
 
throw new UnsupportedOperationException("Type AutoTimestampType is automatic and cannot be updated!");
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/jdbc/MySQLBeanSession.java
New file
0,0 → 1,114
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
 
/**
* MySQL only supports auto-increment.
*
* Now in mysql is 'now()'
*
* @author soliveira
*
*/
public class MySQLBeanSession extends DefaultBeanSession {
 
public MySQLBeanSession(final BeanManager beanManager, final Connection conn) {
 
super(beanManager, conn);
}
 
@Override
protected String getDateTimeCommand() {
 
return "now()";
}
 
/**
* MySQL is not like Oracle. It will SORT everything first and then apply LIMIT.
*/
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final String orderBy, final int limit) {
 
if (limit == -1) {
return sb;
}
 
final StringBuilder sbLimit = new StringBuilder(sb.length() + 32);
 
sbLimit.append(sb.toString()).append(" LIMIT ").append(limit);
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
super.insert(bean);
 
// find autoincrement field...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
final DBField autoIncrement = bc.getAutoIncrementField();
 
if (autoIncrement == null) {
 
return;
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder("select last_insert_id() from ");
 
sb.append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final int id = rset.getInt(1);
 
injectValue(bean, autoIncrement.getName(), id, Integer.class);
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/jdbc/OracleBeanSession.java
New file
0,0 → 1,131
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
 
/**
* When using limit, Oracle will NOT sort first before limiting, so a trick must be used.
*
* Now in Oracle is 'sysdate'.
*
* Oracle only supports sequences for primary keys.
*
* @author soliveira
*
*/
public class OracleBeanSession extends DefaultBeanSession {
 
public OracleBeanSession(final BeanManager beanManager, final Connection conn) {
 
super(beanManager, conn);
}
 
@Override
protected String getDateTimeCommand() {
 
return "sysdate";
}
 
/**
* Oracle will not SORT first then apply LIMIT.
*/
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final String orderBy, final int limit) {
 
if (limit == -1) {
return sb;
}
 
final StringBuilder sbLimit = new StringBuilder(sb.length() + 32);
 
if (orderBy != null) {
 
sbLimit.append("SELECT * FROM (").append(sb.toString()).append(") where rowcount <= ").append(limit);
 
} else {
 
sbLimit.append(sb.toString()).append(" AND rownum <= ").append(limit);
}
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
// find sequence field...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
final DBField seqField = bc.getSequenceField();
 
if (seqField == null) {
 
super.insert(bean);
 
return;
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder(128);
 
sb.append("select seq_").append(seqField.getDbName()).append("_").append(bc.getTableName());
 
sb.append(".nextval from ").append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final int id = rset.getInt(1);
 
injectValue(bean, seqField.getName(), id, Integer.class);
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
 
super.insert(bean);
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/jdbc/FirebirdBeanSession.java
New file
0,0 → 1,137
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
 
/**
* Firebird support.
*
* @author soliveira
*/
public class FirebirdBeanSession extends DefaultBeanSession {
 
public FirebirdBeanSession(final BeanManager beanManager, final Connection conn) {
 
super(beanManager, conn);
}
 
@Override
protected String getDateTimeCommand() {
 
return "current_timestamp";
}
 
/**
* MySQL is not like Oracle. It will SORT everything first and then apply LIMIT.
*/
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final String orderBy, final int limit) {
 
if (limit == -1) {
return sb;
}
 
String query = sb.toString();
 
if (query.toLowerCase().startsWith("select ")) {
throw new BeanException("Got a limit query that does not start with select: " + query);
}
 
String withoutSelect = query.substring("select".length());
 
final StringBuilder sbLimit = new StringBuilder(withoutSelect.length() + 64);
 
sbLimit.append("SELECT first(").append(limit).append(")").append(withoutSelect);
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
// find autoincrement field...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
final DBField autoIncrement = bc.getAutoIncrementField();
 
if (autoIncrement == null) {
 
super.insert(bean);
 
return;
}
 
QueryAndValues qav = prepareInsertQuery(bean);
 
StringBuilder sb = qav.sb;
 
List<Value> values = qav.values;
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
// add the returning...
 
sb.append(" returning ").append(autoIncrement.getDbName());
 
if (DEBUG) {
System.out.println("INSERT SQL: " + sb.toString());
}
 
stmt = conn.prepareStatement(sb.toString());
 
Map<String, Value> fieldsLoaded = bindToInsertStatement(stmt, values);
 
rset = stmt.executeQuery();
 
if (!rset.next()) {
throw new BeanException("Nothing was inserted! Insert returned no result set!");
}
 
int id = rset.getInt(autoIncrement.getDbName());
 
injectValue(bean, autoIncrement.getName(), id, Integer.class);
 
loaded.put(bean, fieldsLoaded);
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
close(stmt, rset);
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/jdbc/H2BeanSession.java
New file
0,0 → 1,152
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
 
/**
* H2 supports AUTOINCREMENT and SEQUENCE fields.
*
* Now has the value 'sysdate', like Oracle.
*
* @author Sergio Oliveira Jr.
*/
public class H2BeanSession extends DefaultBeanSession {
 
public H2BeanSession(final BeanManager beanManager, final Connection conn) {
super(beanManager, conn);
}
 
@Override
protected String getDateTimeCommand() {
 
return "sysdate";
}
 
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final String orderBy, final int limit) {
 
if (limit == -1) {
return sb;
}
 
final StringBuilder sbLimit = new StringBuilder(sb.length() + 32);
 
sbLimit.append(sb.toString()).append(" LIMIT ").append(limit);
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
// find sequence... (if any)...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
final DBField seqField = bc.getSequenceField();
 
if (seqField != null) {
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder(128);
 
sb.append("select NEXTVAL(seq_").append(seqField.getDbName()).append("_").append(bc.getTableName());
 
sb.append(") from ").append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final int id = rset.getInt(1);
 
injectValue(bean, seqField.getName(), id, Integer.class);
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
super.insert(bean);
 
// find autoincrement field...
 
final DBField autoIncrement = bc.getAutoIncrementField();
 
if (autoIncrement == null) {
 
return;
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder("select identity() from ");
 
sb.append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final int id = rset.getInt(1);
 
injectValue(bean, autoIncrement.getName(), id, Integer.class);
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/jdbc/DefaultBeanSession.java
New file
0,0 → 1,1659
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBField;
import org.mentabean.DBType;
import org.mentabean.type.AutoIncrementType;
import org.mentabean.type.AutoTimestampType;
import org.mentabean.type.TimestampType;
import org.mentabean.util.InjectionUtils;
 
/**
* The bean session implementation based on JDBC and SQL.
*
* @author soliveira
*/
public class DefaultBeanSession implements BeanSession {
 
protected static boolean DEBUG = false;
 
/* The loaded map will be cleared when the session dies */
protected IdentityHashMap<Object, Map<String, Value>> loaded = new IdentityHashMap<Object, Map<String, Value>>();
 
protected Connection conn;
 
protected final BeanManager beanManager;
 
/**
* Creates a JdbcBeanSession with a BeanManager and a Connection.
*
* @param beanManager
* The bean manager
* @param conn
* The database connection
*/
public DefaultBeanSession(final BeanManager beanManager, final Connection conn) {
this.beanManager = beanManager;
this.conn = conn;
}
 
/**
* Turn SQL debugging on and off.
*
* @param b
* true if it should be debugged
*/
public static void debugSql(boolean b) {
DefaultBeanSession.DEBUG = b;
}
 
/**
* Get the connection associated with this JdbcBeanSession.
*
* @return the database connection
*/
public Connection getConnection() {
 
return conn;
}
 
/**
* Get the command representing 'now' in this database. This base implementation returns null, in other words, no now command will be used.
*
* @return the command for now in this database (now(), sysdate, etc)
*/
protected String getDateTimeCommand() {
 
return null;
}
 
/**
* Get a value from a bean through reflection.
*
* @param bean
* @param fieldName
* @return The value of a bean property
*/
protected static Object getValueFromBean(final Object bean, final String fieldName) {
 
return getValueFromBean(bean, fieldName, null);
 
}
 
/**
* Get a value from a bean through reflection.
*
* @param bean
* @param fieldName
* @param m
* @return The value of a bean property
*/
protected static Object getValueFromBean(final Object bean, final String fieldName, Method m) {
 
if (m == null) {
m = InjectionUtils.findMethodToGet(bean.getClass(), fieldName);
}
 
if (m == null) {
throw new BeanException("Cannot find method to get field from bean: " + fieldName);
}
 
Object value = null;
 
try {
 
value = m.invoke(bean, (Object[]) null);
 
return value;
 
} catch (Exception e) {
throw new BeanException(e);
}
}
 
private static void checkPK(final Object value, final DBField dbField) {
 
if (value == null) {
throw new BeanException("pk is missing: " + dbField);
} else if (value instanceof Number) {
 
final Number n = (Number) value;
 
if (n.doubleValue() <= 0) {
throw new BeanException("Number pk is missing: " + dbField);
}
}
}
 
@Override
public boolean load(final Object bean) {
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
if (bc.getNumberOfFields() == 0) {
throw new BeanException("BeanConfig has zero fields: " + bc);
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("SELECT ");
 
Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
while (iter.hasNext()) {
 
final String fieldName = iter.next().getDbName();
 
if (count++ > 0) {
sb.append(',');
}
 
sb.append(fieldName);
 
}
 
sb.append(" FROM ").append(bc.getTableName()).append(" WHERE ");
 
if (!bc.hasPK()) {
throw new BeanException("Cannot load bean without a PK!");
}
 
iter = bc.pks();
 
count = 0;
 
final List<Value> values = new LinkedList<Value>();
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final Object value = getValueFromBean(bean, fieldName);
 
checkPK(value, dbField);
 
if (count++ > 0) {
sb.append(" AND ");
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
 
if (values.isEmpty()) {
throw new BeanException("Bean is empty: " + bean + " / " + bc);
}
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
try {
 
if (DEBUG) {
System.out.println("LOAD SQL: " + sb.toString());
}
 
stmt = conn.prepareStatement(sb.toString());
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
rset = stmt.executeQuery();
 
index = 0;
 
final Map<String, Value> fieldsLoaded = new HashMap<String, Value>();
 
if (rset.next()) {
 
iter = bc.fields();
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
final String fieldName = f.getName();
 
final DBType type = f.getType();
 
final Object value = type.getFromResultSet(rset, ++index);
 
injectValue(bean, fieldName, value, type.getTypeClass());
 
fieldsLoaded.put(fieldName, new Value(f, value));
}
 
} else {
return false;
}
 
if (rset.next()) {
throw new BeanException("Load returned more than one row!");
}
 
loaded.put(bean, fieldsLoaded);
 
return true;
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
/**
* Inject a value in a bean through reflection.
*
* @param bean
* @param fieldName
* @param value
* @param valueType
*/
protected static void injectValue(final Object bean, final String fieldName, final Object value, final Class<? extends Object> valueType) {
 
final Method m = InjectionUtils.findMethodToInject(bean.getClass(), fieldName, value == null ? valueType : value.getClass());
 
if (m == null) {
 
// try field...
 
final Field field = InjectionUtils.findFieldToInject(bean.getClass(), fieldName, value == null ? valueType : value.getClass());
 
if (field != null) {
try {
 
field.set(bean, value);
 
} catch (final Exception e) {
 
e.printStackTrace();
 
throw new BeanException(e);
}
} else {
throw new BeanException("Cannot find field or method to inject: " + bean + " / " + fieldName);
}
 
} else {
try {
 
m.invoke(bean, value);
 
} catch (final Exception e) {
 
e.printStackTrace();
 
throw new BeanException(e);
}
}
}
 
/**
* Some databases will sort before applying the limit (MySql), others will not (Oracle). Handle each one accordingly.
*
* Note: This base implementation does nothing.
*
* @param sb
* @param orderBy
* @param limit
* @return A string builder with the the SQL modified for the limit operation
*/
protected StringBuilder handleLimit(final StringBuilder sb, final String orderBy, final int limit) {
 
return sb;
}
 
/**
* Build the column/field list for a SQL SELECT statement based on the bean configuration. Very useful to create select statements.
*
* @param beanClass
* the bean class
* @return the column/field list for a select
*/
@Override
public String buildSelect(final Class<? extends Object> beanClass) {
 
return buildSelectImpl(beanClass, null, null, null);
}
 
@Override
public String buildSelect(final Class<? extends Object> beanClass, String[] properties) {
 
return buildSelectImpl(beanClass, null, properties, null);
}
 
/**
* Build a column/field list for a SQL SELECT statement based on the bean configuration. A table prefix will be used on each field. Very useful to create select statements on multiple tables (joins).
*
* @param beanClass
* the bean class
* @param tablePrefix
* the table prefix to use before each field
* @return the column/field list for a select
*/
@Override
public String buildSelect(final Class<? extends Object> beanClass, final String tablePrefix) {
 
return buildSelectImpl(beanClass, tablePrefix, null, null);
}
 
@Override
public String buildSelect(final Class<? extends Object> beanClass, final String tablePrefix, String[] properties) {
 
return buildSelectImpl(beanClass, tablePrefix, properties, null);
}
 
/**
* Like buildSelect but you can exclude some properties from the resulting list. Useful when you have a bean with too many properties and you just want to fetch a few.
*
* Note: The list of properties to exclude contains 'property names' and NOT database column names.
*
* @param beanClass
* the bean class
* @param minus
* a list for property names to exclude
* @return the column/field list for a select
*/
@Override
public String buildSelectMinus(final Class<? extends Object> beanClass, final String[] minus) {
 
return buildSelectImpl(beanClass, null, null, minus);
}
 
/**
* Same as buildSelectMinus with support for a database table prefix that will be applied on each field.
*
* @param beanClass
* the bean class
* @param tablePrefix
* the database table prefix
* @param minus
* a list of property names to exclude
* @return the column/field list for a select
*/
@Override
public String buildSelectMinus(final Class<? extends Object> beanClass, final String tablePrefix, final String[] minus) {
 
return buildSelectImpl(beanClass, tablePrefix, null, minus);
}
 
private String buildSelectImpl(final Class<? extends Object> beanClass, final String tablePrefix, final String[] properties, final String[] minus) {
 
final BeanConfig bc = beanManager.getBeanConfig(beanClass);
 
if (bc == null) {
return null;
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
final Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField field = iter.next();
 
final String dbField = field.getDbName();
 
if (minus != null && minus.length > 0) {
 
final String name = field.getName();
 
if (properties != null && !checkArray(name, properties)) {
continue;
}
 
if (minus != null && checkArray(name, minus)) {
continue;
}
}
 
if (count++ > 0) {
sb.append(",");
}
 
if (tablePrefix != null) {
 
sb.append(tablePrefix).append('.');
 
sb.append(dbField).append(' ');
 
sb.append(tablePrefix).append('_').append(dbField);
 
} else {
sb.append(dbField);
}
}
 
return sb.toString();
 
}
 
private static boolean checkArray(final String value, final String[] array) {
 
for (int i = 0; i < array.length; i++) {
if (array[i].equals(value)) {
return true;
}
}
 
return false;
}
 
/**
* Populate a bean (insert all its properties) from the results in a result set, based on the bean configuration.
*
* @param rset
* the result set from where to get the property values
* @param bean
* the bean to be populated
* @throws Exception
*/
@Override
public void populateBean(final ResultSet rset, final Object bean) {
 
populateBeanImpl(rset, bean, null, null, null);
}
 
@Override
public void populateBean(final ResultSet rset, final Object bean, String[] properties) {
 
populateBeanImpl(rset, bean, null, properties, null);
}
 
/**
* Same as populateBean, but use a table prefix before fetching the values from the result set. Useful when there are multiple tables involved and you want to avoid field name clashing.
*
* @param rset
* the result set
* @param bean
* the bean to be populated
* @param tablePrefix
* the table prefix
*/
@Override
public void populateBean(final ResultSet rset, final Object bean, final String tablePrefix) {
 
populateBeanImpl(rset, bean, tablePrefix, null, null);
}
 
@Override
public void populateBean(final ResultSet rset, final Object bean, final String tablePrefix, String[] properties) {
 
populateBeanImpl(rset, bean, tablePrefix, properties, null);
}
 
/**
* Same as populateBean, but exclude some fields when populating.
*
* @param rset
* @param bean
* @param minus
*/
@Override
public void populateBeanMinus(final ResultSet rset, final Object bean, final String[] minus) {
 
populateBeanImpl(rset, bean, null, null, minus);
}
 
/**
* Same as populateBean, but exclude some fields when populating and use a table prefix in front of the field names.
*
* @param rset
* @param bean
* @param tablePrefix
* @param minus
*/
@Override
public void populateBeanMinus(final ResultSet rset, final Object bean, final String tablePrefix, final String[] minus) {
 
populateBeanImpl(rset, bean, tablePrefix, null, minus);
}
 
private void populateBeanImpl(final ResultSet rset, final Object bean, final String tablePrefix, final String[] properties, final String[] minus) {
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
final Iterator<DBField> iter = bc.fields();
 
final StringBuilder sbField = new StringBuilder(32);
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
final String fieldName = f.getName();
 
if (minus != null && checkArray(fieldName, minus)) {
continue;
}
 
final String dbFieldName = f.getDbName();
 
final DBType type = f.getType();
 
sbField.setLength(0);
 
if (tablePrefix != null) {
sbField.append(tablePrefix).append('_').append(dbFieldName);
} else {
sbField.append(dbFieldName);
}
 
try {
 
final Object value = type.getFromResultSet(rset, sbField.toString());
 
injectValue(bean, fieldName, value, type.getTypeClass());
 
} catch (Exception e) {
 
throw new BeanException(e);
}
}
}
 
/**
* Load a list of beans, but exclude some fields.
*
* @param <E>
* @param bean
* @param minus
* @param orderBy
* @param limit
* @return A list of beans
*/
@Override
public <E> List<E> loadListMinus(final E bean, final String orderBy, final int limit, final String[] minus) {
 
return loadListImpl(bean, orderBy, limit, null, minus);
}
 
private <E> E checkUnique(final List<E> list) {
 
if (list == null || list.size() == 0) {
return null;
} else if (list.size() > 1) {
throw new BeanException("Query returned more than one bean!");
} else {
return list.get(0);
}
}
 
@Override
public <E> List<E> loadList(final E bean, final String orderBy, final int limit) {
 
return loadListImpl(bean, orderBy, limit, null, null);
}
 
@Override
public <E> List<E> loadList(final E bean, final String orderBy, final int limit, String[] properties) {
return loadListImpl(bean, orderBy, limit, properties, null);
}
 
private <E> StringBuilder prepareListQuery(StringBuilder sb, BeanConfig bc, E bean, String orderBy, int limit, List<Value> values) {
 
sb.append(" FROM ").append(bc.getTableName()).append(" ");
 
Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField field = iter.next();
 
final String dbField = field.getDbName();
 
final Method m = InjectionUtils.findMethodToGet(bean.getClass(), field.getName());
 
if (m == null) {
throw new BeanException("Cannot find method to get field from bean: " + field.getName());
}
 
final Class<? extends Object> returnType = m.getReturnType();
 
final Object value = getValueFromBean(bean, field.getName(), m);
 
if (!isSet(value, returnType)) {
continue;
}
 
if (count++ > 0) {
sb.append(" AND ");
} else {
sb.append(" WHERE ");
}
 
sb.append(dbField).append("=?");
 
values.add(new Value(field, value));
}
 
if (orderBy != null) {
sb.append(" order by ").append(orderBy).append(" ");
}
 
sb = handleLimit(sb, orderBy, limit);
 
return sb;
}
 
@Override
public int countList(Object bean) {
return countListImpl(bean, null, null, -1);
}
 
private int countListImpl(final Object bean, final String[] minus, final String orderBy, final int limit) {
 
if (limit == 0) {
return 0;
}
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("SELECT count(1)");
 
final List<Value> values = new LinkedList<Value>();
 
sb = prepareListQuery(sb, bc, bean, orderBy, limit, values);
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
try {
 
final String sql = sb.toString();
 
if (DEBUG) {
System.out.println("COUNT LIST: " + sql);
}
 
stmt = conn.prepareStatement(sql);
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
rset = stmt.executeQuery();
 
rset.next();
 
return rset.getInt(1);
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
private <E> List<E> loadListImpl(final E bean, final String orderBy, final int limit, final String[] properties, final String[] minus) {
 
if (limit == 0) {
return new ArrayList<E>();
}
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
Iterator<DBField> iter = bc.fields();
 
sb.append("SELECT ");
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField field = iter.next();
 
final String dbField = field.getDbName();
 
final String name = field.getName();
 
if (properties != null && !checkArray(name, properties)) {
continue;
}
 
if (minus != null && checkArray(name, minus)) {
continue;
}
 
if (count++ > 0) {
sb.append(",");
}
 
sb.append(dbField);
}
 
final List<Value> values = new LinkedList<Value>();
 
sb = prepareListQuery(sb, bc, bean, orderBy, limit, values);
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
try {
 
final String sql = sb.toString();
 
if (DEBUG) {
System.out.println("LOAD LIST: " + sql);
}
 
stmt = conn.prepareStatement(sql);
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
rset = stmt.executeQuery();
 
final List<E> results = new LinkedList<E>();
 
final Class<? extends Object> beanKlass = bean.getClass();
 
int total = 0;
 
while (rset.next()) {
 
iter = bc.fields();
 
index = 0;
 
final E item = (E) beanKlass.newInstance(); // not sure how to
// handle generics
// here...
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
final String fieldName = f.getName();
 
if (properties != null && !checkArray(fieldName, properties)) {
continue;
}
 
if (minus != null && checkArray(fieldName, minus)) {
continue;
}
 
final DBType type = f.getType();
 
final Object value = type.getFromResultSet(rset, ++index);
 
injectValue(item, fieldName, value, type.getTypeClass());
}
 
results.add(item);
 
total++;
 
if (limit > 0 && total == limit) {
return results;
}
}
 
return results;
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
/**
* if Boolean consider TRUE to be set and FALSE to be not set.
*
* if Character, cast to integer and assume it is set if different than 0
*
* if Number consider everything different than zero to be set.
*
* Otherwise returns TRUE for anything different than null and FALSE for null.
*
* @param value
* @param returnType
* @return true if is set
*/
protected boolean isSet(final Object value, final Class<? extends Object> returnType) {
 
if (value != null) {
if (returnType.equals(boolean.class) && value instanceof Boolean) {
 
// if Boolean consider TRUE to be set and FALSE to be not set
// (false = default value)
 
final boolean b = ((Boolean) value).booleanValue();
 
return b;
 
} else if (returnType.equals(char.class) && value instanceof Character) {
 
// if Character, cast to int and assume set if different than
// 0...
 
final int c = ((Character) value).charValue();
 
return c != 0;
 
} else if (returnType.isPrimitive() && !returnType.equals(boolean.class) && !returnType.equals(char.class) && value instanceof Number) {
 
// if number consider everything different than zero to be
// set...
 
final Number n = (Number) value;
 
if (n.intValue() != 0) {
return true;
}
 
} else {
return true;
}
}
 
return false;
}
 
@Override
public int update(final Object bean) {
 
return update(bean, true);
}
 
@Override
public int updateAll(final Object bean) {
 
return update(bean, false);
}
 
private int update(final Object bean, final boolean dynUpdate) {
 
final Map<String, Value> fieldsLoaded = loaded.get(bean);
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
if (bc.getNumberOfFields() == 0) {
throw new BeanException("BeanConfig has zero fields: " + bc);
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("UPDATE ").append(bc.getTableName()).append(" SET ");
 
Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
final List<Value> values = new LinkedList<Value>();
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
if (dbField.isPK()) {
continue;
}
 
final DBType type = dbField.getType();
 
if (type instanceof AutoIncrementType) {
continue;
}
 
if (type instanceof AutoTimestampType) {
continue;
}
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final Method m = InjectionUtils.findMethodToGet(bean.getClass(), fieldName);
 
if (m == null) {
throw new BeanException("Cannot find method to get field from bean: " + fieldName);
}
 
final Class<? extends Object> returnType = m.getReturnType();
 
final Object value = getValueFromBean(bean, fieldName, m);
 
boolean update = false;
 
if (!dynUpdate) {
 
// if this is NOT a dynUpdate then update all properties with
// whatever value they have
 
update = true;
 
} else if (fieldsLoaded != null) {
 
// this is a dynUpdate, check if value is dirty, in other words,
// if it has changed since it was loaded...
 
final Value v = fieldsLoaded.get(fieldName);
 
if (v != null) {
if (value == null && v.value != null) {
update = true;
} else if (value != null && v.value == null) {
update = true;
} else if (value == null && v.value == null) {
update = false;
} else {
update = !value.equals(v.value);
}
}
 
} else {
 
// this is a dynUpdate, but bean was not previously loaded from
// the database...
// in this case only update is the property is considered to be
// SET...
 
update = isSet(value, returnType);
}
 
if (update) {
 
if (count++ > 0) {
sb.append(',');
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
}
 
if (count == 0) {
return 0;
}
 
sb.append(" WHERE ");
 
if (!bc.hasPK()) {
throw new BeanException("Cannot update bean without a PK!");
}
 
iter = bc.pks();
 
count = 0;
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final Object value = getValueFromBean(bean, fieldName);
 
if (value == null) {
throw new BeanException("pk is missing: " + dbField);
} else if (value instanceof Number) {
 
final Number n = (Number) value;
 
if (n.doubleValue() <= 0) {
throw new BeanException("Number pk is missing: " + dbField);
}
 
}
 
if (count++ > 0) {
sb.append(" AND ");
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
 
if (values.isEmpty()) {
throw new BeanException("Bean is empty: " + bean + " / " + bc);
}
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
 
try {
 
if (DEBUG) {
System.out.println("UPDATE SQL: " + sb.toString());
}
 
stmt = conn.prepareStatement(sb.toString());
 
Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
final int x = stmt.executeUpdate();
 
if (x > 1) {
throw new BeanException("update modified more than one line: " + x);
}
 
if (x == 0) {
return 0;
}
 
if (fieldsLoaded != null) {
 
iter2 = values.iterator();
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
if (v.field.isPK()) {
continue;
}
 
final Value vv = fieldsLoaded.get(v.field.getName());
 
if (vv != null) {
vv.value = v.value;
}
}
}
 
return 1;
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt);
}
}
 
protected class QueryAndValues {
 
public QueryAndValues(StringBuilder sb, List<Value> values) {
this.sb = sb;
this.values = values;
}
 
public StringBuilder sb;
public List<Value> values;
}
 
protected QueryAndValues prepareInsertQuery(Object bean) {
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
if (bc.getNumberOfFields() == 0) {
throw new BeanException("BeanConfig has zero fields: " + bc);
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("INSERT INTO ").append(bc.getTableName()).append("(");
 
Iterator<DBField> iter = bc.pks();
 
int count = 0;
 
final List<Value> values = new LinkedList<Value>();
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final DBType type = dbField.getType();
 
if (type instanceof AutoIncrementType) {
continue;
}
 
if (type instanceof AutoTimestampType) {
continue;
}
 
final Object value = getValueFromBean(bean, fieldName);
 
if (count++ > 0) {
sb.append(',');
}
 
sb.append(dbFieldName);
 
values.add(new Value(dbField, value));
}
 
iter = bc.fields();
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
if (dbField.isPK()) {
continue;
}
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final DBType type = dbField.getType();
 
if (type instanceof AutoIncrementType) {
continue;
}
 
if (type instanceof AutoTimestampType) {
continue;
}
 
Object value = getValueFromBean(bean, fieldName);
 
boolean isSysdate = false;
 
if (type instanceof TimestampType) { // only timestamp (date AND time) should use the database command for datetime
 
isSysdate = dbField.isDefaultToNow() && value == null;
 
if (isSysdate && getDateTimeCommand() == null) {
value = new java.util.Date();
}
}
 
if (count++ > 0) {
sb.append(',');
}
 
sb.append(dbFieldName);
 
values.add(new Value(dbField, value, isSysdate));
}
 
if (count == 0) {
throw new BeanException("There is nothing to insert!");
}
 
sb.append(") VALUES(");
 
final Iterator<Value> valuesIter = values.iterator();
 
int i = 0;
 
while (valuesIter.hasNext()) {
 
final Value v = valuesIter.next();
 
if (i > 0) {
sb.append(',');
}
 
if (v.isSysdate && getDateTimeCommand() != null) {
sb.append(getDateTimeCommand());
} else {
sb.append('?');
}
 
i++;
}
 
sb.append(')');
 
if (values.isEmpty()) {
throw new BeanException("Bean is empty: " + bean + " / " + bc);
}
 
return new QueryAndValues(sb, values);
}
 
protected Map<String, Value> bindToInsertStatement(PreparedStatement stmt, List<Value> values) {
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
final Map<String, Value> fieldsLoaded = new HashMap<String, Value>();
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
if (v.isSysdate && getDateTimeCommand() != null) {
continue;
}
 
try {
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
} catch (Exception e) {
throw new BeanException(e);
}
 
fieldsLoaded.put(v.field.getName(), v);
}
 
return fieldsLoaded;
}
 
@Override
public void insert(final Object bean) {
 
QueryAndValues qav = prepareInsertQuery(bean);
 
StringBuilder sb = qav.sb;
 
List<Value> values = qav.values;
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
 
try {
 
if (DEBUG) {
System.out.println("INSERT SQL: " + sb.toString());
}
 
stmt = conn.prepareStatement(sb.toString());
 
Map<String, Value> fieldsLoaded = bindToInsertStatement(stmt, values);
 
final int x = stmt.executeUpdate();
 
if (x > 1) {
throw new BeanException("insert modified more than one line: " + x);
}
 
if (x == 0) {
throw new BeanException("Nothing was inserted! Insert returned 0 rows!");
}
 
loaded.put(bean, fieldsLoaded);
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
close(stmt);
}
}
 
@Override
public boolean delete(final Object bean) {
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc.getNumberOfFields() == 0) {
throw new BeanException("BeanConfig has zero fields: " + bc);
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("DELETE FROM ").append(bc.getTableName()).append(" WHERE ");
 
if (!bc.hasPK()) {
throw new BeanException("Cannot delete bean without a PK!");
}
 
final Iterator<DBField> iter = bc.pks();
 
final List<Value> values = new LinkedList<Value>();
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final Object value = getValueFromBean(bean, fieldName);
 
if (value == null) {
throw new BeanException("pk is missing: " + dbField);
} else if (value instanceof Number) {
 
final Number n = (Number) value;
 
if (n.doubleValue() <= 0) {
throw new BeanException("Number pk is missing: " + dbField);
}
 
}
 
if (count++ > 0) {
sb.append(" AND ");
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
 
if (values.isEmpty()) {
throw new BeanException("Bean is empty: " + bean + " / " + bc);
}
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
 
try {
 
if (DEBUG) {
System.out.println("DELETE SQL: " + sb.toString());
}
 
stmt = conn.prepareStatement(sb.toString());
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
final int x = stmt.executeUpdate();
 
if (x > 1) {
throw new BeanException("delete modified more than one line: " + x);
}
 
if (x == 0) {
return false;
}
 
loaded.remove(bean);
 
return true;
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt);
}
}
 
@Override
public <E> List<E> loadList(final E bean) {
 
return loadList(bean, null, -1);
}
 
@Override
public <E> List<E> loadList(final E bean, String[] properties) {
return loadListImpl(bean, null, -1, properties, null);
}
 
@Override
public <E> E loadUnique(final E bean) {
 
return checkUnique(loadList(bean, null, 2));
}
 
@Override
public <E> List<E> loadList(final E bean, final String orderBy) {
 
return loadList(bean, orderBy, -1);
}
 
@Override
public <E> List<E> loadList(final E bean, final String orderBy, String[] properties) {
return loadListImpl(bean, orderBy, -1, properties, null);
}
 
@Override
public <E> List<E> loadList(final E bean, final int limit) {
 
return loadList(bean, null, limit);
}
 
@Override
public <E> List<E> loadList(final E bean, final int limit, String[] properties) {
return loadListImpl(bean, null, limit, properties, null);
}
 
/**
* Load a list of beans, but exclude some fields. Useful when the bean has too many properties and you don't want to fetch everything from the database.
*
* @param <E>
* @param bean
* @param minus
* @return A list of beans
*/
@Override
public <E> List<E> loadListMinus(final E bean, final String[] minus) {
 
return loadListMinus(bean, null, -1, minus);
}
 
/**
* Load a list of beans, but exclude some fields. Useful when the bean has too many properties and you don't want to fetch everything from the database.
*
* @param <E>
* @param bean
* @param minus
* @param orderBy
* @return A list of beans
*/
@Override
public <E> List<E> loadListMinus(final E bean, final String orderBy, final String[] minus) {
 
return loadListMinus(bean, orderBy, -1, minus);
}
 
/**
* Load a list of beans, but exclude some fields. Useful when the bean has too many properties and you don't want to fetch everything from the database.
*
* @param <E>
* @param bean
* @param minus
* @param limit
* @return A list of beans
*/
@Override
public <E> List<E> loadListMinus(final E bean, final int limit, final String[] minus) {
 
return loadListMinus(bean, null, limit, minus);
}
 
protected class Value {
 
public Object value;
 
public DBField field;
 
public boolean isSysdate;
 
public Value(final DBField field, final Object value, final boolean isSysdate) {
 
this.field = field;
 
this.value = value;
 
this.isSysdate = isSysdate;
}
 
public Value(final DBField field, final Object value) {
 
this(field, value, false);
}
}
 
static void close(PreparedStatement stmt) {
close(stmt, null);
}
 
static void close(PreparedStatement stmt, ResultSet rset) {
 
if (rset != null) {
try {
rset.close();
} catch (Exception e) {
e.printStackTrace();
}
}
 
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/BeanException.java
New file
0,0 → 1,97
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
/**
* A runtime exception that can happen when working with MentaBean.
*
* @author Sergio Oliveira Jr.
*/
public class BeanException extends RuntimeException {
 
protected final Throwable rootCause;
 
public BeanException() {
super();
this.rootCause = null;
}
 
public BeanException(Throwable e) {
super(getMsg(e), e);
Throwable root = getRootCause(e);
this.setStackTrace(root.getStackTrace());
 
this.rootCause = root == this ? null : root;
}
 
public BeanException(String msg) {
super(msg);
 
this.rootCause = null;
}
 
public BeanException(String msg, Throwable e) {
 
super(msg, e);
Throwable root = getRootCause(e);
this.setStackTrace(root.getStackTrace());
 
this.rootCause = root == this ? null : root;
}
 
private static String getMsg(Throwable t) {
 
Throwable root = getRootCause(t);
 
String msg = root.getMessage();
 
if (msg == null || msg.length() == 0) {
 
msg = t.getMessage();
 
if (msg == null || msg.length() == 0) {
return root.getClass().getName();
}
}
 
return msg;
}
 
private static Throwable getRootCause(Throwable t) {
 
Throwable root = t.getCause();
 
if (root == null) {
return t;
}
 
while (root.getCause() != null) {
 
root = root.getCause();
}
 
return root;
 
}
 
@Override
public Throwable getCause() {
 
return rootCause;
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/BaseMentaBean.java
New file
0,0 → 1,59
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
/**
* A base implementation of MentaBean to be used by composition.
*
* @author sergio.oliveira.jr@gmail.com
*/
public class BaseMentaBean implements MentaBean {
 
private final BeanSession session;
private final Object bean;
 
public BaseMentaBean(Object bean, BeanSession session) {
this.bean = bean;
this.session = session;
}
 
@Override
public void insert() {
session.insert(bean);
}
 
@Override
public boolean load() {
return session.load(bean);
}
 
@Override
public boolean update() {
return session.update(bean) == 1;
}
 
@Override
public boolean updateAll() {
return session.updateAll(bean) == 1;
}
 
@Override
public boolean delete() {
return session.delete(bean);
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/DBType.java
New file
0,0 → 1,74
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
/**
* An interface defining a database type. You can add more database types by implementing this interface.
*
* @author sergio.oliveira.jr@gmail.com
*/
public interface DBType<E> {
 
/**
* Do what you have to do to get and return this database type from a result set.
*
* @param rset
* The result set
* @param index
* The index in the result set
* @return The value from the result set
* @throws SQLException
*/
public E getFromResultSet(ResultSet rset, int index) throws SQLException;
 
/**
* Do what you have to do to bind a value to a prepared statement.
*
* @param stmt
* The prepared statement
* @param index
* The index in the prepared statement
* @param value
* The value to be bound to the prepared statement
* @throws SQLException
*/
public void bindToStmt(PreparedStatement stmt, int index, E value) throws SQLException;
 
/**
* Do what you have to do to get and return this database type from a result set.
*
* @param rset
* The result set
* @param field
* The name of the field in the result set
* @return The value from the result set
* @throws SQLException
*/
public E getFromResultSet(ResultSet rset, String field) throws SQLException;
 
/**
* Return the java type representing this database type.
*
* @return The java type of this database type.
*/
public Class<? extends Object> getTypeClass();
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/BeanSession.java
New file
0,0 → 1,196
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import java.sql.ResultSet;
import java.util.List;
 
/**
* Describe a simple ORM interface that can perform CRUD for Beans according to properties defined programmatically on BeanManager. It can also load lists and unique beans based on properties set on a given bean. It also supports dynamic update, in other words, it will only update fields from a bean
* loaded from the database that were actually modified during the session. The behavior can be turned off when necessary ,in other words, when you want to blindly update all properties from a bean in the database regarding of whether they were modified or not.
*
* @author Sergio Oliveira Jr.
*/
public interface BeanSession {
 
/**
* Load the bean from the database, injecting all its properties through reflection. Note that the bean passed MUST have its primary key set otherwise there is no way we can load it from the database.
*
* @param bean
* The bean we want to load from the DB.
* @return true if the bean was found in the database, false otherwise
*/
public boolean load(Object bean);
 
/**
* Update the bean in the database. Only the bean fields that have been modified (dirty) will be updated.
*
* It will return 1 if an update did happen or 0 if the bean could not be found in the database or if there was nothing modified in bean.
*
* The bean MUST have its primary key set, otherwise it is impossible to update the bean in the database, and an exception will be thrown.
*
* @param bean
* The bean to be updated
* @return 1 if update was successful, 0 if the update did not happen or was not necessary
*/
public int update(Object bean);
 
/**
* Same as update(bean) but here you can turn off the default dynamic update behavior and force all bean properties to be updated regardless whether they have been modified or not.
*
* @param bean
* @return the number of rows that were updated
* @throws Exception
*/
public int updateAll(Object bean);
 
/**
* Insert the bean in the database.
*
* Depending on the type of PK, the generation of the PK can and should be taken care by the DB itself. The generated PK should be inserted in the bean by reflection, before the method returns.
*
* The default, database-independent implementation of this method, insert all fields in the database not worrying about PK generation strategies.
*
* @param bean
* The bean to insert
*/
public void insert(Object bean);
 
/**
* Delete the bean from the database.
*
* The PK of the bean MUST be set. The bean can only be deleted by its PK.
*
* @param bean
* @return true if it was deleted or false if it did not exist
* @throws Exception
*/
public boolean delete(Object bean);
 
/**
* Count the number of beans that would be returned by a loadList method.
*
* @param bean
* The bean holding the properties used by the list query.
* @return the number of beans found in the database
*/
public int countList(Object bean);
 
/**
* Load a list of beans based on the properties present in the bean passed. For example, if you want to load all users with lastName equal to 'saoj' you would instantiate a bean and set its lastName property to 'saoj' before passing it as an argument to this method.
*
* @param <E>
* @param bean
* The bean holding the properties used by the list query.
* @return A list of beans the match the properties in the given bean. Or an empty list if nothing was found.
*/
public <E> List<E> loadList(E bean);
public <E> List<E> loadList(E bean, String[] properties);
public <E> List<E> loadListMinus(E bean, String[] minus);
/**
* Same as loadList(bean) except that you can order the list returned by passing an SQL orderBy clause.
*
* @param <E>
* @param bean
* The bean holding the properties used by the list query.
* @param orderBy
* The orderBy SQL clause.
* @return A list of beans the match the properties in the given bean. Or an empty list if nothing was found.
*/
public <E> List<E> loadList(E bean, String orderBy);
public <E> List<E> loadList(E bean, String orderBy, String[] properties);
public <E> List<E> loadListMinus(E bean, String orderBy, String[] minus);
/**
* Same as loadList(bean) except that you can limit the number of beans returned in the list.
*
* @param <E>
* @param bean
* The bean holding the properties used by the list query.
* @param limit
* The max number of beans returned in the list.
* @return A list of beans the match the properties in the given bean. Or an empty list if nothing was found.
*/
public <E> List<E> loadList(E bean, int limit);
public <E> List<E> loadList(E bean, int limit, String[] properties);
public <E> List<E> loadListMinus(E bean, int limit, String[] minus);
 
/**
* Same as loadList(bean) except that you can limit the number of beans returned in the list as well as sort them by passing a orderBy SQL clause.
*
* @param <E>
* @param bean
* The bean holding the properties used by the list query.
* @param orderBy
* The orderBy SQL clause.
* @param limit
* The max number of beans returned in the list.
* @return A list of beans the match the properties in the given bean. Or an empty list if nothing was found.
*/
public <E> List<E> loadList(E bean, String orderBy, int limit);
public <E> List<E> loadList(E bean, String orderBy, int limit, String[] properties);
public <E> List<E> loadListMinus(E bean, String orderBy, int limit, String[] minus);
 
/**
* Same as loadList(bean) but it attempts to load a single bean only. If more than one bean is found it throws an exception.
*
* @param <E>
* @param bean
* The bean holding the properties used by the load query.
* @return A unique bean that match the properties in the given bean. Or null if nothing was found.
* @throws BeanException
* if more than one bean is found by the query.
*/
public <E> E loadUnique(E bean);
 
public String buildSelect(final Class<? extends Object> beanClass);
public String buildSelect(final Class<? extends Object> beanClass, String[] properties);
public String buildSelectMinus(final Class<? extends Object> beanClass, String[] minus);
 
public String buildSelect(final Class<? extends Object> beanClass, String tableName);
public String buildSelect(final Class<? extends Object> beanClass, String tableName, String[] properties);
public String buildSelectMinus(final Class<? extends Object> beanClass, String tableName, String[] minus);
public void populateBean(final ResultSet rset, final Object bean);
public void populateBean(final ResultSet rset, final Object bean, String[] properties);
public void populateBeanMinus(final ResultSet rset, final Object bean, String[] minus);
public void populateBean(final ResultSet rset, final Object bean, String tableName);
public void populateBean(final ResultSet rset, final Object bean, String tableName, String[] properties);
public void populateBeanMinus(final ResultSet rset, final Object bean, String tableName, String[] minus);
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/DBField.java
New file
0,0 → 1,108
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import org.mentabean.type.TimestampType;
 
/**
* A class representing a database field. It has the name of the bean property, the name of the column in the database, the database type, whether it is a PK or not and whether it default to now.
*
* @author sergio.oliveira.jr@gmail.com
*/
public class DBField {
 
private final String name;
private final DBType<?> type;
private final String dbName;
private final boolean isPK;
private boolean defaultToNow = false;
 
public DBField(final String name, final String dbName, final DBType<?> type, final boolean isPK) {
this.name = name;
this.dbName = dbName;
this.type = type;
this.isPK = isPK;
}
 
public void setDefaultToNow(final boolean b) {
if (!(getType() instanceof TimestampType)) {
throw new IllegalStateException("Only TimestampType can be set to now!");
}
 
this.defaultToNow = b;
}
 
public boolean isDefaultToNow() {
 
return defaultToNow;
}
 
@Override
public String toString() {
 
final StringBuilder sb = new StringBuilder(32);
 
sb.append("DBField: ").append(name).append(" type=").append(type).append(" dbName=").append(dbName);
 
return sb.toString();
}
 
@Override
public int hashCode() {
 
return name.hashCode();
}
 
@Override
public boolean equals(final Object obj) {
 
if (obj instanceof DBField) {
 
final DBField f = (DBField) obj;
 
if (f.name.equalsIgnoreCase(this.name)) {
return true;
}
}
 
return false;
}
 
public String getName() {
 
return name;
 
}
 
public DBType getType() {
 
return type;
}
 
public String getDbName() {
 
return dbName;
}
 
public boolean isPK() {
 
return isPK;
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/DBTypes.java
New file
0,0 → 1,52
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import org.mentabean.type.AutoIncrementType;
import org.mentabean.type.AutoTimestampType;
import org.mentabean.type.BigDecimalType;
import org.mentabean.type.BooleanIntType;
import org.mentabean.type.BooleanStringType;
import org.mentabean.type.DateType;
import org.mentabean.type.DoubleType;
import org.mentabean.type.FloatType;
import org.mentabean.type.IntegerType;
import org.mentabean.type.LongType;
import org.mentabean.type.SequenceType;
import org.mentabean.type.StringType;
import org.mentabean.type.TimeType;
import org.mentabean.type.TimestampType;
 
public class DBTypes {
 
public static StringType STRING = new StringType();
public static IntegerType INTEGER = new IntegerType();
public static DateType DATE = new DateType();
public static SequenceType SEQUENCE = new SequenceType();
public static AutoIncrementType AUTOINCREMENT = new AutoIncrementType();
public static AutoTimestampType AUTOTIMESTAMP = new AutoTimestampType();
public static LongType LONG = new LongType();
public static DoubleType DOUBLE = new DoubleType();
public static TimeType TIME = new TimeType();
public static TimestampType TIMESTAMP = new TimestampType();
public static FloatType FLOAT = new FloatType();
public static BooleanStringType BOOLEANSTRING = new BooleanStringType();
public static BooleanIntType BOOLEANINT = new BooleanIntType();
public static BigDecimalType BIGDECIMAL = new BigDecimalType();
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/MentaBean.java
New file
0,0 → 1,64
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
/**
* The functionality of a MentaBean, in other words, the methods you can call on a mentabean to perform database operations like insert, load, reload, save, update and delete.
*
* @author Sergio Oliveira Jr.
*/
public interface MentaBean {
 
/**
* Attempt to insert a bean to the database.
*
* Note: This method can be called multiple times in the same bean. Of course the PK constraints will be enforced by the database, so you can change the PK by hand and call this method multiple times, to insert multiple beans. If the PK is an auto-generated database field (e.g. auto-increment),
* you will not change the PK by hand and a new PK will be automatically assigned to the bean.
*/
public void insert();
 
/**
* Attempt to load the bean properties from the database.
*
* This method will throw an exception if you try to load a bean without its primary key set.
*
* @return true if the bean was loaded
*/
public boolean load();
 
/**
* Attempt to update the bean properties in the database. If this bean was previously loaded, this method will update only the properties that were modified (dirty).
*
* @return true if it was updated
*/
public boolean update();
 
/**
* Attempt to update ALL the bean properties in the database, not just the ones that have been changed.
*
* @return true if it was updated
*/
public boolean updateAll();
 
/**
* Attempt to delete a bean from the database. It will throw an exception if the bean does not have its PK set.
*
* @return true if it was deleted
*/
public boolean delete();
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/BeanConfig.java
New file
0,0 → 1,297
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
 
import org.mentabean.type.AutoIncrementType;
import org.mentabean.type.SequenceType;
 
/**
* A class representing a bean configuration, like table name, primary keys and fields in the database.
*
* @author sergio.oliveira.jr@gmail.com
*/
public class BeanConfig {
 
private final List<DBField> fieldList = new LinkedList<DBField>();
 
private final List<DBField> pkList = new LinkedList<DBField>();
 
private final Class<? extends Object> beanClass;
 
private final String tableName;
 
private DBField sequence = null;
 
private DBField autoincrement = null;
 
/**
* Creates a configuration for a bean represented by the given class.
*
* @param beanClass
* The bean klass
* @param tableName
* The database table where the bean properties will be stored.
*/
public BeanConfig(final Class<? extends Object> beanClass, final String tableName) {
 
this.beanClass = beanClass;
 
this.tableName = tableName;
}
 
/**
* Return the table name where the bean properties are stored.
*
* @return The database table name.
*/
public String getTableName() {
 
return tableName;
}
 
/**
* Return the bean class.
*
* @return The bean class.
*/
public Class<? extends Object> getBeanClass() {
 
return beanClass;
}
 
private DBField findDBField(final String name) {
 
final Iterator<DBField> iter = fieldList.iterator();
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
if (f.getName().equals(name)) {
return f;
}
}
 
return null;
}
 
private BeanConfig addField(final String name, final String dbName, final DBType<? extends Object> type, final boolean isPK) {
 
if (!isPK) {
 
if (type instanceof SequenceType) {
throw new IllegalStateException("A sequence type can only be a primary key!");
}
 
if (type instanceof AutoIncrementType) {
throw new IllegalStateException("A auto-increment type can only be a primary key!");
}
}
 
final DBField f = new DBField(name, dbName, type, isPK);
 
fieldList.add(f);
 
if (isPK) {
 
pkList.add(f);
 
if (type instanceof SequenceType) {
 
if (sequence != null) {
throw new IllegalStateException("A bean can have only one sequence field!");
}
 
sequence = f;
 
} else if (type instanceof AutoIncrementType) {
 
if (autoincrement != null) {
throw new IllegalStateException("A bean can have only one auto-increment field!");
}
 
autoincrement = f;
}
}
 
return this;
}
 
/**
* Return an auto-increment field, if one was configured for this bean.
*
* Note: A bean can have only one auto-increment field configured for this bean. Attempting to configure more than one will throw an exception.
*
* @return the auto-increment field configured for this bean or null if it was not defined
*/
public DBField getAutoIncrementField() {
 
return autoincrement;
}
 
/**
* Return a sequence field, if one was configured for this bean.
*
* Note: A bean can have only one sequence field configured for this bean. Attempting to configure more than one will throw an exception.
*
* @return the sequence field configured for this bean or null if it was not defined
*/
public DBField getSequenceField() {
 
return sequence;
}
 
/**
* Make this bean property default to 'now' when inserting in the database.
*
* Note: The bean property must have been previously configured for you to call this method, in other words, a field must have been previously configured with that bean property name.
*
* @param name
* The bean property name that should default to now.
*
* @return This BeanConfig (Fluent API)
*/
public BeanConfig defaultToNow(final String name) {
 
final DBField f = findDBField(name);
 
if (f == null) {
throw new IllegalArgumentException("Cannot find field with name: " + name);
}
 
f.setDefaultToNow(true);
 
return this;
}
 
/**
* Add a database field for the given property with the given database type. It assumes that the property name is the SAME as the database column name. If they are different, use the other addField method.
*
* @param name
* The bean property name (same as the database column name)
* @param type
* The database type
* @return This BeanConfig (Fluent API)
*/
public BeanConfig field(final String name, final DBType<? extends Object> type) {
 
return addField(name, name, type, false);
}
 
/**
* Add a database field for the given property with the given database type.
*
* @param name
* The bean property name
* @param dbName
* The name of the database column holding this property
* @param type
* The database type
* @return This BeanConfig (Fluent API)
*/
public BeanConfig field(final String name, final String dbName, final DBType<? extends Object> type) {
 
return addField(name, dbName, type, false);
}
 
/**
* Add a bean property that is the primary key in the database. The column name is the same as the property bean name. If they are different use the other pk method. All beans must have a primary key and you can call this method multiple times to support composite primary keys.
*
* @param name
* The bean property name
* @param type
* The database type
* @return This BeanConfig (Fluent API)
*/
public BeanConfig pk(final String name, final DBType<? extends Object> type) {
 
return addField(name, name, type, true);
}
 
/**
* Add a property that is the primary key in the database. All beans must have a primary key and you can call this method multiple times to support composite primary keys.
*
* @param name
* The bean property name
* @param dbName
* The name of the database column holding this property
* @param type
* The database type
* @return This BeanConfig (Fluent API)
*/
public BeanConfig pk(final String name, final String dbName, final DBType<? extends Object> type) {
 
return addField(name, dbName, type, true);
}
 
/**
* Return the number of fields configured for this bean. It includes the PK.
*
* @return The number of fields configured for this bean.
*/
public int getNumberOfFields() {
 
return fieldList.size();
}
 
@Override
public String toString() {
 
final StringBuilder sb = new StringBuilder(64);
 
sb.append("BeanConfig: ").append(beanClass.getName()).append(" tableName=").append(tableName);
 
return sb.toString();
}
 
/**
* Return all DBFields configured for this bean. It includes the PK as well.
*
* @return An Iterator with all DBFields configured for this bean.
*/
public Iterator<DBField> fields() {
 
return fieldList.iterator();
}
 
/**
* Check whether the primary key was defined.
*
* @return true if a primary key was defined.
*/
public boolean hasPK() {
 
return !pkList.isEmpty();
}
 
/**
* Return an iterator with the DBFields for the PK configured for this bean.
*
* Note: A bean can have more than one property as its primary key, in that case it has a composite primary key.
*
* @return An iterator with the DBFields for the PK.
*/
public Iterator<DBField> pks() {
 
return pkList.iterator();
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/util/SQLUtils.java
New file
0,0 → 1,55
package org.mentabean.util;
 
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
 
public class SQLUtils {
public static void executeScript(Connection conn, String file, String charset) {
FileInputStream fis = null;
BufferedReader br = null;
try {
 
ScriptRunner script = new ScriptRunner(conn);
fis = new FileInputStream(file);
if (charset != null) {
br = new BufferedReader(new InputStreamReader(fis, charset));
} else {
br = new BufferedReader(new InputStreamReader(fis));
}
script.runScript(br);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public static boolean checkIfTableExists(Connection conn, String tableName) {
ResultSet rset = null;
try {
DatabaseMetaData dbm = conn.getMetaData();
rset = dbm.getTables(null, null, null, new String[] { "TABLE" });
while(rset.next()) {
String tn = rset.getString("TABLE_NAME");
if (tn.equalsIgnoreCase(tableName)) return true;
}
return false;
} catch(Exception e) {
throw new RuntimeException(e);
} finally {
if (rset != null) try { rset.close(); } catch(Exception e) { e.printStackTrace(); }
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/util/FindMethod.java
New file
0,0 → 1,159
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.util;
 
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
 
/**
* Find method with polymorphism! Class.getMethod only finds an exact match.
*
* @author Jon Skeet (http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/921ab91865c8cc2e/9e141d3d62e7cb3f)
*/
public class FindMethod {
 
/**
* Finds the most specific applicable method
*
* @param source
* Class to find method in
* @param name
* Name of method to find
* @param parameterTypes
* Parameter types to search for
*/
public static Method getMethod(Class<? extends Object> source, String name, Class<? extends Object>[] parameterTypes) throws NoSuchMethodException {
return internalFind(source.getMethods(), name, parameterTypes);
}
 
/**
* Finds the most specific applicable declared method
*
* @param source
* Class to find method in
* @param name
* Name of method to find
* @param parameterTypes
* Parameter types to search for
*/
public static Method getDeclaredMethod(Class<? extends Object> source, String name, Class<? extends Object>[] parameterTypes) throws NoSuchMethodException {
return internalFind(source.getDeclaredMethods(), name, parameterTypes);
}
 
/**
* Internal method to find the most specific applicable method
*/
private static Method internalFind(Method[] toTest, String name, Class<? extends Object>[] parameterTypes) throws NoSuchMethodException {
int l = parameterTypes.length;
 
// First find the applicable methods
List<Method> applicableMethods = new LinkedList<Method>();
 
for (int i = 0; i < toTest.length; i++) {
// Check the name matches
if (!toTest[i].getName().equals(name)) {
continue;
}
// Check the parameters match
Class<? extends Object>[] params = toTest[i].getParameterTypes();
 
if (params.length != l) {
continue;
}
int j;
 
for (j = 0; j < l; j++) {
if (!params[j].isAssignableFrom(parameterTypes[j])) {
break;
}
}
// If so, add it to the list
if (j == l) {
applicableMethods.add(toTest[i]);
}
}
 
/*
* If we've got one or zero methods, we can finish the job now.
*/
int size = applicableMethods.size();
 
if (size == 0) {
throw new NoSuchMethodException("No such method: " + name);
}
if (size == 1) {
return applicableMethods.get(0);
}
 
/*
* Now find the most specific method. Do this in a very primitive way - check whether each method is maximally specific. If more than one method is maximally specific, we'll throw an exception. For a definition of maximally specific, see JLS section 15.11.2.2.
*
* I'm sure there are much quicker ways - and I could probably set the second loop to be from i+1 to size. I'd rather not though, until I'm sure...
*/
int maximallySpecific = -1; // Index of maximally specific method
 
for (int i = 0; i < size; i++) {
int j;
// In terms of the JLS, current is T
Method current = applicableMethods.get(i);
Class<? extends Object>[] currentParams = current.getParameterTypes();
Class<? extends Object> currentDeclarer = current.getDeclaringClass();
 
for (j = 0; j < size; j++) {
if (i == j) {
continue;
}
// In terms of the JLS, test is U
Method test = applicableMethods.get(j);
Class<? extends Object>[] testParams = test.getParameterTypes();
Class<? extends Object> testDeclarer = test.getDeclaringClass();
 
// Check if T is a subclass of U, breaking if not
if (!testDeclarer.isAssignableFrom(currentDeclarer)) {
break;
}
 
// Check if each parameter in T is a subclass of the
// equivalent parameter in U
int k;
 
for (k = 0; k < l; k++) {
if (!testParams[k].isAssignableFrom(currentParams[k])) {
break;
}
}
if (k != l) {
break;
}
}
// Maximally specific!
if (j == size) {
if (maximallySpecific != -1) {
throw new NoSuchMethodException("Ambiguous method search - more " + "than one maximally specific method");
}
maximallySpecific = i;
}
}
if (maximallySpecific == -1) {
throw new NoSuchMethodException("No maximally specific method.");
}
return applicableMethods.get(maximallySpecific);
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/util/InjectionUtils.java
New file
0,0 → 1,855
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.util;
 
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
 
public class InjectionUtils {
 
/**
* The character used to separate the prefix from the value name when you are using the getObject method with a prefix. You can change the value of this prefix if you want to by changing this static variable.
*
* Ex: getObject(User.class, "user") will get all values that begin with "user.".
*/
public static char PREFIX_SEPARATOR = '.';
 
private static Map<Class<? extends Object>, Map<String, Object>> settersMaps = new HashMap<Class<? extends Object>, Map<String, Object>>();
 
private static Map<Class<? extends Object>, Map<String, Object>> fieldsMaps = new HashMap<Class<? extends Object>, Map<String, Object>>();
 
public static void prepareForInjection(Class<? extends Object> klass, Map<String, Object> setters, Map<String, Object> fields) {
 
StringBuffer sb = new StringBuffer(32);
 
Method[] methods = klass.getMethods();
 
for (int i = 0; i < methods.length; i++) {
 
Method m = methods[i];
 
String name = m.getName();
 
Class<?>[] types = m.getParameterTypes();
 
if (name.startsWith("set") && name.length() > 3 && types.length == 1) {
 
String var = name.substring(3);
 
if (var.length() > 1) {
 
sb.delete(0, sb.length());
 
sb.append(var.substring(0, 1).toLowerCase());
 
sb.append(var.substring(1));
 
var = sb.toString();
 
} else {
 
var = var.toLowerCase();
}
 
m.setAccessible(true);
 
if (setters.containsKey(var)) {
 
Object obj = setters.get(var);
 
if (obj instanceof List) {
 
List<Method> list = (List<Method>) obj;
 
list.add(m);
 
} else if (obj instanceof Method) {
 
List<Method> list = new ArrayList<Method>();
 
list.add((Method) obj);
 
list.add(m);
 
setters.put(var, list);
 
}
 
} else {
 
setters.put(var, m);
 
}
}
}
 
if (fields == null) {
return;
}
 
Field[] f = klass.getDeclaredFields();
 
for (int i = 0; i < f.length; i++) {
 
Field field = f[i];
 
field.setAccessible(true);
 
String name = field.getName();
 
if (setters.containsKey(name)) {
 
Object obj = setters.get(name);
 
if (obj instanceof Method) {
 
Method m = (Method) obj;
 
Class<?>[] types = m.getParameterTypes();
 
Class<?> type = field.getType();
 
if (type.isAssignableFrom(types[0])) {
continue;
}
 
} else if (obj instanceof List) {
 
List<Method> list = (List<Method>) obj;
 
Iterator<Method> iter = list.iterator();
 
boolean found = false;
 
while (iter.hasNext()) {
 
Method m = iter.next();
 
Class<?>[] types = m.getParameterTypes();
 
Class<?> type = field.getType();
 
if (type.isAssignableFrom(types[0])) {
 
found = true;
 
break;
}
}
 
if (found) {
continue;
}
}
}
 
fields.put(name, field);
 
}
}
 
public static boolean checkPrimitives(Class<? extends Object> target, Class<? extends Object> source) {
 
if (target.equals(int.class) && source.equals(Integer.class)) {
return true;
}
 
if (target.equals(boolean.class) && source.equals(Boolean.class)) {
return true;
}
 
if (target.equals(byte.class) && source.equals(Byte.class)) {
return true;
}
 
if (target.equals(short.class) && source.equals(Short.class)) {
return true;
}
 
if (target.equals(char.class) && source.equals(Character.class)) {
return true;
}
 
if (target.equals(long.class) && source.equals(Long.class)) {
return true;
}
 
if (target.equals(float.class) && source.equals(Float.class)) {
return true;
}
 
if (target.equals(double.class) && source.equals(Double.class)) {
return true;
}
 
return false;
 
}
 
public static Object tryToConvert(Object source, Class<? extends Object> targetType) {
 
return tryToConvert(source, targetType, false);
}
 
public static Object tryToConvert(Object source, Class<?> targetType, boolean tryNumber) {
 
String value = null;
 
if (source instanceof String) {
 
value = (String) source;
 
} else if (tryNumber && source instanceof Number) {
 
value = source.toString();
 
} else {
 
return null;
}
 
Object newValue = null;
 
String className = targetType.getName();
 
if (className.equals("int") || className.equals("java.lang.Integer")) {
int x = -1;
try {
x = Integer.parseInt(value);
} catch (Exception e) {
return null;
}
newValue = new Integer(x);
} else if (className.equals("short") || className.equals("java.lang.Short")) {
short x = -1;
try {
x = Short.parseShort(value);
} catch (Exception e) {
return null;
}
newValue = new Short(x);
 
} else if (className.equals("char") || className.equals("java.lang.Character")) {
 
if (value.length() != 1) {
return null;
}
 
newValue = new Character(value.charAt(0));
 
} else if (className.equals("long") || className.equals("java.lang.Long")) {
long x = -1;
try {
x = Long.parseLong(value);
} catch (Exception e) {
return null;
}
newValue = new Long(x);
} else if (className.equals("float") || className.equals("java.lang.Float")) {
float x = -1;
try {
x = Float.parseFloat(value);
} catch (Exception e) {
return null;
}
newValue = new Float(x);
} else if (className.equals("double") || className.equals("java.lang.Double")) {
double x = -1;
try {
x = Double.parseDouble(value);
} catch (Exception e) {
return null;
}
newValue = new Double(x);
} else if (className.equals("boolean") || className.equals("java.lang.Boolean")) {
try {
int x = Integer.parseInt(value);
if (x == 1) {
newValue = Boolean.TRUE;
} else if (x == 0) {
newValue = Boolean.FALSE;
} else {
return null;
}
} catch (Exception e) {
if (value.equalsIgnoreCase("true") || value.equals("on")) {
newValue = Boolean.TRUE;
} else if (value.equalsIgnoreCase("false")) {
newValue = Boolean.FALSE;
} else {
return null;
}
}
} else if (targetType.isEnum()) {
 
try {
 
Class k = targetType; // not sure how to avoid this raw type!
 
newValue = Enum.valueOf(k, value);
 
} catch (Exception e) {
 
return null;
}
 
}
 
return newValue;
 
}
 
public static Object shouldConvertToNull(Object value, Class<? extends Object> targetType) {
 
if (targetType.equals(String.class)) {
 
return value;
 
} else if (targetType.isPrimitive()) {
 
return value;
}
 
return null;
}
 
public static Class<? extends Object> getPrimitiveFrom(Object w) {
if (w instanceof Boolean) {
return Boolean.TYPE;
} else if (w instanceof Byte) {
return Byte.TYPE;
} else if (w instanceof Short) {
return Short.TYPE;
} else if (w instanceof Character) {
return Character.TYPE;
} else if (w instanceof Integer) {
return Integer.TYPE;
} else if (w instanceof Long) {
return Long.TYPE;
} else if (w instanceof Float) {
return Float.TYPE;
} else if (w instanceof Double) {
return Double.TYPE;
}
return null;
}
 
public static Class<? extends Object> getPrimitiveFrom(Class<? extends Object> klass) {
 
String s = klass.getName();
 
if (s.equals("java.lang.Boolean")) {
return Boolean.TYPE;
} else if (s.equals("java.lang.Byte")) {
return Byte.TYPE;
} else if (s.equals("java.lang.Short")) {
return Short.TYPE;
} else if (s.equals("java.lang.Character")) {
return Character.TYPE;
} else if (s.equals("java.lang.Integer")) {
return Integer.TYPE;
} else if (s.equals("java.lang.Long")) {
return Long.TYPE;
} else if (s.equals("java.lang.Float")) {
return Float.TYPE;
} else if (s.equals("java.lang.Double")) {
return Double.TYPE;
}
return null;
}
 
public static Field getField(Object target, String name) {
return getField(target.getClass(), name);
}
 
public static Field getField(Class<? extends Object> target, String name) {
Field fields[] = target.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (name.equals(fields[i].getName())) {
return fields[i];
}
}
return null;
}
 
public static Method findMethodToGet(Class<? extends Object> target, String name) {
 
StringBuffer sb = new StringBuffer(128);
 
sb.append("get").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) {
sb.append(name.substring(1));
}
 
try {
 
return target.getMethod(sb.toString(), (Class[]) null);
 
} catch (Exception e) {
 
}
 
sb.setLength(0);
 
sb.append("is").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) {
 
sb.append(name.substring(1));
}
 
try {
 
return target.getMethod(sb.toString(), (Class[]) null);
 
} catch (Exception e) {
 
}
 
return null;
}
 
public static Method findMethodToInject(Class<? extends Object> target, String name, Class<? extends Object> source) {
 
StringBuffer sb = new StringBuffer(128);
 
sb.append("set").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) {
sb.append(name.substring(1));
}
 
String methodName = sb.toString();
 
Method m = null;
 
try {
 
m = FindMethod.getMethod(target, methodName, new Class[] { source });
 
} catch (Exception e) {
}
 
if (m == null) {
 
Class<? extends Object> primitive = getPrimitiveFrom(source);
 
if (primitive != null) {
 
try {
 
m = target.getMethod(methodName, new Class[] { primitive });
 
} catch (Exception e) {
}
 
}
}
 
if (m != null) {
m.setAccessible(true);
}
 
return m;
 
}
 
public static Field findFieldToInject(Class<? extends Object> target, String name, Class<? extends Object> source) {
 
Field f = getField(target, name);
 
if (f != null) {
 
Class<?> type = f.getType();
 
if (type.isAssignableFrom(source) || checkPrimitives(type, source)) {
 
f.setAccessible(true);
 
return f;
}
 
}
 
return null;
}
 
private static final boolean isBlank(Object value) {
 
if (value != null && value instanceof String) {
 
String s = ((String) value).trim();
 
if (s.length() == 0) {
return true;
}
}
 
return false;
}
 
public static boolean inject(Method m, Object target, Object value, boolean tryToConvert, boolean tryingToConvertBoolean) throws Exception {
 
Class<?> type = m.getParameterTypes()[0];
 
if (tryingToConvertBoolean) {
 
if (value == null && (type.equals(Boolean.class) || type.equals(boolean.class))) {
 
value = Boolean.FALSE;
 
} else {
 
// if trying to convert boolean, convert or don't do anything...
 
return false;
 
}
}
 
if (value == null || (type.isAssignableFrom(value.getClass()) || checkPrimitives(type, value.getClass()) || (tryToConvert && ((isBlank(value) && (value = shouldConvertToNull(value, type)) == null) || (value = tryToConvert(value, type)) != null)))) {
 
try {
 
m.invoke(target, new Object[] { value });
 
return true;
 
} catch (Exception e) {
 
System.err.println("Error injecting by method: " + value + " in " + target + " thru " + m);
 
e.printStackTrace();
 
throw e;
 
}
}
 
return false;
 
}
 
public static boolean hasDefaultConstructor(Class<? extends Object> klass) {
 
try {
 
return klass.getConstructor((Class[]) null) != null;
 
} catch (Exception e) {
 
return false;
}
}
 
/**
* Extract the value of a property of a bean!
*
* @param bean
* the target bean
* @param nameProperty
* the property name
* @return they value as String. The method toString is always called to every property!
* @throws Exception
*/
public static String getProperty(Object bean, String nameProperty) throws Exception {
 
if (nameProperty == null || nameProperty.equals("")) {
return null;
}
 
String methodName = getter(nameProperty);
 
Class<? extends Object> clazz = bean.getClass();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getName().equals(methodName) && method.getParameterTypes().length == 0) {
Object value = method.invoke(bean, (Object[]) null);
if (value == null) {
return null;
}
return value.toString();
}
}
 
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.getName().equals(nameProperty)) {
Object value = field.get(bean);
if (value == null) {
return null;
}
return value.toString();
}
}
 
return null;
}
 
private static String getter(String name) {
StringBuilder sb = new StringBuilder(name.length() + 3);
 
sb.append("get").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) {
sb.append(name.substring(1));
}
return sb.toString();
}
 
public static void beanToMap(Object bean, Map<String, String> map) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
if (bean != null) {
 
for (Method method : bean.getClass().getMethods()) {
String name = method.getName();
 
if (name.length() > 3 && name.startsWith("get") && !name.equals("getClass") && method.getParameterTypes().length == 0) {
 
method.setAccessible(true);
Object value = method.invoke(bean, new Object[0]);
map.put(name, value.toString());
}
}
}
}
 
public static interface Provider {
 
public Object get(String key);
 
public boolean hasValue(String key);
}
 
public static void getObject(Object target, Provider provider, boolean tryField, String prefix, boolean tryToConvert, boolean convertBoolean, boolean allowRecursion) throws Exception {
 
Class<? extends Object> targetClass = target.getClass();
 
Map<String, Object> setters, fields;
 
// see if we have these in cache...
 
synchronized (settersMaps) {
 
setters = settersMaps.get(targetClass);
 
fields = fieldsMaps.get(targetClass);
 
}
 
// if not in cache, prepare maps for injection...
 
if (setters == null) {
 
setters = new HashMap<String, Object>();
 
fields = null;
 
if (tryField) {
 
fields = new HashMap<String, Object>();
 
}
 
prepareForInjection(targetClass, setters, fields);
 
synchronized (settersMaps) {
 
settersMaps.put(targetClass, setters);
 
fieldsMaps.put(targetClass, fields);
 
}
}
 
Iterator<String> iter = setters.keySet().iterator();
 
while (iter.hasNext()) {
 
String var = iter.next();
 
boolean hasValue = provider.hasValue(var);
 
Object value = provider.get(var);
 
boolean tryingToConvertBoolean = false;
 
if (value == null && !hasValue) {
 
if (!convertBoolean) {
 
continue;
 
} else {
 
tryingToConvertBoolean = true;
}
 
}
 
// if (value == null) continue;
 
Object obj = setters.get(var);
 
// we may have a list of overloaded methods...
 
List<Method> list = null;
 
Method m = null;
 
if (obj instanceof List) {
 
list = (List<Method>) obj;
 
} else {
 
m = (Method) setters.get(var);
 
}
 
if (m != null) {
 
if (!inject(m, target, value, tryToConvert, tryingToConvertBoolean) && allowRecursion) {
 
// i did not inject... how about a VO object for this
// setter?
 
Class<?> type = m.getParameterTypes()[0];
 
if (!type.getName().startsWith("java.") && !type.isPrimitive() && hasDefaultConstructor(type)) {
 
Object param = type.newInstance();
 
InjectionUtils.getObject(param, provider, true, prefix, true, true, false); // no
// recursion...
 
inject(m, target, param, false, false);
}
}
 
} else {
 
Iterator<Method> it = list.iterator();
 
boolean injected = false;
 
while (it.hasNext()) {
 
m = it.next();
 
if (inject(m, target, value, tryToConvert, tryingToConvertBoolean)) {
 
injected = true;
 
break;
}
}
 
if (!injected && allowRecursion) {
 
// i could not inject anything... how about a VO object for
// this setter...
 
it = list.iterator();
 
while (it.hasNext()) {
 
m = it.next();
 
Class<?> type = m.getParameterTypes()[0];
 
if (!type.getName().startsWith("java.") && !type.isPrimitive() && hasDefaultConstructor(type)) {
 
Object param = type.newInstance();
 
InjectionUtils.getObject(param, provider, true, prefix, true, true, false); // no
// recursion...
 
if (inject(m, target, param, false, false)) {
 
break; // done...
}
}
}
}
}
}
 
if (fields != null) {
 
iter = fields.keySet().iterator();
 
while (iter.hasNext()) {
 
String var = iter.next();
 
boolean hasValue = provider.hasValue(var);
 
Object value = provider.get(var);
 
Field f = (Field) fields.get(var);
 
Class<?> type = f.getType();
 
// If there is no value in the action input, assume false for
// booleans...
// (checkboxes and radio buttons are not send when not
// marked...)
 
if (convertBoolean && value == null && !hasValue) {
 
if (type.equals(Boolean.class) || type.equals(boolean.class)) {
 
value = Boolean.FALSE;
}
 
}
 
if (value == null && !hasValue) {
continue;
}
 
// if (value == null) continue;
 
if (value == null || (type.isAssignableFrom(value.getClass()) || checkPrimitives(type, value.getClass()) || (tryToConvert && ((isBlank(value) && (value = shouldConvertToNull(value, type)) == null) || (value = tryToConvert(value, type)) != null)))) {
 
try {
 
f.set(target, value);
 
} catch (Exception e) {
 
System.err.println("Error injecting by field: " + value + " in " + target);
 
e.printStackTrace();
 
throw e;
 
}
}
}
}
}
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/util/FindConstructor.java
New file
0,0 → 1,152
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.util;
 
import java.lang.reflect.Constructor;
import java.util.LinkedList;
import java.util.List;
 
/**
* Find constructor with polymorphism! Class.getConstructor only finds an exact match.
*
* @author Jon Skeet (http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/921ab91865c8cc2e/9e141d3d62e7cb3f)
*/
public class FindConstructor {
 
/**
* Finds the most specific applicable constructor
*
* @param source
* Class to find a constructor for
* @param parameterTypes
* Parameter types to search for
*/
public static Constructor<? extends Object> getConstructor(Class<? extends Object> source, Class<? extends Object>[] parameterTypes) throws NoSuchMethodException {
return internalFind(source.getConstructors(), parameterTypes);
}
 
/**
* Finds the most specific applicable declared constructor
*
* @param source
* Class to find method in
* @param parameterTypes
* Parameter types to search for
*/
public static Constructor<? extends Object> getDeclaredConstructor(Class<? extends Object> source, Class<? extends Object>[] parameterTypes) throws NoSuchMethodException {
return internalFind(source.getDeclaredConstructors(), parameterTypes);
}
 
/**
* Internal method to find the most specific applicable method
*/
private static Constructor<? extends Object> internalFind(Constructor<? extends Object>[] toTest, Class<? extends Object>[] parameterTypes) throws NoSuchMethodException {
 
int l = parameterTypes.length;
 
// First find the applicable methods
List<Constructor<? extends Object>> applicableMethods = new LinkedList<Constructor<? extends Object>>();
 
for (int i = 0; i < toTest.length; i++) {
// Check the parameters match
Class<? extends Object>[] params = toTest[i].getParameterTypes();
 
if (params.length != l) {
continue;
}
int j;
 
for (j = 0; j < l; j++) {
if (!params[j].isAssignableFrom(parameterTypes[j])) {
break;
}
}
// If so, add it to the list
if (j == l) {
applicableMethods.add(toTest[i]);
}
}
 
/*
* If we've got one or zero methods, we can finish the job now.
*/
int size = applicableMethods.size();
 
if (size == 0) {
throw new NoSuchMethodException("No such constructor!");
}
if (size == 1) {
return applicableMethods.get(0);
}
 
/*
* Now find the most specific method. Do this in a very primitive way - check whether each method is maximally specific. If more than one method is maximally specific, we'll throw an exception. For a definition of maximally specific, see JLS section 15.11.2.2.
*
* I'm sure there are much quicker ways - and I could probably set the second loop to be from i+1 to size. I'd rather not though, until I'm sure...
*/
int maximallySpecific = -1; // Index of maximally specific method
 
for (int i = 0; i < size; i++) {
int j;
// In terms of the JLS, current is T
Constructor<? extends Object> current = applicableMethods.get(i);
Class<? extends Object>[] currentParams = current.getParameterTypes();
Class<? extends Object> currentDeclarer = current.getDeclaringClass();
 
for (j = 0; j < size; j++) {
if (i == j) {
continue;
}
// In terms of the JLS, test is U
Constructor<? extends Object> test = applicableMethods.get(j);
Class<? extends Object>[] testParams = test.getParameterTypes();
Class<? extends Object> testDeclarer = test.getDeclaringClass();
 
// Check if T is a subclass of U, breaking if not
if (!testDeclarer.isAssignableFrom(currentDeclarer)) {
break;
}
 
// Check if each parameter in T is a subclass of the
// equivalent parameter in U
int k;
 
for (k = 0; k < l; k++) {
if (!testParams[k].isAssignableFrom(currentParams[k])) {
break;
}
}
if (k != l) {
break;
}
}
// Maximally specific!
if (j == size) {
if (maximallySpecific != -1) {
throw new NoSuchMethodException("Ambiguous method search - more " + "than one maximally specific method");
}
maximallySpecific = i;
}
}
if (maximallySpecific == -1) {
throw new NoSuchMethodException("No maximally specific method.");
}
return applicableMethods.get(maximallySpecific);
}
 
}
/tags/menta-bean-0.9.4/src/main/java/org/mentabean/util/ScriptRunner.java
New file
0,0 → 1,302
/*
* Added additional null checks when closing the ResultSet and Statements.
*
* Thanks to pihug12 and Grzegorz Oledzki at stackoverflow.com
* http://stackoverflow.com/questions/5332149/jdbc-scriptrunner-java-lang-nullpointerexception?tab=active#tab-top
*/
/*
* Modified: Use logWriter in print(Object), JavaDoc comments, correct Typo.
*/
/*
* Modified by Pantelis Sopasakis <chvng@mail.ntua.gr> to take care of DELIMITER statements. This way you
* can execute scripts that contain some TRIGGER creation code. New version using REGEXPs! Latest
* modification: Cater for a NullPointerException while parsing. Date: Feb 16, 2011, 11:48 EET
*/
/*
* Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class from the iBATIS Apache
* project. Only removed dependency on Resource class and a constructor
*/
/*
* Copyright 2004 Clinton Begin Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package org.mentabean.util;
 
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
* Tool to run database scripts. This version of the script can be found at
* https://gist.github.com/gists/831762/
*/
public class ScriptRunner {
 
private static final String DEFAULT_DELIMITER = ";";
private static final String DELIMITER_LINE_REGEX = "(?i)DELIMITER.+";
private static final String DELIMITER_LINE_SPLIT_REGEX = "(?i)DELIMITER";
 
private final Connection connection;
private final boolean stopOnError;
private final boolean autoCommit;
private PrintWriter logWriter = new PrintWriter(System.out);
private PrintWriter errorLogWriter = new PrintWriter(System.err);
private String delimiter = DEFAULT_DELIMITER;
private boolean fullLineDelimiter = false;
 
/**
* Default constructor.
*
* @param connection
* @param autoCommit
* @param stopOnError
*/
public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) {
this.connection = connection;
this.autoCommit = autoCommit;
this.stopOnError = stopOnError;
}
public ScriptRunner(Connection conn) {
this(conn, false, true);
setLogWriter(null);
setErrorLogWriter(null);
}
 
/**
* @param delimiter
* @param fullLineDelimiter
*/
public void setDelimiter(String delimiter, boolean fullLineDelimiter) {
this.delimiter = delimiter;
this.fullLineDelimiter = fullLineDelimiter;
}
 
/**
* Setter for logWriter property.
*
* @param logWriter
* - the new value of the logWriter property
*/
public void setLogWriter(PrintWriter logWriter) {
this.logWriter = logWriter;
}
 
/**
* Setter for errorLogWriter property.
*
* @param errorLogWriter
* - the new value of the errorLogWriter property
*/
public void setErrorLogWriter(PrintWriter errorLogWriter) {
this.errorLogWriter = errorLogWriter;
}
 
/**
* Runs an SQL script (read in using the Reader parameter).
*
* @param reader
* - the source of the script
* @throws SQLException
* if any SQL errors occur
* @throws IOException
* if there is an error reading from the Reader
*/
public void runScript(Reader reader) throws IOException, SQLException {
try {
boolean originalAutoCommit = connection.getAutoCommit();
try {
if (originalAutoCommit != autoCommit) {
connection.setAutoCommit(autoCommit);
}
runScript(connection, reader);
} finally {
connection.setAutoCommit(originalAutoCommit);
}
} catch (IOException e) {
throw e;
} catch (SQLException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Error running script. Cause: " + e, e);
}
}
 
/**
* Runs an SQL script (read in using the Reader parameter) using the connection passed in.
*
* @param conn
* - the connection to use for the script
* @param reader
* - the source of the script
* @throws SQLException
* if any SQL errors occur
* @throws IOException
* if there is an error reading from the Reader
*/
private void runScript(Connection conn, Reader reader) throws IOException, SQLException {
StringBuffer command = null;
try {
LineNumberReader lineReader = new LineNumberReader(reader);
String line = null;
while ((line = lineReader.readLine()) != null) {
if (command == null) {
command = new StringBuffer();
}
String trimmedLine = line.trim();
if (trimmedLine.startsWith("--")) {
println(trimmedLine);
} else if (trimmedLine.length() < 1 || trimmedLine.startsWith("//")) {
// Do nothing
} else if (trimmedLine.length() < 1 || trimmedLine.startsWith("--")) {
// Do nothing
} else if (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter())
|| fullLineDelimiter && trimmedLine.equals(getDelimiter())) {
 
Pattern pattern = Pattern.compile(DELIMITER_LINE_REGEX);
Matcher matcher = pattern.matcher(trimmedLine);
if (matcher.matches()) {
setDelimiter(trimmedLine.split(DELIMITER_LINE_SPLIT_REGEX)[1].trim(),
fullLineDelimiter);
line = lineReader.readLine();
if (line == null) {
break;
}
trimmedLine = line.trim();
}
 
command.append(line.substring(0, line.lastIndexOf(getDelimiter())));
command.append(" ");
Statement statement = conn.createStatement();
 
println(command);
 
boolean hasResults = false;
if (stopOnError) {
hasResults = statement.execute(command.toString());
} else {
try {
statement.execute(command.toString());
} catch (SQLException e) {
e.fillInStackTrace();
printlnError("Error executing: " + command);
printlnError(e);
}
}
 
if (autoCommit && !conn.getAutoCommit()) {
conn.commit();
}
 
ResultSet rs = statement.getResultSet();
if (hasResults && rs != null) {
ResultSetMetaData md = rs.getMetaData();
int cols = md.getColumnCount();
for (int i = 0; i < cols; i++) {
String name = md.getColumnLabel(i);
print(name + "\t");
}
println("");
while (rs.next()) {
for (int i = 1; i <= cols; i++) {
String value = rs.getString(i);
print(value + "\t");
}
println("");
}
}
 
command = null;
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (statement != null) {
statement.close();
}
} catch (Exception e) {
e.printStackTrace();
// Ignore to workaround a bug in Jakarta DBCP
}
} else {
Pattern pattern = Pattern.compile(DELIMITER_LINE_REGEX);
Matcher matcher = pattern.matcher(trimmedLine);
if (matcher.matches()) {
setDelimiter(trimmedLine.split(DELIMITER_LINE_SPLIT_REGEX)[1].trim(),
fullLineDelimiter);
line = lineReader.readLine();
if (line == null) {
break;
}
trimmedLine = line.trim();
}
command.append(line);
command.append(" ");
}
}
if (!autoCommit) {
conn.commit();
}
} catch (SQLException e) {
e.fillInStackTrace();
printlnError("Error executing: " + command);
printlnError(e);
throw e;
} catch (IOException e) {
e.fillInStackTrace();
printlnError("Error executing: " + command);
printlnError(e);
throw e;
} finally {
conn.rollback();
flush();
}
}
 
private String getDelimiter() {
return delimiter;
}
 
private void print(Object o) {
if (logWriter != null) {
logWriter.print(o);
}
}
 
private void println(Object o) {
if (logWriter != null) {
logWriter.println(o);
}
}
 
private void printlnError(Object o) {
if (errorLogWriter != null) {
errorLogWriter.println(o);
}
}
 
private void flush() {
if (logWriter != null) {
logWriter.flush();
}
if (errorLogWriter != null) {
errorLogWriter.flush();
}
}
}
/tags/menta-bean-0.9.4/LICENSE-lgpl-3.0.txt
New file
0,0 → 1,165
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
 
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
 
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
 
0. Additional Definitions.
 
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
 
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
 
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
 
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
 
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
 
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
 
1. Exception to Section 3 of the GNU GPL.
 
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
 
2. Conveying Modified Versions.
 
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
 
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
 
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
 
3. Object Code Incorporating Material from Library Header Files.
 
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
 
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
 
b) Accompany the object code with a copy of the GNU GPL and this license
document.
 
4. Combined Works.
 
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
 
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
 
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
 
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
 
d) Do one of the following:
 
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
 
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
 
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
 
5. Combined Libraries.
 
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
 
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
 
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
 
6. Revised Versions of the GNU Lesser General Public License.
 
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
 
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
 
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
/tags/menta-bean-0.9.4/pom.xml
New file
0,0 → 1,411
<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>
<artifactId>oss-parent</artifactId>
<groupId>org.sonatype.oss</groupId>
<version>3</version>
</parent>
<groupId>me.soliveirajr</groupId>
<artifactId>menta-bean</artifactId>
<version>0.9.4</version>
<name>MentaBean</name>
<description>An query helper and simple CRUD ORM.</description>
<url>http://maven.apache.org</url>
<licenses>
<license>
<name>GNU Lesser General Public License (LGPL), Version 2.1</name>
<url>http://www.fsf.org/licensing/licenses/lgpl.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<connection>scm:svn:svn://soliveirajr.com/mentabean/tags/menta-bean-0.9.4</connection>
<developerConnection>scm:svn:svn://soliveirajr.com/mentabean/tags/menta-bean-0.9.4</developerConnection>
<url>svn://soliveirajr.com/mentabean/tags/menta-bean-0.9.4</url>
</scm>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<properties>
<build.final.name>mentabean</build.final.name>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<svn.tags>svn://soliveirajr.com/mentabean/tags</svn.tags>
<svn.url>svn://soliveirajr.com/mentabean/trunk</svn.url>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.2.138</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Repository Switchboard</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Plugin Repository</name>
<url>http://repo1.maven.org/maven2</url>
</pluginRepository>
</pluginRepositories>
<build>
<finalName>mentabean</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0</version>
<configuration>
<mavenExecutorId>forked-path</mavenExecutorId>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
</executions>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0</version>
<configuration>
<tagBase>svn://soliveirajr.com/mentabean/tags</tagBase>
<connectionUrl>scm:svn:svn://soliveirajr.com/mentabean/trunk</connectionUrl>
<mavenExecutorId>forked-path</mavenExecutorId>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>default-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
<execution>
<id>default-testResources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>2.0.1</version>
<executions>
<execution>
<id>default-site</id>
<phase>site</phase>
<goals>
<goal>site</goal>
</goals>
<configuration>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>...</configuration>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
<execution>
<id>default-deploy</id>
<phase>site-deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>...</configuration>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
</executions>
<configuration>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>...</configuration>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
</plugin>
</plugins>
</reporting>
<profiles>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
/menta-bean-0.9.4
Property changes:
Added: svn:ignore
+ .settings
.classpath
.project
target