// © 2014 by IT-Power GmbH (http://www.it-power.org) package de.knurt.fam.core.model.config; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Observable; import java.util.Observer; import org.apache.commons.lang.StringUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import de.knurt.fam.core.aspects.logging.FamLog; import de.knurt.fam.core.model.persist.ContactDetail; import de.knurt.fam.core.model.persist.LogbookEntry; import de.knurt.fam.core.model.persist.User; import de.knurt.fam.core.persistence.dao.FamDaoProxy; import de.knurt.fam.core.persistence.dao.config.RoleConfigDao; import de.knurt.fam.core.util.JSONFactory; /** * COMMENTME * * @author itp1dol * @since 06.03.2014 */ public class LogbookUserObserver extends Logbook implements Observer { public void setObservable(Observable observable) { observable.addObserver(this); } private boolean is(Object obj, Class<?> clazz) { return obj.getClass().equals(clazz); } /** * return an {@link LogbookEntry} with an admin as author, current date, english as language. * * @since 06.03.2014 * @return base {@link LogbookEntry} for all entries made here */ private LogbookEntry getNewBaseEntry() { LogbookEntry result = new LogbookEntry(); result.setOfUserName(RoleConfigDao.getInstance().getUsernamesOfAdmins()[0]); result.setLogbookId(this.getKey()); result.setTagsFromCsv("system"); result.setDate(); result.setLanguage(Locale.ENGLISH); return result; } private LogbookEntry getEntryForUserNew(User newUser) { LogbookEntry result = this.getNewBaseEntry(); result.setHeadline("New user: " + newUser.getUsername()); result.setContent(String.format("%s was inserted with the role %s", newUser.getFullName(), newUser.getRoleLabel())); return result; } private LogbookEntry getEntryForUserAnonymized(String username) { LogbookEntry result = this.getNewBaseEntry(); result.setHeadline("Anonymized user" + username); result.setContent(String.format("%s is anonym now", username)); return result; } private LogbookEntry getEntryForUserDeleted(User user) { LogbookEntry result = this.getNewBaseEntry(); result.setHeadline("Deleted user: " + user.getUsername()); result.setContent(String.format("%s was deleted", user.getFullName())); return result; } /** {@inheritDoc} */ @Override public void update(Observable userDao, Object object) { LogbookEntry newEntry = null; if (this.is(object, User.class)) { User user = (User) object; if (user.hasBeenAnonymized()) { newEntry = this.getEntryForUserAnonymized(user.getUsernameBeforeAnonym()); } else if (user.hasJustBeenInserted()) { // a new user was inserted newEntry = this.getEntryForUserNew(user); } else if (user.hasJustBeenDeleted()) { newEntry = this.getEntryForUserDeleted(user); } else { User old = FamDaoProxy.userDao().getUserFromUsername(user.getUsername()); newEntry = this.getEntryForUserUpdate(old, user); } } else if (this.is(object, ContactDetail.class)) { ContactDetail cd = (ContactDetail) object; newEntry = this.getEntryForContactDetails(cd); } if (newEntry != null) { newEntry.insert(); } else { FamLog.error("observed an unknown event: " + object.getClass(), 201403061006l); } } private LogbookEntry getEntryForContactDetails(ContactDetail cd) { LogbookEntry result = this.getNewBaseEntry(); result.setHeadline("contact details changed of user " + cd.getUsername()); result.setContent(String.format("%s: %s", cd.getTitle(), cd.getDetail())); return result; } private boolean isJSONObject(JSONObject subject, String key) { boolean result = true; try { subject.getJSONObject(key); } catch (JSONException e) { result = false; } return result; } private boolean isJSONArray(JSONObject json, String key) { boolean result = true; try { json.getJSONArray(key); } catch (JSONException e) { result = false; } return result; } private List<String> getBeforeAfterMessages(JSONArray newJson, JSONArray oldJson) throws JSONException { List<String> result = new ArrayList<String>(); int i = 0; while (i < newJson.length()) { if (oldJson.length() < i) { result.add("a new value: " + newJson.get(i)); } else if (this.isJSONObject(newJson, i)) { result.addAll(this.getBeforeAfterMessages(newJson.getJSONObject(i), oldJson.getJSONObject(i))); } else if (this.isJSONArray(newJson, i)) { result.addAll(this.getBeforeAfterMessages(newJson.getJSONArray(i), oldJson.getJSONArray(i))); } else if (!newJson.equals(oldJson)) { result.add(this.getMessage(newJson, oldJson, i)); } i++; } return result; } private boolean isJSONObject(JSONArray json, int i) { boolean result = true; try { json.getJSONObject(i); } catch (JSONException e) { result = false; } return result; } private boolean isJSONArray(JSONArray json, int i) { boolean result = true; try { json.getJSONArray(i); } catch (JSONException e) { result = false; } return result; } private String getMessage(String oldValue, String newValue, String key) { String result = null; if (oldValue.isEmpty()) { result = String.format("added value for %s: %s", key, newValue); } else { result = String.format("changed value of %s from %s to %s", key, oldValue, newValue); } return result; } private String getMessage(JSONObject jsonNew, JSONObject jsonOld, String key) throws JSONException { return this.getMessage(jsonOld.getString(key), jsonNew.getString(key), key); } private String getMessage(JSONArray jsonNew, JSONArray jsonOld, int key) throws JSONException { return this.getMessage(jsonOld.getString(key), jsonNew.getString(key), key + ""); } /** * CODESMELL this has nothing to do with this logbook (but it is used) * * @since 06.03.2014 * @param newJson * @param oldJson * @return * @throws JSONException */ private List<String> getBeforeAfterMessages(JSONObject newJson, JSONObject oldJson) throws JSONException { List<String> result = new ArrayList<String>(); Iterator<?> keyIterator = newJson.keys(); while (keyIterator.hasNext()) { String jsonKey = (String) keyIterator.next(); if (oldJson.has(jsonKey) == false) { result.add("a new field " + jsonKey + " = " + newJson.get(jsonKey).toString()); } else if (this.isJSONObject(newJson, jsonKey)) { result.addAll(this.getBeforeAfterMessages(newJson.getJSONObject(jsonKey), oldJson.getJSONObject(jsonKey))); } else if (this.isJSONArray(newJson, jsonKey)) { result.addAll(this.getBeforeAfterMessages(newJson.getJSONArray(jsonKey), oldJson.getJSONArray(jsonKey))); } else if (!newJson.getString(jsonKey).equals(oldJson.getString(jsonKey))) { result.add(this.getMessage(newJson, oldJson, jsonKey)); } } return result; } private LogbookEntry getEntryForUserUpdate(User oldUser, User newUser) { LogbookEntry result = this.getNewBaseEntry(); result.setHeadline("Update user: " + newUser.getUsername()); List<String> messages = new ArrayList<String>(); try { JSONObject newUserJson = JSONFactory.me().getUser(newUser); JSONObject oldUserJson = JSONFactory.me().getUser(oldUser); messages.addAll(this.getBeforeAfterMessages(newUserJson, oldUserJson)); } catch (JSONException e) { FamLog.exception(e, 201402061143l); messages.add("please report error 201402061143"); } result.setContent(StringUtils.join(messages.toArray(), "\r\n")); // FIXME check delimiter return result; } public List<LogbookEntry> getAllEntries() { LogbookEntry le = new LogbookEntry(); le.setLogbookId(this.getKey()); return FamDaoProxy.logbookEntryDao().getObjectsLike(le); } }