.get(language);
if (existingVanityUrls == null) {
existingMappings.put(language,
new HashMap<String, VanityUrl>());
}
VanityUrl vanityUrl = populateJCRData(currentNode,
new VanityUrl());
existingMappings.get(language).put(currentNode.getName(), vanityUrl);
if (currentNode.getProperty(PROPERTY_DEFAULT).getBoolean()) {
oldDefaultMappings.put(language, new DefaultKeyValue(
currentNode.getName(), vanityUrl));
}
}
}
}
// as next we need to find out, which mappings need to be updated or added and
// get the collection of new default mappings.
List<VanityUrl> toAdd = new ArrayList<VanityUrl>();
Map<String, VanityUrl> toUpdate = new HashMap<String, VanityUrl>();
Map<String, VanityUrl> newDefaultMappings = new HashMap<String, VanityUrl>();
for (VanityUrl vanityUrl : vanityUrls) {
if (vanityUrl.isDefaultMapping()) {
VanityUrl otherDefaultMapping = newDefaultMappings.put(
vanityUrl.getLanguage(), vanityUrl);
if (otherDefaultMapping != null) {
throw new ConstraintViolationException(
"Two mappings are set as default for the same language: "
+ vanityUrl.getUrl() + " and "
+ otherDefaultMapping.getUrl()
+ " for language: "
+ vanityUrl.getLanguage(), null);
}
}
boolean found = false;
Map<String, VanityUrl> mappings = existingMappings.get(vanityUrl
.getLanguage());
if (mappings != null) {
for (Map.Entry<String, VanityUrl> entry : mappings.entrySet()) {
if (entry.getValue().equals(vanityUrl)) {
mappings.remove(entry.getKey());
found = true;
if (entry.getValue().isActive() != vanityUrl.isActive()
|| entry.getValue().isDefaultMapping() != vanityUrl
.isDefaultMapping()) {
vanityUrl.setIdentifier(entry.getValue()
.getIdentifier());
toUpdate.put(entry.getKey(), vanityUrl);
}
break;
}
}
}
if (!found) {
toAdd.add(vanityUrl);
}
}
// Compare the new default settings with the old ones to see which mapping should
// be default. Also consider the case, that in the new collection none is set to
// default, then we take the previous default one or if there was also no default,
// then the first found mapping for a language will be default.
if (!newDefaultMappings.keySet().containsAll(updatedLocales)) {
for (String locale : updatedLocales) {
if (!newDefaultMappings.containsKey(locale)) {
boolean defaultWasSet = false;
VanityUrl oldDefaultVanityUrl = null;
if (oldDefaultMappings.get(locale) != null) {
oldDefaultVanityUrl = (VanityUrl) oldDefaultMappings
.get(locale).getValue();
for (Map.Entry<String, VanityUrl> entry : toUpdate
.entrySet()) {
VanityUrl vanityUrl = entry.getValue();
if (vanityUrl.equals(oldDefaultVanityUrl)) {
vanityUrl.setDefaultMapping(true);
newDefaultMappings.put(locale, vanityUrl);
defaultWasSet = true;
}
}
}
if (!defaultWasSet) {
for (VanityUrl vanityUrl : vanityUrls) {
if (locale.equals(vanityUrl.getLanguage())) {
vanityUrl.setDefaultMapping(true);
newDefaultMappings.put(locale, vanityUrl);
break;
}
}
}
}
}
}
// At last we need to see, which mappings are no longer existing in the new collection,
// which means that they need to be completely removed
List<Map.Entry<String, VanityUrl>> toDelete = new ArrayList<Map.Entry<String, VanityUrl>>();
for (Map<String, VanityUrl> existingVanityUrls : existingMappings
.values()) {
toDelete.addAll(existingVanityUrls.entrySet());
}
// Compare the new default settings with the old ones to know if the default flag needs
// to be set to false for the previous default.
List<String> removeDefaultMapping = new ArrayList<String>();
for (Map.Entry<String, KeyValue> oldDefaultMapping : oldDefaultMappings
.entrySet()) {
VanityUrl oldDefaultVanityUrl = (VanityUrl) oldDefaultMapping
.getValue().getValue();
VanityUrl newDefaultVanityUrl = newDefaultMappings
.get(oldDefaultMapping.getKey());
if (!oldDefaultVanityUrl.equals(newDefaultVanityUrl)) {
boolean oldDefaultWillBeDeleted = false;
for (Map.Entry<String, VanityUrl> entry : toDelete) {
if (oldDefaultVanityUrl.equals(entry.getValue())) {
oldDefaultWillBeDeleted = true;
break;
}
}
if (!(oldDefaultWillBeDeleted || toUpdate.entrySet().contains(
oldDefaultVanityUrl))) {
removeDefaultMapping.add((String) oldDefaultMapping
.getValue().getKey());
}
}
}
// Check if the added vanity URLs are really unique for the site
for (VanityUrl vanityUrl : toAdd) {
checkUniqueConstraint(contentNode, vanityUrl, toDelete, session);
}
// If there is no change do nothing otherwise do all the operations and
// save the session
if (toUpdate.isEmpty() && toAdd.isEmpty() && toDelete.isEmpty()) {
return false;
} else {
session.checkout(vanityUrlMappingsNode);
for (Map.Entry<String, VanityUrl> entry : toUpdate.entrySet()) {
JCRNodeWrapper vanityUrlNode = vanityUrlMappingsNode
.getNode(entry.getKey());
VanityUrl vanityUrl = entry.getValue();
session.checkout(vanityUrlNode);
vanityUrlNode
.setProperty(PROPERTY_ACTIVE, vanityUrl.isActive());
vanityUrlNode.setProperty(PROPERTY_DEFAULT, vanityUrl
.isDefaultMapping());
}
for (String index : removeDefaultMapping) {
JCRNodeWrapper vanityUrlNode = vanityUrlMappingsNode
.getNode(index);
session.checkout(vanityUrlNode);
vanityUrlNode.setProperty(PROPERTY_DEFAULT, false);
}
for (Map.Entry<String, VanityUrl> entry : toDelete) {
JCRNodeWrapper vanityUrlNode = vanityUrlMappingsNode
.getNode(entry.getKey());
session.checkout(vanityUrlNode);
vanityUrlNode.remove();
}
for (VanityUrl vanityUrl : toAdd) {
JCRNodeWrapper vanityUrlNode = vanityUrlMappingsNode.addNode(
JCRContentUtils.escapeLocalNodeName(vanityUrl.getUrl()), JAHIANT_VANITYURL);
session.checkout(vanityUrlNode);
vanityUrlNode.setProperty(PROPERTY_URL, vanityUrl.getUrl());
vanityUrlNode
.setProperty(JCR_LANGUAGE, vanityUrl.getLanguage());
vanityUrlNode
.setProperty(PROPERTY_ACTIVE, vanityUrl.isActive());
vanityUrlNode.setProperty(PROPERTY_DEFAULT, vanityUrl
.isDefaultMapping());
}
session.save();
}
return true;