changeset 43:9dbbbfd474f4

new: 1.existing topic in search result. 2.difference-set of book for topic
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Wed, 23 Dec 2015 16:03:32 +0100
parents 815cd86bb9ec
children 89d1076df1c3
files src/main/java/de/mpiwg/gazetteer/bo/LGTopic.java src/main/java/de/mpiwg/gazetteer/bo/LGTopicSectionRelation.java src/main/java/de/mpiwg/gazetteer/db/DBBook.java src/main/java/de/mpiwg/gazetteer/db/DBSection.java src/main/java/de/mpiwg/gazetteer/utils/DBService.java src/main/java/de/mpiwg/gazetteer/utils/DataProvider.java src/main/java/de/mpiwg/web/jsp/ApplicationBean.java src/main/java/de/mpiwg/web/jsp/JSPProxy.java src/main/java/de/mpiwg/web/jsp/SearchPage.java src/main/java/de/mpiwg/web/jsp/SessionBean.java src/main/java/de/mpiwg/web/jsp/TopicListPage.java src/main/java/de/mpiwg/web/jsp/TopicPage.java src/main/webapp/methods/addSectionToTopic.jsp src/main/webapp/methods/getDataverseForm.jsp src/main/webapp/pages/branchPage.jsp src/main/webapp/pages/search.jsp src/main/webapp/pages/topicList.jsp src/main/webapp/pages/topicPage.jsp
diffstat 18 files changed, 602 insertions(+), 226 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/de/mpiwg/gazetteer/bo/LGTopic.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/gazetteer/bo/LGTopic.java	Wed Dec 23 16:03:32 2015 +0100
@@ -46,6 +46,9 @@
 	@Column(name="description")
 	private String description;
 
+	@Column(name="keywords")
+	private String keywords;
+
 	
 	@Transient
 	private List<Long> contributorsList;
@@ -204,6 +207,18 @@
 
 
 
+	public String getKeywords() {
+		return keywords;
+	}
+
+
+	public void setKeywords(String keywords) {
+		this.keywords = keywords;
+	}
+
+
+
+
 	public void setContributorsList(List<Long> contributorsList) {
 		this.contributorsList = contributorsList;
 	}
@@ -216,7 +231,10 @@
 	public DuplexKey<Long, Long> getKey(){
 		return new DuplexKey<Long, Long>(this.userId, this.id);
 	}
-	
+
+	public String info() {
+		return nameEn + "(" + nameCh + ", " + namePinyin + ")";
+	}
 
 	@Override
 	public String toString(){
@@ -224,4 +242,6 @@
 	}
 
 	
+
+	
 }
--- a/src/main/java/de/mpiwg/gazetteer/bo/LGTopicSectionRelation.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/gazetteer/bo/LGTopicSectionRelation.java	Wed Dec 23 16:03:32 2015 +0100
@@ -34,13 +34,25 @@
 	@Column(name="sectionId")
 	private Long sectionId;
 	
-	
 	@Column(name="bookId")
 	private String bookId;
 
+	
+	
 	@Transient
 	private boolean transientDataLoaded = false;
 	
+
+	@Transient
+	private LGTopic topic;
+	
+	public void loadTransientData(){
+		
+		this.topic = DataProvider.getInstance().getTopic(topicId);
+	
+		this.transientDataLoaded = true;
+		
+	}
 	
 	
 	
@@ -92,6 +104,18 @@
 	}
 
 
+	public LGTopic getTopic() {
+		return topic;
+	}
+
+
+
+	public void setTopic(LGTopic topic) {
+		this.topic = topic;
+	}
+
+
+
 	public DuplexKey<Long, Long> getKey(){
 		return new DuplexKey<Long, Long>(this.topicId, this.sectionId);
 	}
@@ -101,5 +125,8 @@
 		return "LGTopicSectionRelation[topicId=" + topicId.toString() + ", sectionId=" + sectionId.toString() + "]";
 	}
 
+
+	
+
 	
 }
--- a/src/main/java/de/mpiwg/gazetteer/db/DBBook.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/gazetteer/db/DBBook.java	Wed Dec 23 16:03:32 2015 +0100
@@ -31,6 +31,10 @@
 
 	private DBSectionVersion currentSectionVersion;
 	
+	public DBBook() {
+		
+	}
+	
 	public DBBook(ResultSet rs) throws SQLException{
 		this.name = rs.getString("name");
 		this.id = rs.getString("id");
--- a/src/main/java/de/mpiwg/gazetteer/db/DBSection.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/gazetteer/db/DBSection.java	Wed Dec 23 16:03:32 2015 +0100
@@ -5,6 +5,8 @@
 import java.util.List;
 
 import de.mpiwg.gazetteer.bo.LGBranch;
+import de.mpiwg.gazetteer.bo.LGTopic;
+import de.mpiwg.gazetteer.bo.LGTopicSectionRelation;
 
 public class DBSection implements Comparable<DBSection>{
 
@@ -19,6 +21,7 @@
 	private Integer end_page;
 	
 	private List<LGBranch> branches;
+	private List<LGTopicSectionRelation> topicSectionRelation;
 	
 	/*
 	public DBSection(Long id){
@@ -94,6 +97,16 @@
 		this.branches = branches;
 	}
 	
+
+	public List<LGTopicSectionRelation> getTopicSectionRelation() {
+		return topicSectionRelation;
+	}
+
+	public void setTopicSectionRelation(
+			List<LGTopicSectionRelation> topicSectionRelation) {
+		this.topicSectionRelation = topicSectionRelation;
+	}
+
 	public Integer getStart_page() {
 		return start_page;
 	}
--- a/src/main/java/de/mpiwg/gazetteer/utils/DBService.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/gazetteer/utils/DBService.java	Wed Dec 23 16:03:32 2015 +0100
@@ -145,7 +145,7 @@
 		return getBookMap().get(id);
 	}
 	
-	private Map<String, DBBook> getBookMap(){
+	public Map<String, DBBook> getBookMap(){
 		if(bookMap == null){
 			try {
 				this.loadBookMap();	
@@ -543,6 +543,7 @@
 		return list;
 	}
 	
+	
 	public static DBSection getSectionWithContent(Long sectionId) throws SQLException {
 
 		Connection conn = null;
--- a/src/main/java/de/mpiwg/gazetteer/utils/DataProvider.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/gazetteer/utils/DataProvider.java	Wed Dec 23 16:03:32 2015 +0100
@@ -22,7 +22,7 @@
 
 public class DataProvider extends AbstractDataProvider{
 	
-	private static Logger logger = Logger.getLogger(DBService.class);
+	private static Logger logger = Logger.getLogger(DataProvider.class);
 	private static DataProvider instance;
 	
 	public static DataProvider getInstance(){
@@ -54,6 +54,14 @@
 		return list;
 	}
 	
+	public List<LGTopicSectionRelation> getAllExistingTopicSectionRelation() {
+		List<LGTopicSectionRelation> list = new ArrayList<LGTopicSectionRelation>();
+		for (LGTopicSectionRelation relation : getTopicSectionRelationMap().values()) {
+			list.add(relation);
+		}
+		return list;
+	}
+	
 	public List<LGBranch> getAllExistingBranches(){
 		List<LGBranch> list = new ArrayList<LGBranch>();
 		for(LGBranch branch : getBranchMap().values()){	
@@ -392,7 +400,7 @@
 		// get sections from topicSecionRelation list
 		List<DBSection> list = new ArrayList<DBSection>();
 		for (LGTopicSectionRelation aRelation : topicSectionRelationList) {
-			logger.debug(aRelation.getInfo() );
+			//logger.debug(aRelation.getInfo() );
 			
 			DBSection section = DBService.getSectionWithContent(aRelation.getSectionId());
 			list.add(section);
--- a/src/main/java/de/mpiwg/web/jsp/ApplicationBean.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/web/jsp/ApplicationBean.java	Wed Dec 23 16:03:32 2015 +0100
@@ -68,6 +68,10 @@
 		return value;	
 	}
 	
+	public String getOkImage(){
+		return getRootServer() + "/resources/images/ok.png";
+	}
+	
 	public String getPlusImage() {
 		return getRootServer() + "/resources/images/plus.png";
 	}
--- a/src/main/java/de/mpiwg/web/jsp/JSPProxy.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/web/jsp/JSPProxy.java	Wed Dec 23 16:03:32 2015 +0100
@@ -28,6 +28,28 @@
 		
 		try{
 			
+			
+			if(StringUtils.equals(bean, "loginBean")){
+				getSessionBean().loadParameters(request, response);
+			
+				if(StringUtils.equals(action, "login")){
+					getSessionBean().login();
+				}else if(StringUtils.equals(action, "logout")){
+					getSessionBean().logout();
+				}
+				return TopicListPage.page;	// the new home page
+				//return "pages/home.jsp";
+				
+			} else if (getSessionBean() == null || getSessionBean().getUser() == null) {
+				// return to home page where will ask user to login.
+				
+				// alert session timeout
+				getSessionBean().addMsg("Timeout or Logout at another page! Please login again.");
+				
+				return TopicListPage.page;	// the new home page
+			}
+		
+			
 			if(StringUtils.equals(bean, BranchPage.bean)){
 				
 				getSessionBean().getBranchPage().loadParameters(request, response);
@@ -133,18 +155,7 @@
 				
 				return HomePage.page;
 				
-			}else if(StringUtils.equals(bean, "loginBean")){
-				getSessionBean().loadParameters(request, response);
-				
-				if(StringUtils.equals(action, "login")){
-					getSessionBean().login();
-				}else if(StringUtils.equals(action, "logout")){
-					getSessionBean().logout();
-				}
-				
-				return TopicListPage.page;
-				//return "pages/home.jsp";
-				
+			
 			}else if(StringUtils.equals(bean, SearchPage.bean)){
 				getSessionBean().getSearchPage().loadParameters(request, response);
 				
@@ -334,6 +345,11 @@
 					getSessionBean().getTopicPage().updateDescription();
 					getSessionBean().getTopicListPage().forceLoadTopics();
 					
+				} else if( StringUtils.equals(action ,"updateKeywords")) {
+					getSessionBean().getTopicPage().updateKeywords();
+					getSessionBean().getTopicListPage().forceLoadTopics();
+			
+					
 				/* ====== */
 					
 					
@@ -341,13 +357,20 @@
 					getSessionBean().getTopicPage().deleteSection(getLongParameter("sectionId"));
 				
 				
-				} else if(StringUtils.equals(action, "addSectionToTopic")) {
+				} else if(StringUtils.equals(action, "addSection")) {
 					Long selectedSectionId = getLongParameter("selectedSectionId");
 					Long selectedTopicId = getLongParameter("selectedTopicId");
+					getSessionBean().getTopicPage().addSectionToTopic(selectedSectionId, selectedTopicId);
+					getSessionBean().getSearchPage().updateTopicSectionRelation();
 					
-					getSessionBean().getTopicPage().addSectionToTopic(selectedSectionId, selectedTopicId);
 					return SearchPage.page;
+				
+				} else if(StringUtils.equals(action, "addAllSections")) {
+					Long selectedTopicId = getLongParameter("selectedTopicId");
+					getSessionBean().getTopicPage().addAllSectionsToTopic(getSessionBean().getSearchPage().getFilteredSectionList(), selectedTopicId);
+					getSessionBean().getSearchPage().updateTopicSectionRelation();
 					
+					return SearchPage.page;
 					
 					
 				//SORTING
--- a/src/main/java/de/mpiwg/web/jsp/SearchPage.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/web/jsp/SearchPage.java	Wed Dec 23 16:03:32 2015 +0100
@@ -13,6 +13,8 @@
 import org.apache.log4j.Logger;
 
 import de.mpiwg.gazetteer.bo.LGBranch;
+import de.mpiwg.gazetteer.bo.LGTopic;
+import de.mpiwg.gazetteer.bo.LGTopicSectionRelation;
 import de.mpiwg.gazetteer.db.DBSection;
 import de.mpiwg.gazetteer.utils.DBService;
 import de.mpiwg.gazetteer.utils.DataProvider;
@@ -58,6 +60,8 @@
 	private String filteringMessage;
 	
 
+	private Map<Long, List<LGTopicSectionRelation>> topicSectionRelationMap;
+	
 	
 	@Override
 	public void init(){
@@ -77,6 +81,13 @@
 			
 	}
 	
+	public void updateTopicSectionRelation() {
+		logger.debug("updateTopicSectionRelation");	
+		this.loadTopicSectionRelation();
+		this.filter();
+		
+	}
+	
 	public void search(){		
 		logger.debug("Searching: " + this.searchTerm);
 		
@@ -86,6 +97,12 @@
 		
 		if(StringUtils.isNotEmpty(this.searchTerm)){
 			this.loadBranches();
+			
+			this.loadTopicSectionRelation();
+			
+			// TODO load all books for the difference set??
+			
+			
 			try {
 				List<String> terms = splitTerms();
 				
@@ -166,6 +183,7 @@
 		
 		for(DBSection section : this.displaySectionList){
 			section.setBranches(this.branchesMap.get(section.getId()));
+			section.setTopicSectionRelation(this.topicSectionRelationMap.get(section.getId()));
 		}
 	}
 	
@@ -183,8 +201,18 @@
 		}
 	}
 	
-	
-
+	private void loadTopicSectionRelation(){
+		this.topicSectionRelationMap = new HashMap<Long, List<LGTopicSectionRelation>>();
+		List<LGTopicSectionRelation> list = DataProvider.getInstance().getAllExistingTopicSectionRelation();
+		
+		for(LGTopicSectionRelation relation : list){
+			relation.loadTransientData();
+			if(this.topicSectionRelationMap.get(relation.getSectionId()) == null){
+				this.topicSectionRelationMap.put(relation.getSectionId(), new ArrayList<LGTopicSectionRelation>());
+			}
+			this.topicSectionRelationMap.get(relation.getSectionId()).add(relation);
+		}
+	}
 	
 	
 	private List<String> splitTerms(){
@@ -253,6 +281,15 @@
 	}
 
 
+	public Map<Long, List<LGTopicSectionRelation>> getTopicSectionRelationMap() {
+		return topicSectionRelationMap;
+	}
+
+	public void setTopicSectionRelationMap(
+			Map<Long, List<LGTopicSectionRelation>> topicSectionRelationMap) {
+		this.topicSectionRelationMap = topicSectionRelationMap;
+	}
+
 	public Map<Long, List<LGBranch>> getBranchesMap() {
 		return branchesMap;
 	}
--- a/src/main/java/de/mpiwg/web/jsp/SessionBean.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/web/jsp/SessionBean.java	Wed Dec 23 16:03:32 2015 +0100
@@ -11,6 +11,7 @@
 
 import de.mpiwg.gazetteer.dataverse.DataverseUtils;
 import de.mpiwg.gazetteer.dataverse.bo.VDCUser;
+import de.mpiwg.gazetteer.utils.DataProvider;
 
 public class SessionBean extends AbstractJSPPage {
 
@@ -56,8 +57,14 @@
 		this.homePage = new HomePage();
 		this.createFilePage = new CreateFilePage();
 		this.branchPage = new BranchPage();
+		
+		this.booksPage = new BooksPage();
+		this.topicListPage = new TopicListPage();
+		this.topicPage = new TopicPage();
+
 		this.userName = new String();
 		this.password = new String();
+		
 	}
 	
 	public List<String> getMsgList() {
@@ -89,10 +96,13 @@
 				// check if user has role in the "Chinese Local Gazetteers" Dataverse, rather than the following hardcoded checking
 				// use dvn/getRoleAssignments?user=&password=&datasetId=
 				if ( StringUtils.equals(userName, "dataverseAdmin") || DataverseUtils.isUserInLG(userName, password) || DataverseUtils.isUserInGroups(this.user.getUserName(), theUserGroups)){
+					
 					this.user.setPassword(this.password);
 					this.homePage.loadParameters(request, response);
 					this.homePage.reloadBranches();	
 					
+					
+					
 				} else {					
 					this.user = null;
 					
--- a/src/main/java/de/mpiwg/web/jsp/TopicListPage.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/web/jsp/TopicListPage.java	Wed Dec 23 16:03:32 2015 +0100
@@ -54,25 +54,27 @@
 	
 	public void forceLoadTopics(){
 		logger.debug("forceLoadTopics");
+		
 		DataProvider.getInstance().setTopicMap(null);
 		DataProvider.getInstance().setTopicSectionRelationMap(null); 
 		
+		
 		this.completeTopicList = new ArrayList<LGTopic>();
 	
 		if(getSessionBean().getUser() != null){
 			for(LGTopic topic : DataProvider.getInstance().getTopics(getSessionBean().getUser().getId())){
-		
+				
 				if (topic.isEmpty()) {
 					logger.debug("topic doesn't exist anymore.");
 				} else {
 					this.completeTopicList.add(topic);
 				}
 			}	
-		}
-		this.setTopicNumber(this.completeTopicList.size());
+		
+			this.setTopicNumber(this.completeTopicList.size());
 		
-		sortByLastModifiedDown();	// default sorting by from lasted modified to oldest
-		
+			sortByLastModifiedDown();	// default sorting by from lasted modified to oldest
+		}
 		
 	}
 	
@@ -85,13 +87,14 @@
 		String namePinyin = getParameter("namePinyin");
 		String description = getParameter("description");
 
-		logger.debug("nameEn: " + nameEn);
-		logger.debug("nameCh: " + nameCh);
-		logger.debug("namePinyin: " + namePinyin);
-		logger.debug("description: " + description);
+		logger.debug("nameEn: " + nameEn + "nameCh: " + nameCh + "namePinyin: " + namePinyin + "description: " + description);
 		
 		if (StringUtils.isEmpty(nameEn)) {
-			addMsg("Create Fails. Name(eng) cannot be empty.");
+			addMsg("Creating topic Failed. Name(Eng) cannot be empty.");
+		} else if (StringUtils.isEmpty(nameCh)) {
+			addMsg("Creating topic Failed. Name(中文) cannot be empty.");
+		}else if (StringUtils.isEmpty(namePinyin)) {
+			addMsg("Creating topic Failed. Name(Pinyin) cannot be empty.");
 		} else {
 			
 			DataProvider.getInstance().createTopic(nameEn, nameCh, namePinyin, description, userId);
@@ -144,7 +147,7 @@
 		}
 		
 		if(completeTopicList.size() > 0){
-			this.filteringMessage = this.filteredTopicList.size() + " topics listed after filtering";
+			//this.filteringMessage = this.filteredTopicList.size() + " topics listed after filtering";
 			this.paginator.setCurrentPage(0);
 			this.paginator.resetNumberOfPages(filteredTopicList.size());
 			
--- a/src/main/java/de/mpiwg/web/jsp/TopicPage.java	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/java/de/mpiwg/web/jsp/TopicPage.java	Wed Dec 23 16:03:32 2015 +0100
@@ -1,8 +1,10 @@
 package de.mpiwg.web.jsp;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -18,6 +20,7 @@
 import de.mpiwg.gazetteer.bo.LGTopicSectionRelation;
 import de.mpiwg.gazetteer.dataverse.DataverseUtils;
 import de.mpiwg.gazetteer.dataverse.bo.VDCUser;
+import de.mpiwg.gazetteer.db.DBBook;
 import de.mpiwg.gazetteer.db.DBSection;
 import de.mpiwg.gazetteer.utils.DBService;
 import de.mpiwg.gazetteer.utils.DataProvider;
@@ -67,6 +70,11 @@
 	
 	private Map<Long, List<LGBranch>> branchesMap;
 	
+	private Map<String, DBBook> booksMap;
+	
+	private List<DBBook> pendingBookList;
+
+	
 	public void loadParameters(HttpServletRequest request, HttpServletResponse response){
 
 		this.request = request;
@@ -160,6 +168,8 @@
 			
 		if(topic != null && topic.isPersistent()){
 			this.loadBranches();
+			this.loadBooks();
+			
 			try {
 				this.topic = (LGTopic)topic.clone();
 				
@@ -184,6 +194,21 @@
 			logger.info("completeSectionList.size=" + completeSectionList.size());
 		}
 		this.filter();
+		
+		
+		// pendingBookList
+		for(DBSection section :this.completeSectionList) {
+			String bookId = section.getBookId();
+			
+			if (this.booksMap.get(bookId) != null) {
+				// remove the book with bookId from pendingBookList
+				this.booksMap.remove(bookId);
+			} 
+		}
+		
+		this.pendingBookList = new ArrayList<DBBook>();
+		this.pendingBookList.addAll(this.booksMap.values());
+	
 	}
 	
 	
@@ -295,10 +320,12 @@
 		}
 		*/
 		
-		for(DBSection section : this.displaySectionList){
-			section.setBranches(this.branchesMap.get(section.getId()));
+		//for(DBSection section : this.displaySectionList){
+		for(DBSection section : this.completeSectionList){	// we don't paginate now
+			section.setBranches(this.branchesMap.get(section.getId()));		
 		}
 		
+		
 	
 	}
 	
@@ -312,7 +339,6 @@
 		String status = DataProvider.getInstance().updateTopicSectionRelation(_sectionId, _topicId);
 		
 		if (StringUtils.equals(status, "added") ) {
-			// TODO responding with names to user
 			addMsg("Added section [id=" + _sectionId + "] to the topic [id=" + _topicId + "]");
 		} else if (StringUtils.equals(status, "updated") ) {
 			addMsg("The section already in the topic");
@@ -335,9 +361,58 @@
 				this.branchesMap.put(branch.getSectionId(), new ArrayList<LGBranch>());
 			}
 			this.branchesMap.get(branch.getSectionId()).add(branch);
+		
 		}
 	}
 	
+	
+	private void loadBooks(){
+	
+		List<DBBook> bookList = DBService.getInstance().getBooks();
+		
+		this.booksMap = new HashMap<String, DBBook>();
+		
+		for (DBBook book : bookList) {
+			
+			this.booksMap.put(book.getId(), book);
+			
+		}
+			
+	}
+	
+	
+
+	public void addAllSectionsToTopic(List<DBSection> list, Long selectedTopicId) throws Exception {
+		
+		if (list == null) {
+			return;
+		}
+		logger.debug("selectedTopicId: " + selectedTopicId + ", total " + list.size() + " sections.");
+	
+		Integer added = 0;
+		Integer existing = 0;
+		
+		for (DBSection section : list) {
+			// create a new record in TopicSectionRelation table 
+			String status = DataProvider.getInstance().updateTopicSectionRelation(section.getId(), selectedTopicId);
+			
+			if (StringUtils.equals(status, "added") ) {
+				added++;
+			} else if (StringUtils.equals(status, "updated") ) {
+				existing++;
+			} 
+			
+		}
+		
+		addMsg("Added " + added.toString() + " sections. " + existing.toString() + " sections already in the topic.");
+		
+		this.reset();
+	}
+
+	
+	
+	
+	
 	public List<VDCUser> getContributors() {
 		return contributors;
 	}
@@ -538,21 +613,36 @@
 	}
 
 
+	
+
+
+	public List<DBBook> getPendingBookList() {
+		return pendingBookList;
+	}
+
+
+
+	public void setPendingBookList(List<DBBook> pendingBookList) {
+		this.pendingBookList = pendingBookList;
+	}
+
+
 
 	public List<DBSection> getCompleteSectionList() {
 		return completeSectionList;
 	}
 
-
-
 	public void setCompleteSectionList(List<DBSection> completeSectionList) {
 		this.completeSectionList = completeSectionList;
 	}
 
 
+	
+
+
+
 
 	/////// Sorting
-	
 
 	public void sortByBookNameUp(){
 		Collections.sort(this.completeSectionList, new SortSectionByBookName());
@@ -669,6 +759,18 @@
 		filter();
 	}
 
+
+	public void updateKeywords() {
+		String keywords = getParameter("keywords");
+		this.getTopic().setKeywords(keywords);
+		
+		this.saveTopic0();
+		
+	}
+
+
+
+
 	
 	
 
--- a/src/main/webapp/methods/addSectionToTopic.jsp	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/webapp/methods/addSectionToTopic.jsp	Wed Dec 23 16:03:32 2015 +0100
@@ -3,53 +3,69 @@
 <%@page import="de.mpiwg.gazetteer.utils.DBService"%>
 <%@page import="de.mpiwg.gazetteer.utils.DataProvider"%>
 
+
 <jsp:useBean id="sessionBean" class="de.mpiwg.web.jsp.SessionBean" scope="session" />
 	
 <%
-	if(request.getParameter("sectionId") != null){
-		Long sectionId = Long.parseLong(request.getParameter("sectionId"));
-		
-		if(sectionId != 0){
+	if (sessionBean == null || sessionBean.getUser() == null) { %>
+		<form name="timeoutForm"
+			action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
+			method="post">
+			<input name="bean" type="hidden" value="loginBean" />
 			
-			if (sessionBean.getTopicListPage().getCompleteTopicList() == null) {
-				sessionBean.getTopicListPage().loadParameters(request, response);
-				sessionBean.getTopicListPage().reloadTopics();
-			}
-			
+			<h3>Timeout or Logout at another page! Please Login again.</h3>
+			<input type="image" width="40" height="40"
+					onclick="setAction('logout', 'timeoutForm');" 
+					src="<%=sessionBean.getApplicationBean().getOkImage() %>"/>
+		
+		</form> 
+<% } else if (sessionBean.getTopicListPage().getCompleteTopicList() == null) {
+		sessionBean.getTopicListPage().loadParameters(request, response);
+		sessionBean.getTopicListPage().reloadTopics();
+	}
+%>
+		
+		<form name="addSectionToTopicForm" id="addSectionToTopicForm"
+				action="<%= sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
+				method="post">
+				<input name="bean" type="hidden" value="topicBean" /> 
+		
+						
+				<table class="dialogTable">
+					<tr>
+						<td><label style="font-weight: bold;">Topic Id</label></td>
+						<td><label style="font-weight: bold;">Name</label></td>
+					</tr>
+					
+					<% for (LGTopic topic : sessionBean.getTopicListPage().getCompleteTopicList() ) {%>
+					<tr>	
+						<td><%=topic.getId() %></td>
+						<td>
+							<%=topic.getNameEn() %>(<%=topic.getNameCh() %>)
+						
+							<% if(request.getParameter("sectionId") != null) {
+								Long sectionId = Long.parseLong(request.getParameter("sectionId"));
+							%>
+								<!-- add section to selected topic -->
+								<input name="selectedSectionId" type="hidden" value="<%=request.getParameter("sectionId") %>" />
+	
+								<input type="image"
+										onclick="setAction0('addSection', 'addSectionToTopicForm', 'selectedTopicId', '<%=topic.getId() %>');"
+										src="<%=sessionBean.getApplicationBean().getPlusImage() %>" width="20" height="20"/>
+							
+						 	<% } else if (request.getParameter("addAllSections") != null) { %>	
+								<input type="image"
+										onclick="setAction0('addAllSections', 'addSectionToTopicForm', 'selectedTopicId', '<%=topic.getId() %>');"
+										src="<%=sessionBean.getApplicationBean().getPlusImage() %>" width="20" height="20"/>
+								
+							<% } %>	
+		 								
+						</td>						
+					</tr>
+					<% } %>
+				</table>
 			
-%>
-	
-	<form name="addSectionToTopicForm" id="addSectionToTopicForm"
-		action="<%= sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
-		method="post">
-		<input name="bean" type="hidden" value="topicBean" /> 
+			</form>
 
-		<!-- TODO add section to selected topic -->
-		<input name="selectedSectionId" type="hidden" value="<%=request.getParameter("sectionId") %>" />
-				
-		<table class="dialogTable">
-			<tr>
-				<td><label style="font-weight: bold;">Topic Id</label></td>
-				<td><label style="font-weight: bold;">Name</label></td>
-			</tr>
-			
-			<% for (LGTopic topic : sessionBean.getTopicListPage().getCompleteTopicList() ) {%>
-			<tr>	
-				<td><%=topic.getId() %></td>
-				<td>
-					<%=topic.getNameEn() %>(<%=topic.getNameCh() %>)
- 
-					<input type="image"
-							onclick="setAction0('addSectionToTopic', 'addSectionToTopicForm', 'selectedTopicId', '<%=topic.getId() %>');"
-							src="<%=sessionBean.getApplicationBean().getPlusImage() %>" width="20" height="20"/>
-				</td>						
-			</tr>
-			<% } %>
-		</table>
-	
-	</form>
-	
-<%
-		}
-	}
-%>
\ No newline at end of file
+
+		
\ No newline at end of file
--- a/src/main/webapp/methods/getDataverseForm.jsp	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/webapp/methods/getDataverseForm.jsp	Wed Dec 23 16:03:32 2015 +0100
@@ -2,77 +2,94 @@
 <%@page import="de.mpiwg.gazetteer.dataverse.bo.Study"%>
 <%@page import="de.mpiwg.gazetteer.dataverse.bo.Datasets"%>
 <%@page import="java.util.List"%>
-<jsp:useBean id="sessionBean" class="de.mpiwg.web.jsp.SessionBean" scope="session" />
-<%
-	
-	//List<Study> studies = DataverseUtils.getStudies(sessionBean.getUser().getUserName(), sessionBean.getUser().getPassword());
-	// List<Datasets> studies = DataverseUtils.getDatasets(sessionBean.getUser().getUserName(), sessionBean.getUser().getPassword());
-	List<Datasets> studies = DataverseUtils.getDatasetsInAllDataverse(sessionBean.getUser().getUserName(), sessionBean.getUser().getPassword());
-	
-	System.out.println("%%%%% Studies: " + studies.size());
-	
-	if(studies.isEmpty()){
-%>
 
-	<label>The system does not find studies for the user <%= sessionBean.getUser().getUserName()%>.</label>
-
-<%		
-	} else {
-%>
+<jsp:useBean id="sessionBean" class="de.mpiwg.web.jsp.SessionBean" scope="session" />
+		
+	<% if (sessionBean == null || sessionBean.getUser() == null) { %>
+		<form name="timeoutForm"
+			action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
+			method="post">
+			<input name="bean" type="hidden" value="loginBean" />
+			
+			<h3>Timeout or Logout at another page! Please Login again.</h3>
+			<input type="image" width="40" height="40"
+					onclick="setAction('logout', 'timeoutForm');" 
+					src="<%=sessionBean.getApplicationBean().getOkImage() %>"/>
+		
+		</form> 
+	        
+	<% } else {
 
-<form name="dataverseForm"
-	action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
-	method="post">
-	<input name="bean" type="hidden" value="branchBean" />
-	<input name="fileId" type="hidden" value="<%=request.getParameter("fileId") %>" /> 	
+		//List<Study> studies = DataverseUtils.getStudies(sessionBean.getUser().getUserName(), sessionBean.getUser().getPassword());
+		// List<Datasets> studies = DataverseUtils.getDatasets(sessionBean.getUser().getUserName(), sessionBean.getUser().getPassword());
+		List<Datasets> studies = DataverseUtils.getDatasetsInAllDataverse(sessionBean.getUser().getUserName(), sessionBean.getUser().getPassword());
+		
+		System.out.println("%%%%% Studies: " + studies.size());
+		
+		if(studies.isEmpty()){
+		%>
 	
+		<label>The system does not find studies for the user <%= sessionBean.getUser().getUserName()%>.</label>
+	
+		<%		
+		} else {
+		%>
 	
-	<table class="pageTable">
-		<tbody>
-			<tr>
-				<th><label class="tableTitle">Dataverse</label></th>
-				<!-- 
-				<th><label class="tableTitle">Dataset ID</label></th>
-				-->
-				<th><label class="tableTitle">Dataset</label></th>
-				<th><label class="tableTitle">Created</label></th>
-				<th><label class="tableTitle">State</label></th>
-				<th><label class="tableTitle">Version</label></th>
-				<th><label class="tableTitle">Publish</label></th>
-				<!-- 
-				<th><label class="tableTitle">Release Date</label></th>
-				<th><label class="tableTitle">Last Updated</label></th>
-				<th><label class="tableTitle">Number of Files </label></th>
-				 -->
-			</tr>
-		</tbody>
-		<%
-			for(Datasets study : studies){
-		%>
+		<form name="dataverseForm"
+			action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
+			method="post">
+			<input name="bean" type="hidden" value="branchBean" />
+			<input name="fileId" type="hidden" value="<%=request.getParameter("fileId") %>" /> 	
+			
 			
-			<tr>
-				<!--  <td>Chinese Local Gazetteers </td> -->
-				<td><%= study.getDvIdInDataverse() %></td>
-				
-				<!-- <td><%= study.getId()%></td> 
-				-->
-				<td><%= study.getTitle() %></td>
-				<td><%= study.getCreateTime() %></td>
-				<td><%= study.getVersionState().toLowerCase() %></td>
-				
-				<td><%= study.getVersion() %></td>
-				<td>
-					<input type="image" 
-						onclick="<%=sessionBean.getApplicationBean().getJSConfirmationPublish() %> setAction0('publishFile', 'dataverseForm', 'datasetId', '<%=study.getId() %>');" 
-						src="<%=sessionBean.getApplicationBean().getPublishImage()%>"/>
-				</td>
-			</tr>
-			
-		<% 
-			}
-		%>				
-	</table>
-</form>
+			<table class="pageTable">
+				<tbody>
+					<tr>
+						<th><label class="tableTitle">Dataverse</label></th>
+						<!-- 
+						<th><label class="tableTitle">Dataset ID</label></th>
+						-->
+						<th><label class="tableTitle">Dataset</label></th>
+						<th><label class="tableTitle">Created</label></th>
+						<th><label class="tableTitle">State</label></th>
+						<th><label class="tableTitle">Version</label></th>
+						<th><label class="tableTitle">Publish</label></th>
+						<!-- 
+						<th><label class="tableTitle">Release Date</label></th>
+						<th><label class="tableTitle">Last Updated</label></th>
+						<th><label class="tableTitle">Number of Files </label></th>
+						 -->
+					</tr>
+				</tbody>
+				<%	
+					for(Datasets study : studies){
+				%>
+					
+					<tr>
+						<!--  <td>Chinese Local Gazetteers </td> -->
+						<td><%= study.getDvIdInDataverse() %></td>
+						
+						<!-- <td><%= study.getId()%></td> 
+						-->
+						<td><%= study.getTitle() %></td>
+						<td><%= study.getCreateTime() %></td>
+						<td><%= study.getVersionState().toLowerCase() %></td>
+						
+						<td><%= study.getVersion() %></td>
+						<td>
+							<input type="image" 
+								onclick="<%=sessionBean.getApplicationBean().getJSConfirmationPublish() %> setAction0('publishFile', 'dataverseForm', 'datasetId', '<%=study.getId() %>');" 
+								src="<%=sessionBean.getApplicationBean().getPublishImage()%>"/>
+						</td>
+					</tr>
+					
+				<% 
+					}
+				%>				
+			</table>
+		</form>
+
 <%
+		}
 	}
 %>
\ No newline at end of file
--- a/src/main/webapp/pages/branchPage.jsp	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/webapp/pages/branchPage.jsp	Wed Dec 23 16:03:32 2015 +0100
@@ -62,7 +62,7 @@
 	<jsp:include page="../componentes/template.jsp"/>
 	
 	<div id="dialogDataverse" title="Select a Dataset to publish your File" >
-	  <div id="dialogDataverseTable">XXXX</div>
+	  <div id="dialogDataverseTable"></div>
 	</div>		
 
 	<div id="page">
--- a/src/main/webapp/pages/search.jsp	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/webapp/pages/search.jsp	Wed Dec 23 16:03:32 2015 +0100
@@ -1,4 +1,5 @@
 <%@page import="de.mpiwg.gazetteer.bo.LGBranch"%>
+<%@page import="de.mpiwg.gazetteer.bo.LGTopicSectionRelation"%>
 <%@page import="org.apache.commons.lang.StringUtils"%>
 <%@page import="de.mpiwg.gazetteer.db.DBSection"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
@@ -16,15 +17,33 @@
 	
 		$(function() {
 		
+			$("#addAllSectionsToTopic").click(function() {
+				
+				var r = confirm("Add "+ '<%= sessionBean.getSearchPage().getFilteredSectionList().size() %>' + " sections to a topic?");
+				if (r == true) {
+				    console.log("addAllSectionsToTopic");
+			
+					var url0 = "<%=sessionBean.getApplicationBean().getRootServer()%>/methods/addSectionToTopic.jsp?addAllSections=1";
+					
+					$.ajax( url0 )
+					.done(function(data) {
+						$( "#dialogAddSectionToTopicTable" ).replaceWith(data);
+						dialogAddSectionToTopic.dialog( "open" );
+					})
+				  	.fail(function() {
+				    	console.error("Error calling: " + query);
+				  	});
+			  	
+				}
+
+			});
+			
 			$( ".addSectionToTopic" ).click(function() {
 				var sectionId = $( this ).data('section-id');
-				
-
-				console.log("addSectionToTopic. sectionId = " + sectionId);
+				//console.log("addSectionToTopic. sectionId = " + sectionId);
 						
 				var url0 = "<%=sessionBean.getApplicationBean().getRootServer()%>/methods/addSectionToTopic.jsp?sectionId=" + sectionId;
-				
-				
+		
 				$.ajax( url0 )
 				.done(function(data) {
 					$( "#dialogAddSectionToTopicTable" ).replaceWith(data);
@@ -191,7 +210,7 @@
 	  <div id="dialogMoreInfoTable"></div>
 	</div>
  	
-	<div id="dialogAddSectionToTopic" title="Add Section into Topic:">
+	<div id="dialogAddSectionToTopic" title="Add Section(s) into Topic:">
 		<div id="dialogAddSectionToTopicTable"></div>
 	</div>
 
@@ -411,29 +430,6 @@
 											</tr>								
 										</table>	
 									</th>
-									<!-- 
-									<th>
-										<table class="sortTable">
-											<tr>
-												<td><label class="tableTitle">Volume</label></td>
-												<td>
-													<table>
-														<tr><td>
-															<input type="image"
-																onclick="setAction('sortByVolumeUp', 'searchForm');"
-																src="<%=sessionBean.getApplicationBean().getUpImage()%>"/>										
-														</td></tr>
-														<tr><td>
-															<input type="image"
-																onclick="setAction('sortByVolumeDown', 'searchForm');"
-																src="<%=sessionBean.getApplicationBean().getDownImage()%>"/>																				
-														</td></tr>
-													</table>
-												</td>
-											</tr>
-										</table>						
-									</th>
-									-->
 									<th>
 										<table class="sortTable">
 											<tr>
@@ -478,13 +474,20 @@
 									
 									</th>
 									<th><label class="tableTitle">View Text</label></th>
-									<th><label class="tableTitle">Add to Topic</label></th>
+									
+									<th>
+										<label class="tableTitle">Add to Topic</label>
+										
+										<img id="addAllSectionsToTopic" width="15" height="15" alt="Add all sections to Topic" src="<%=sessionBean.getApplicationBean().getPlusImage()%>">
+										
+										
+									</th>
 									<th><label class="tableTitle">Existing Tasks</label></th>
 								</tr>
 							
 				
-								<%
-									for (DBSection section : sessionBean.getSearchPage().getDisplaySectionList()) {
+								<% 
+								for (DBSection section : sessionBean.getSearchPage().getDisplaySectionList()) {
 								%>
 								<tr>
 									<td>
@@ -514,10 +517,33 @@
 									</td>
 									
 									<!-- Add to Topic -->
-									<td>
+									<td style="max-width:300px;">
+										<!-- existing topic -->
+										<% if(section.getTopicSectionRelation() != null && !section.getTopicSectionRelation().isEmpty()) { %>
+											<lable>Already in topic: </lable>
+											<table style="width:100%">		
+												<% for(LGTopicSectionRelation relation : section.getTopicSectionRelation()) { %>
+													<tr>
+														<td>
+															<table style="width:100%; min-width:100px">
+															<tr><td><%=relation.getTopic().info() %></td></tr>
+															</table>
+														</td>
+														<td style="max-width:150px">
+															
+															<a href="<%=sessionBean.getApplicationBean().getRootServer() %>/pages/topicPage.jsp?topicId=<%=relation.getTopicId() %>" >
+																<img alt="Manage Topic" src="<%=sessionBean.getApplicationBean().getEditBranchImage()%>"/>
+															</a>												
+															
+														</td>
+													</tr>
+												<% } %>
+											</table>
+										<% } %>
 										
 										<img width="10" height="10" alt="Add the section to Topic" src="<%=sessionBean.getApplicationBean().getPlusImage()%>" data-section-id="<%=section.getId()%>" class="addSectionToTopic">
-						
+									
+									
 									</td>
 									
 									
--- a/src/main/webapp/pages/topicList.jsp	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/webapp/pages/topicList.jsp	Wed Dec 23 16:03:32 2015 +0100
@@ -52,7 +52,7 @@
 					<table>
 						<tr>
 							<td>
-								<span>Name (Eng)</span>
+								<span>name(Eng)*</span>
 							</td>
 							<td>
 								<input id="nameEn" name="nameEn" type="text" placeholder="e.g. Local Product"/>
@@ -60,7 +60,7 @@
 						</tr>
 						<tr>
 							<td>
-								<span>name (中文)</span>
+								<span>name(中文)*</span>
 							</td>
 							<td>
 								<input id="nameCh" name="nameCh" type="text" placeholder="e.g. 物產"/>
@@ -68,7 +68,7 @@
 						</tr>
 						<tr>
 							<td>
-								<span>name (Pinyin)</span>
+								<span>name(Pinyin)*</span>
 							</td>
 							<td>
 								<input id="namePinyin" name="namePinyin" type="text" placeholder="e.g. wu chan"/>
@@ -96,7 +96,7 @@
 				action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp" >
 				<input name="bean" type="hidden" value="topicListBean" /> 
 				
-				<div class="subTitel">Topic 
+				<div class="subTitel">Topic List
 					<input type="image"
 						onclick="setAction('forceLoadTopics', 'topicListForm');"
 						src="<%=sessionBean.getApplicationBean().getRefreshImage()%>" width="20" height="20"/>
@@ -109,10 +109,7 @@
 				
 				<button id="createTopic" type="button" class="lgButton">Create New Topic</button>		
 				
-				
-				<jsp:include page="../componentes/paginator.jsp">
-					<jsp:param name="formName" value="topicListForm"/>
-				</jsp:include> 
+			
 		
 				<div class="tableDiv double-scroll">
 					<table class="pageTable" >
@@ -139,7 +136,6 @@
 								</table>
 							</td>
 			
-							
 							<td>
 								<table class="sortTable">
 									<tr>
@@ -257,7 +253,7 @@
 							<td><label class="tableTitle">Delete</label></td>
 						</tr>	
 						
-						<% for (LGTopic topic : sessionBean.getTopicListPage().getDisplayTopicList() ) {
+						<% for (LGTopic topic : sessionBean.getTopicListPage().getCompleteTopicList() ) {
 						%>
 						<tr>
 							<td><%=topic.getId() %></td>
@@ -296,10 +292,6 @@
 				</div>
 				
 				
-				<jsp:include page="../componentes/paginator.jsp">
-					<jsp:param name="formName" value="topicListForm"/>
-				</jsp:include> 
-				
 			</form>
 		<% } %>
 		<% } %>
--- a/src/main/webapp/pages/topicPage.jsp	Fri Dec 18 11:50:24 2015 +0100
+++ b/src/main/webapp/pages/topicPage.jsp	Wed Dec 23 16:03:32 2015 +0100
@@ -3,6 +3,7 @@
 <%@page import="de.mpiwg.gazetteer.bo.LGBranch"%>
 <%@page import="org.apache.commons.lang.StringUtils"%>
 <%@page import="de.mpiwg.gazetteer.db.DBSection"%>
+<%@page import="de.mpiwg.gazetteer.db.DBBook"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 <jsp:useBean id="sessionBean" class="de.mpiwg.web.jsp.SessionBean" scope="session" />
 
@@ -12,9 +13,19 @@
 	<jsp:include page="../componentes/headContent.jsp"/>	
 	
 	<script>
+	
 		  $(function() {
-			  
-			    $( "#dialogDataverse" ).dialog({
+			  $("#showPendingButton").click(function() {  
+				  if($('#pendingBooks').css('display') == 'none'){ 
+					   $('#pendingBooks').show(); 
+					   $("#showPendingButton").text('Hide Missing Books');
+					} else { 
+					   $('#pendingBooks').hide();
+					   $("#showPendingButton").text('Show Missing Books');
+					}
+			  });
+			 
+			  	$( "#dialogDataverse" ).dialog({
 			        autoOpen: false,
 			        modal: true,
 			        width: 600,
@@ -70,10 +81,7 @@
 				sessionBean.getTopicPage().loadTopic(request.getParameter("topicId"));
 			} %>
 			
-			<% if(sessionBean.getTopicPage().getCompleteSectionList().isEmpty()) { %>
-				<label>Task not found!</label>
-				
-			<% } else { %>
+			
 			
 				<div id="dialogAddContributors" title="Select a new Contributors:">
 					<form name="contributorsForm" id="contributorsForm"
@@ -94,7 +102,13 @@
 				
 				<!-- Topic Detail -->
 				<div>
-					<label class="subTitel">Topic "<%=sessionBean.getTopicPage().getTopic().getNameEn() %> (<%=sessionBean.getTopicPage().getTopic().getNameCh()%>)" Details </label>
+					<label class="subTitel">Topic "<%=sessionBean.getTopicPage().getTopic().getNameEn() %> (<%=sessionBean.getTopicPage().getTopic().getNameCh()%>)"</label>
+					<form name="topicForm"
+						action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
+						method="post">
+						<input name="bean" type="hidden" value="topicBean" />
+						<input name="topicId" type="hidden" value="<%=sessionBean.getTopicPage().getTopicId()%>" />
+									
 					
 					<table class="tableComponent">
 						<tr>
@@ -116,17 +130,21 @@
 						<tr>
 							<td><label>Description</label></td>
 							<td>
-								<form name="topicForm"
-									action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
-									method="post">
-									<input name="bean" type="hidden" value="topicBean" />
-									<input name="topicId" type="hidden" value="<%=sessionBean.getTopicPage().getTopicId()%>" />
-									<input type="text" name="description" size="60" maxlength="250" value="<%=sessionBean.getTopicPage().getTopic().getDescription() %>" />
-									<input type="image" alt="edit description" onclick="setAction('updateDescription', 'topicForm');" 
-										src="<%=sessionBean.getApplicationBean().getSaveImage()%>" width="15" height="15"/>	
-								
-								</form>
+								<input type="text" name="description" size="60" maxlength="250" value="<%=sessionBean.getTopicPage().getTopic().getDescription() %>" />
+								<input type="image" alt="edit description" onclick="setAction('updateDescription', 'topicForm');" 
+									src="<%=sessionBean.getApplicationBean().getSaveImage()%>" width="15" height="15"/>	
+						
 							</td>
+						</tr>
+						<tr>
+							<td><label>Searching Keywords(separated by ",")</label></td>
+							<td>
+								<input type="text" name="keywords" size="60" maxlength="250" value="<%=sessionBean.getTopicPage().getTopic().getKeywords() %>" />
+								<input type="image" alt="edit keywords" onclick="setAction('updateKeywords', 'topicForm');" 
+									src="<%=sessionBean.getApplicationBean().getSaveImage()%>" width="15" height="15"/>	
+						
+							</td>
+						</tr>
 						<tr>
 							<td><label>Created</label></td>
 							<td><label><%=sessionBean.getTopicPage().getTopic().getFomattedCreation() %></label></td>
@@ -149,8 +167,6 @@
 												action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
 												method="post">
 												<input name="bean" type="hidden" value="topicBean" />
-												<input name="topicId" type="hidden" value="<%=sessionBean.getTopicPage().getTopicId()%>" />
-						
 												<table style="width: 300px;" class="pageTable">
 													<% for(VDCUser contr : sessionBean.getTopicPage().getContributors()) { %>
 														<tr>
@@ -173,26 +189,79 @@
 							</td>
 						</tr>
 					</table>
+					</form>
 				</div>
 				
 				
+						
+				<div>		
+					<button id="showPendingButton" type="button" class="lgButton" >Show Missing Books</button>
 				
-				<!-- Sections in Topic -->
-				
-				<div>
 					<form name="topicSectionRelationForm"
 						action="<%=sessionBean.getApplicationBean().getRootServer()%>/proxy.jsp"
 						method="post">
 						<input name="bean" type="hidden" value="topicBean" />
 						<input name="topicId" type="hidden" value="<%=sessionBean.getTopicPage().getTopicId()%>" />
 						
+						<div id="pendingBooks" style="display:none">
+							<label class="subTitel"><%=sessionBean.getTopicPage().getPendingBookList().size()%> book(s) not in the topic.</label>
+					
+							<div class="tableDiv double-scroll" >
+								<table class="pageTable">
+									<tr>
+										<th><label class="tableTitle">Book Id</label></th>
+										<th><label class="tableTitle">Book Name</label></th>
+										<th><label class="tableTitle">Level 1</label></th>
+										<th><label class="tableTitle">Level 2</label></th>
+										<th><label class="tableTitle">Dynasty</label></th>
+										<th><label class="tableTitle">Period</label></th>
+										<th><label class="tableTitle">Admin Type</label></th>
+										<th><label class="tableTitle">Section Name</label></th>
+										<th><label class="tableTitle">Section Pages</label></th>
+										<th><label class="tableTitle">View Text</label></th>
+										<th><label class="tableTitle">Existing Tasks</label></th>
+										<th><label class="tableTitle">Remove</label></th>
+									</tr>	
+									
+									<!-- TODO pending book list -->
+									<% for(DBBook book : sessionBean.getTopicPage().getPendingBookList() ) { %>
+									<tr>
+										<td>
+											<a href="<%=sessionBean.getApplicationBean().getTocInterfaceUrl()%>/check_sections_details.php?book_id=<%=book.getId() %>&amp;count=100&amp;sessionId=<%= session.getId()%>" target="blank">
+												<%=book.getId() %>
+											</a>	
+										</td>
+										<td><label><%= book.getName() %></label></td>
+										<td class="removedContent"><label><%= book.getLevel1() %></label></td>
+										<td class="removedContent"><label><%= book.getLevel2() %></label></td>
+										<td class="removedContent"><label><%= book.getDynasty() %></label></td>
+										<td class="removedContent"><label><%= book.getPeriod() %></label></td>
+										<td class="removedContent"><label><%= book.getAdmin_type() %></label></td>
+										<td class="removedContent"><label>-</label></td>
+										<td class="removedContent"><label>-</label></td>
+										<td class="removedContent"><label>-</label></td>
+										<td class="removedContent"><label>-</label></td>
+										<td class="removedContent"><label>-</label></td>
+									</tr>
+									
+									<% } %>
+								</table>
+							</div>
+						</div>	
 						
-						<label class="subTitel">Sections in Topic
+						<label class="subTitel"> <%=sessionBean.getTopicPage().getCompleteSectionList().size()%> section(s) in the topic
 							<input type="image"
-								onclick="setAction0('forceLoadTopicSectionRelation', 'topicSectionRelationForm');"
+								onclick="setAction('forceLoadTopicSectionRelation', 'topicSectionRelationForm');"
 								src="<%=sessionBean.getApplicationBean().getRefreshImage()%>" width="20" height="20"/>
 						</label>
-									
+						
+						<!-- Sections in Topic -->
+						<% if(sessionBean.getTopicPage().getCompleteSectionList().isEmpty()) { %>
+							<label>(No section in the topic...)</label>
+						
+						<% } else { %>
+					
+					
 						<div class="tableDiv double-scroll">
 							<table class="pageTable">
 								<tr>
@@ -475,7 +544,7 @@
 									<th><label class="tableTitle">Remove</label></th>
 								</tr>	
 								
-								<% for(DBSection section : sessionBean.getTopicPage().getDisplaySectionList() ) { %>
+								<% for(DBSection section : sessionBean.getTopicPage().getCompleteSectionList() ) { %>
 								<tr>
 									<td>
 										<a href="<%=sessionBean.getApplicationBean().getTocInterfaceUrl()%>/check_sections_details.php?book_id=<%=section.getBook().getId() %>&amp;count=100&amp;sessionId=<%= session.getId()%>" target="blank">
@@ -533,14 +602,18 @@
 											src="<%=sessionBean.getApplicationBean().getDeleteImage()%>"/>
 									</td>
 								</tr>
-								<% } %>				
+								<% } %>	
+													
 							</table>
 						</div>
+								
+						
+														
+						<% } %>
 					</form>
 				</div>
 			
-											
-			<% } %>
+			
 
 		<% } %>