/* * Copyright (C) 2005-2012 BetaCONCEPT Limited * * This file is part of Astroboa. * * Astroboa is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Astroboa is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Astroboa. If not, see <http://www.gnu.org/licenses/>. */ package org.betaconceptframework.astroboa.model.impl; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.RepositoryUser; import org.betaconceptframework.astroboa.api.model.Taxonomy; import org.betaconceptframework.astroboa.api.model.Topic; import org.betaconceptframework.astroboa.api.model.exception.CmsException; import org.betaconceptframework.astroboa.context.AstroboaClientContextHolder; import org.betaconceptframework.astroboa.model.jaxb.adapter.BooleanAdapter; import org.betaconceptframework.astroboa.model.jaxb.adapter.NumberOfChildrenAdapter; import org.betaconceptframework.astroboa.model.jaxb.adapter.RepositoryUserAdapter; import org.betaconceptframework.astroboa.model.jaxb.adapter.TaxonomyAdapter; import org.betaconceptframework.astroboa.model.jaxb.adapter.TopicAdapter; import org.betaconceptframework.astroboa.model.lazy.LazyLoader; /** * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ @XmlRootElement(name="topic") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "topicType", propOrder = { "name", "allowsReferrerContentObjects", "order", "numberOfChildren", "owner", "taxonomy", "parent", "children" }) public class TopicImpl extends LocalizableEntityImpl implements Topic, Serializable { /** * */ @XmlTransient private static final long serialVersionUID = 2829025801426584624L; @XmlAttribute private String name; /** * Used in case parent needs to be lazy loaded */ @XmlTransient private String parentId; @XmlAttribute @XmlJavaTypeAdapter(type=int.class, value=BooleanAdapter.class) private Boolean allowsReferrerContentObjects; @XmlAttribute @XmlJavaTypeAdapter(type=int.class, value=NumberOfChildrenAdapter.class) private int numberOfChildren=-1; @XmlAttribute private Long order; @XmlElement @XmlJavaTypeAdapter(value=RepositoryUserAdapter.class) private RepositoryUser owner; @XmlTransient private int numberOfContentObjectIdsWhichReferToThisTopic = -1; @XmlTransient private List<String> contentObjectIdsWhichReferToThisTopic ; /** * Parent topic */ @XmlElement( name="parentTopic" ) @XmlJavaTypeAdapter(value=TopicAdapter.class) private Topic parent; /** * Child Topics */ @XmlElementWrapper(name="childTopics") @XmlElement( name="topic", type=TopicImpl.class ) private List<Topic> children; @XmlElement @XmlJavaTypeAdapter(value=TaxonomyAdapter.class) private Taxonomy taxonomy; public TopicImpl(){ } /** * @return Returns the subTopics. */ public List<Topic> getChildren() { // Load children if not already there if (!isChildrenLoaded()) { //Continue only if there is an Id if (StringUtils.isNotBlank(getId() )) { getLazyLoader().lazyLoadTopicChildren(this, authenticationToken); } } return children; } /** * @param subTopics The subTopics to set. */ public void setChildren(List<Topic> subTopics) { this.children = subTopics; if (subTopics == null){ numberOfChildren = 0; } else{ numberOfChildren = subTopics.size(); } } /** * @return Returns the parent. */ public Topic getParent() { if (parent == null && StringUtils.isNotBlank(parentId)){ LazyLoader lazyLoader = getLazyLoader(); if (lazyLoader != null){ getLazyLoader().lazyLoadParentTopic(this, parentId, authenticationToken); } } return parent; } /** * @param parent The parent to set. */ public void setParent(Topic parent) { if (parent != null && (parent == this || ( StringUtils.equals(parent.getId(), this.getId()) && parent.getId() != null )|| ( StringUtils.equals(parent.getName(), this.getName()) && parent.getName() != null) ) ){ throw new CmsException("Topic "+getId() + " : "+getName() + " cannot have itself as a parent"); } this.parent = parent; if (parent != null && parent.getId() != null){ this.parentId = parent.getId(); } else{ //Nullify parentId as well this.parentId = null; } } public void addChild(Topic child){ if (child == null){ return; } if (child != null && (child == this || ( StringUtils.equals(child.getId(), this.getId()) && child.getId() != null )|| ( StringUtils.equals(child.getName(), this.getName()) && child.getName() != null) ) ){ throw new CmsException("Topic "+getId() + " : "+getName() + " cannot have itself as a child"); } if (children == null){ children = new ArrayList<Topic>(); } //add child only if it has not been added. if (!children.contains(child)){ children.add(child); } child.setParent(this); numberOfChildren = children.size(); } public RepositoryUser getOwner() { return owner; } public void setOwner(RepositoryUser owner) { this.owner = owner; } public int getNumberOfChildren() { if (numberOfChildren < 0 && children != null){ numberOfChildren = children.size(); } if (numberOfChildren < 0){ return 0; } return numberOfChildren; } public void setNumberOfChildren(int numberOfChildren) { this.numberOfChildren = numberOfChildren; } /** * @return the taxonomy */ public Taxonomy getTaxonomy() { return taxonomy; } /** * @param taxonomy the taxonomy to set */ public void setTaxonomy(Taxonomy taxonomy) { this.taxonomy = taxonomy; //If there are children then children should have the same taxonomy if (CollectionUtils.isNotEmpty(children)){ for (Topic child : children){ Taxonomy childTaxonomy = child.getTaxonomy(); //Both are null, thus they are the same so continue with the other children if (childTaxonomy == null && taxonomy == null){ continue; } //One of them is null therefore change child's taxonomy if ( childTaxonomy == null || taxonomy == null){ child.setTaxonomy(taxonomy); } else{ //They are both not null //If they are the same continue with the other children if (childTaxonomy == taxonomy){ continue; } else { //If no ids are provided check with their names if (childTaxonomy.getId() == null && taxonomy.getId() == null){ //Both have the same name so continue with the other children if (StringUtils.equals(childTaxonomy.getName(), taxonomy.getName())){ continue; } else{ //Their names differ, thus change child's taxonomy child.setTaxonomy(taxonomy); } } else{ //One or both ids are not null. If they are the same, continue with the other children if (StringUtils.equals(childTaxonomy.getId(), taxonomy.getId())){ continue; } else{ //Different ids, change child's taxonomy child.setTaxonomy(taxonomy); } } } } } } } public Long getOrder() { return order; } public void setOrder(Long order) { this.order = order; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isAllowsReferrerContentObjects() { return allowsReferrerContentObjects != null && allowsReferrerContentObjects; } public void setAllowsReferrerContentObjects( boolean allowsReferrerContentObjects) { this.allowsReferrerContentObjects = allowsReferrerContentObjects; } public void setNumberOfContentObjectIdsWhichReferToThisTopic(int numberOfContentObjectIdsWhichReferToThisTopic) { this.numberOfContentObjectIdsWhichReferToThisTopic = numberOfContentObjectIdsWhichReferToThisTopic; } public void setContentObjectIdsWhichReferToThisTopic(List<String> contentObjectIdsWhichReferToThisTopic) { this.contentObjectIdsWhichReferToThisTopic = contentObjectIdsWhichReferToThisTopic; } public void addContentObjectIdWhichReferToThisTopic(String contentObjectIdWhichReferToThisTopic) { if (contentObjectIdWhichReferToThisTopic != null){ if (contentObjectIdsWhichReferToThisTopic == null) contentObjectIdsWhichReferToThisTopic = new ArrayList<String>(); contentObjectIdsWhichReferToThisTopic.add(contentObjectIdWhichReferToThisTopic); } } public boolean isChildrenLoaded() { return children != null; } private LazyLoader getLazyLoader() { return AstroboaClientContextHolder.getLazyLoaderForClient(authenticationToken); } public void setParentId(String parentId){ this.parentId = parentId; } public void detectCycle(String name) { if (name == null){ if (parent != null){ ((TopicImpl)parent).detectCycle(this.name); } } else{ if (StringUtils.equals(this.name, name)){ throw new CmsException("Topic with name "+name+ " exists more than once in topic hierarchy"); } else if (parent != null){ ((TopicImpl)parent).detectCycle(name); } } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("TopicImpl ["); if (name != null) builder.append("name=").append(name); if (getId() != null) builder.append(", ").append("id=").append(getId()); if (taxonomy != null) builder.append(", ").append("taxonomy=").append(taxonomy.toString()); builder.append("]"); return builder.toString(); } @Override public boolean areContenObjectIdsWhichReferToThisTopicLoaded() { return contentObjectIdsWhichReferToThisTopic != null; } @Override public List<String> getContentObjectIdsWhichReferToThisTopic() { if (!areContenObjectIdsWhichReferToThisTopicLoaded()){ if (StringUtils.isNotBlank(getId())){ getLazyLoader().lazyLoadContentObjectIdsWhichReferToTopic(this, authenticationToken); } } return contentObjectIdsWhichReferToThisTopic; } @Override public int getNumberOfContentObjectsWhichReferToThisTopic() { if (!isNumberOfContentObjectsWhichReferToThisTopicLoaded()){ if (StringUtils.isNotBlank(getId())){ getLazyLoader().lazyLoadNumberOfContentObjectIdsWhichReferToTopic(this, authenticationToken); } } return numberOfContentObjectIdsWhichReferToThisTopic == -1 ? 0: numberOfContentObjectIdsWhichReferToThisTopic; } @Override public boolean isNumberOfContentObjectsWhichReferToThisTopicLoaded() { return numberOfContentObjectIdsWhichReferToThisTopic != -1; } public boolean allowsReferrerContentObjectsHasBeenSet() { return allowsReferrerContentObjects != null; } }