public Document getUserLayout (IPerson person, UserProfile profile) throws Exception {
int userId = person.getID();
int realUserId = userId;
ResultSet rs;
Connection con = RDBMServices.getConnection();
LocaleManager localeManager = profile.getLocaleManager();
RDBMServices.setAutoCommit(con, false); // May speed things up, can't hurt
try {
Document doc = DocumentFactory.getNewDocument();
Element root = doc.createElement("layout");
Statement stmt = con.createStatement();
// A separate statement is needed so as not to interfere with ResultSet
// of statements used for queries
Statement insertStmt = con.createStatement();
try {
long startTime = System.currentTimeMillis();
// eventually, we need to fix template layout implementations so you can just do this:
// int layoutId=profile.getLayoutId();
// but for now:
int layoutId = this.getLayoutID(userId, profile.getProfileId());
if (layoutId == 0) { // First time, grab the default layout for this user
String sQuery = "SELECT USER_DFLT_USR_ID, USER_DFLT_LAY_ID FROM UP_USER WHERE USER_ID=" + userId;
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sQuery);
rs = stmt.executeQuery(sQuery);
try {
rs.next();
userId = rs.getInt(1);
layoutId = rs.getInt(2);
} finally {
rs.close();
}
// Make sure the next struct id is set in case the user adds a channel
sQuery = "SELECT NEXT_STRUCT_ID FROM UP_USER WHERE USER_ID=" + userId;
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sQuery);
int nextStructId;
rs = stmt.executeQuery(sQuery);
try {
rs.next();
nextStructId = rs.getInt(1);
} finally {
rs.close();
}
int realNextStructId = 0;
if (realUserId != userId) {
// But never make the existing value SMALLER, change it only to make it LARGER
// (so, get existing value)
sQuery = "SELECT NEXT_STRUCT_ID FROM UP_USER WHERE USER_ID=" + realUserId;
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sQuery);
rs = stmt.executeQuery(sQuery);
try {
rs.next();
realNextStructId = rs.getInt(1);
} finally {
rs.close();
}
}
if (nextStructId > realNextStructId) {
sQuery = "UPDATE UP_USER SET NEXT_STRUCT_ID=" + nextStructId + " WHERE USER_ID=" + realUserId;
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sQuery);
stmt.executeUpdate(sQuery);
}
RDBMServices.commit(con); // Make sure it appears in the store
}
int firstStructId = -1;
//Flags to enable a default layout lookup if it's needed
boolean foundLayout = false;
boolean triedDefault = false;
//This loop is used to ensure a layout is found for a user. It tries
//looking up the layout for the current userID. If one isn't found
//the userID is replaced with the template user ID for this user and
//the layout is searched for again. This loop should only ever loop once.
do {
String sQuery = "SELECT INIT_STRUCT_ID FROM UP_USER_LAYOUT WHERE USER_ID=" + userId + " AND LAYOUT_ID = " + layoutId;
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sQuery);
rs = stmt.executeQuery(sQuery);
try {
if (rs.next()) {
firstStructId = rs.getInt(1);
} else {
throw new Exception("RDBMUserLayoutStore::getUserLayout(): No INIT_STRUCT_ID in UP_USER_LAYOUT for " + userId + " and LAYOUT_ID " + layoutId);
}
} finally {
rs.close();
}
String sql;
if (localeAware) {
// This needs to be changed to get the localized strings
sql = "SELECT ULS.STRUCT_ID,ULS.NEXT_STRUCT_ID,ULS.CHLD_STRUCT_ID,ULS.CHAN_ID,ULS.NAME,ULS.TYPE,ULS.HIDDEN,"+
"ULS.UNREMOVABLE,ULS.IMMUTABLE";
} else {
sql = "SELECT ULS.STRUCT_ID,ULS.NEXT_STRUCT_ID,ULS.CHLD_STRUCT_ID,ULS.CHAN_ID,ULS.NAME,ULS.TYPE,ULS.HIDDEN,"+
"ULS.UNREMOVABLE,ULS.IMMUTABLE";
}
if (RDBMServices.getDbMetaData().supportsOuterJoins()) {
sql += ",USP.STRUCT_PARM_NM,USP.STRUCT_PARM_VAL FROM " + RDBMServices.getDbMetaData().getJoinQuery().getQuery("layout");
} else {
sql += " FROM UP_LAYOUT_STRUCT ULS WHERE ";
}
sql += " ULS.USER_ID=" + userId + " AND ULS.LAYOUT_ID=" + layoutId + " ORDER BY ULS.STRUCT_ID";
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sql);
rs = stmt.executeQuery(sql);
//check for rows in the result set
foundLayout = rs.next();
if (!foundLayout && !triedDefault && userId == realUserId) {
//If we didn't find any rows and we haven't tried the default user yet
triedDefault = true;
rs.close();
//Get the default user ID and layout ID
sQuery = "SELECT USER_DFLT_USR_ID, USER_DFLT_LAY_ID FROM UP_USER WHERE USER_ID=" + userId;
if (log.isDebugEnabled())
log.debug("RDBMUserLayoutStore::getUserLayout(): " + sQuery);
rs = stmt.executeQuery(sQuery);
try {
rs.next();
userId = rs.getInt(1);
layoutId = rs.getInt(2);
} finally {
rs.close();
}
}
else {
//We tried the default or actually found a layout
break;
}
} while (!foundLayout);
HashMap layoutStructure = new HashMap();
StringBuffer structChanIds = new StringBuffer();
try {
int lastStructId = 0;
LayoutStructure ls = null;
String sepChar = "";
if (foundLayout) {
int structId = rs.getInt(1);
// Result Set returns 0 by default if structId was null
// Except if you are using poolman 2.0.4 in which case you get -1 back
if (rs.wasNull()) {
structId = 0;
}
readLayout: while (true) {
if (DEBUG > 1) System.err.println("Found layout structureID " + structId);
int nextId = rs.getInt(2);
if (rs.wasNull()) {
nextId = 0;
}
int childId = rs.getInt(3);
if (rs.wasNull()) {
childId = 0;
}
int chanId = rs.getInt(4);
if (rs.wasNull()) {
chanId = 0;
}
String temp5=rs.getString(5); // Some JDBC drivers require columns accessed in order
String temp6=rs.getString(6); // Access 5 and 6 now, save till needed.
// uPortal i18n
int name_index, value_index;
if (localeAware) {
ls = new LayoutStructure(structId, nextId, childId, chanId, rs.getString(7),rs.getString(8),rs.getString(9),localeManager.getLocales()[0].toString());
name_index=10;
value_index=11;
} else {
ls = new LayoutStructure(structId, nextId, childId, chanId, rs.getString(7),rs.getString(8),rs.getString(9));
name_index=10;