}
});
}
protected Document getPersonalUserLayout (final IPerson person, final IUserProfile profile) {
final LocaleManager localeManager = profile.getLocaleManager();
return jdbcOperations.execute(new ConnectionCallback<Document>() {
@Override
public Document doInConnection(Connection con) throws SQLException, DataAccessException {
ResultSet rs;
int userId = person.getID();
final int realUserId = userId;
Document doc = DocumentFactory.getThreadDocument();
Element root = doc.createElement("layout");
final 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 = getLayoutID(userId, profile.getProfileId());
if (layoutId == 0) { // First time, grab the default layout for this user
final Tuple<Integer, Integer> userLayoutIds = transactionOperations.execute(new TransactionCallback<Tuple<Integer, Integer>>() {
@Override
public Tuple<Integer, Integer> doInTransaction(TransactionStatus status) {
return jdbcOperations.execute(new ConnectionCallback<Tuple<Integer, Integer>>() {
@Override
public Tuple<Integer, Integer> doInConnection(Connection con) throws SQLException, DataAccessException {
int newLayoutId;
int newUserId;
String sQuery = "SELECT USER_DFLT_USR_ID, USER_DFLT_LAY_ID FROM UP_USER WHERE USER_ID=" + realUserId;
logger.debug("getUserLayout(): {}", sQuery);
ResultSet rs = stmt.executeQuery(sQuery);
try {
boolean hasRow = rs.next();
newUserId = rs.getInt(1);
newLayoutId = 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=" + newUserId;
logger.debug("getUserLayout(): {}", sQuery);
int nextStructId;
rs = stmt.executeQuery(sQuery);
try {
boolean hasRow = rs.next();
nextStructId = rs.getInt(1);
} finally {
rs.close();
}
int realNextStructId = 0;
if (realUserId != newUserId) {
// 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;
logger.debug("getUserLayout(): {}", sQuery);
rs = stmt.executeQuery(sQuery);
try {
boolean hasRow = 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;
logger.debug("getUserLayout(): {}", sQuery);
stmt.executeUpdate(sQuery);
}
return new Tuple<Integer, Integer>(newUserId, newLayoutId);
}
});
}
});
userId = userLayoutIds.first;
layoutId = userLayoutIds.second;
}
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;
logger.debug("getUserLayout(): {}", sQuery);
rs = stmt.executeQuery(sQuery);
try {
if (rs.next()) {
firstStructId = rs.getInt(1);
} else {
throw new RuntimeException("getUserLayout(): No INIT_STRUCT_ID in UP_USER_LAYOUT for USER_ID: " + 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 (databaseMetadata.supportsOuterJoins()) {
sql += ",USP.STRUCT_PARM_NM,USP.STRUCT_PARM_VAL FROM " + databaseMetadata.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";
logger.debug("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;
logger.debug("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) {
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) {
Locale[] locales = localeManager.getLocales();
String locale = locales[0].toString();
ls = new LayoutStructure(
structId, nextId, childId, chanId,
rs.getString(7),rs.getString(8),rs.getString(9),
locale);