001 package org.mycore.datamodel.classifications;
002
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.HashMap;
006 import java.util.HashSet;
007 import java.util.Iterator;
008 import java.util.Set;
009
010 import org.apache.log4j.Logger;
011
012 import org.mycore.common.MCRSessionMgr;
013 import org.mycore.datamodel.classifications2.MCRCategLinkService;
014 import org.mycore.datamodel.classifications2.MCRCategLinkServiceFactory;
015 import org.mycore.datamodel.classifications2.MCRCategory;
016 import org.mycore.datamodel.classifications2.MCRCategoryDAO;
017 import org.mycore.datamodel.classifications2.MCRCategoryDAOFactory;
018 import org.mycore.datamodel.classifications2.MCRCategoryID;
019 import org.mycore.frontend.cli.MCRObjectCommands;
020
021 /**
022 * @author Radi Radichev
023 *
024 */
025
026 public class MCRClassificationPool {
027
028 /**
029 * stores all edited classifications
030 */
031 private HashMap<MCRCategoryID, MCRCategory> classifications = new HashMap<MCRCategoryID, MCRCategory>();
032
033 private HashSet<MCRCategoryID> movedCategories = new HashSet<MCRCategoryID>();
034
035 static Logger LOGGER = Logger.getLogger(MCRClassificationPool.class);
036
037 private static MCRCategoryDAO DAO = MCRCategoryDAOFactory.getInstance();
038
039 public MCRClassificationPool() {
040 //store reference of classifications in current session
041 MCRSessionMgr.getCurrentSession().put("classifications", classifications); // Put
042 }
043
044 /**
045 * This method returns all ClassificationIDs. From the database and pool
046 * together.
047 *
048 * @return
049 */
050 public Set<MCRCategoryID> getAllIDs() {
051 Set<MCRCategoryID> ids = new HashSet<MCRCategoryID>();
052 ids.addAll(DAO.getRootCategoryIDs());
053 ids.addAll(classifications.keySet());
054 return ids;
055 }
056
057 /**
058 * Save all changes to the database.
059 *
060 * @return
061 */
062 public boolean saveAll() {
063 synchronized (classifications) {
064 HashMap<MCRCategoryID, MCRCategory> classCopy = new HashMap<MCRCategoryID, MCRCategory>();
065 classCopy.putAll(classifications);
066 Iterator<MCRCategory> rootCategories = classifications.values().iterator();
067 try {
068 while (rootCategories.hasNext()) {
069 MCRCategory clas = rootCategories.next();
070 LOGGER.debug("Classification to be saved: " + clas.getId());
071 if (DAO.exist(clas.getId())) {
072 DAO.replaceCategory(clas);
073 } else {
074 DAO.addCategory(null, clas);
075 }
076 rootCategories.remove();
077 }
078 } catch (Exception e) {
079 LOGGER.warn("Error while saving all classifications.", e);
080 return false;
081 }
082 LOGGER.debug("Getting all categories that where moved to left or right");
083 HashSet<MCRCategoryID> modifiedCategories = new HashSet<MCRCategoryID>();
084 for (MCRCategoryID categID : getMovedCategories()) {
085 LOGGER.debug("Getting sub categories of "+categID);
086 MCRCategory cat = findCategory(classCopy.get(MCRCategoryID.rootID(categID.getRootID())), categID);
087 modifiedCategories.addAll(getSubTree(cat));
088 }
089 LOGGER.debug("Getting all objects that where affected my category movements");
090 HashSet<String> linkedObjects = new HashSet<String>();
091 MCRCategLinkService linkService = MCRCategLinkServiceFactory.getInstance();
092 for (MCRCategoryID cat:modifiedCategories){
093 LOGGER.debug("Getting linked objects for "+cat);
094 linkedObjects.addAll(linkService.getLinksFromCategory(cat));
095 }
096 for (String objectID:linkedObjects){
097 MCRObjectCommands.repairMetadataSearchForID(objectID);
098 }
099 movedCategories.clear();
100 }
101 return true;
102 }
103
104 private static Collection<MCRCategoryID> getSubTree(MCRCategory subTreeNode) {
105 ArrayList<MCRCategoryID> children = new ArrayList<MCRCategoryID>();
106 children.add(subTreeNode.getId());
107 for (MCRCategory child : subTreeNode.getChildren()) {
108 children.addAll(getSubTree(child));
109 }
110 return children;
111 }
112
113 private static MCRCategory findCategory(MCRCategory parent, MCRCategoryID id) {
114 MCRCategory found = null;
115 for (MCRCategory cat : parent.getChildren()) {
116 if (cat.getId().equals(id)) {
117 found = cat;
118 LOGGER.debug("Found Category: " + found.getId().getID());
119 break;
120 }
121 MCRCategory rFound = findCategory(cat, id);
122 if (rFound != null) {
123 found = rFound;
124 break;
125 }
126 }
127
128 return found;
129 }
130
131 /**
132 * Cancel all changes. Clear the hashtable.
133 *
134 * @return
135 */
136 public boolean purgeAll() {
137
138 LOGGER.debug("Purging all in progress...");
139 synchronized (classifications) {
140 classifications.clear();
141 movedCategories.clear();
142 }
143 return true;
144 }
145
146 /**
147 * Check if the Classification with classID is already edited and in the
148 * session.
149 *
150 * @param classID
151 * Classification ID to check for
152 * @return <code>true</code> when Classification is edited,
153 * <code>false</code> when not.
154 */
155 public boolean isEdited(MCRCategoryID classID) {
156 return classifications.containsKey(classID);
157 }
158
159 /**
160 * Put the classification in the Session. This method is executed every time
161 * a Classification or a Category is edited
162 *
163 * @param cl
164 * Classification to be stored in the session.
165 */
166 public void updateClassification(MCRCategory cl) {
167 classifications.put(cl.getId(), cl);
168 LOGGER.info("Classification: " + cl.getId() + " added to session!");
169 }
170
171 /**
172 * Delete a classfication from the pool
173 * @param cl
174 */
175 public void deleteClassification(MCRCategoryID cl) {
176 if (classifications.containsKey(cl))
177 classifications.remove(cl);
178 }
179
180 /**
181 * This method checks to see if the classification which is expected is in
182 * the Session (when edited) or it takes the classification from the
183 * database
184 *
185 * @param clid
186 * @param writeAccess
187 * @return MCRCategory classif
188 */
189
190 public MCRCategory getClassificationAsPojo(MCRCategoryID clid, boolean writeAccess) {
191 MCRCategory classif = classifications.get(clid);
192 if (classif != null) {
193 return classif;
194 } else {
195 MCRCategory cl = DAO.getCategory(clid, writeAccess ? -1 : 0);
196 return cl;
197 }
198 }
199
200 public HashSet<MCRCategoryID> getMovedCategories() {
201 return movedCategories;
202 }
203
204 }