/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.core.internal.dom;
import static org.xmind.core.internal.dom.DOMConstants.ATTR_ID;
import static org.xmind.core.internal.dom.DOMConstants.ATTR_STYLE_ID;
import static org.xmind.core.internal.dom.DOMConstants.ATTR_THEME;
import static org.xmind.core.internal.dom.DOMConstants.TAG_RELATIONSHIP;
import static org.xmind.core.internal.dom.DOMConstants.TAG_RELATIONSHIPS;
import static org.xmind.core.internal.dom.DOMConstants.TAG_TITLE;
import static org.xmind.core.internal.dom.DOMConstants.TAG_TOPIC;
import java.util.Collections;
import java.util.Set;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xmind.core.Core;
import org.xmind.core.ILegend;
import org.xmind.core.IRelationship;
import org.xmind.core.ITopic;
import org.xmind.core.IWorkbook;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventRegistration;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.core.event.ICoreEventSupport;
import org.xmind.core.internal.Sheet;
import org.xmind.core.internal.event.CoreEventSupport;
import org.xmind.core.util.DOMUtils;
import org.xmind.core.util.ILabelRefCounter;
import org.xmind.core.util.IMarkerRefCounter;
/**
* @author briansun
*
*/
public class SheetImpl extends Sheet implements ICoreEventSource {
private static final Set<IRelationship> NO_RELATIONSHIPS = Collections
.emptySet();
private Element implementation;
private WorkbookImpl ownedWorkbook;
private SheetMarkerRefCounter markerRefCounter = null;
private SheetLabelRefCounter labelRefCounter = null;
private LegendImpl legend = null;
private CoreEventSupport coreEventSupport = null;
/**
* @param implementation
*/
public SheetImpl(Element implementation, WorkbookImpl ownedWorkbook) {
super();
this.ownedWorkbook = ownedWorkbook;
this.implementation = DOMUtils.addIdAttribute(implementation);
DOMUtils.ensureChildElement(implementation, TAG_TOPIC);
//((TopicImpl) getRootTopic()).addNotify(ownedWorkbook, this, null);
}
/**
* @return the implementation
*/
public Element getImplementation() {
return implementation;
}
public int hashCode() {
return implementation.hashCode();
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null || !(obj instanceof SheetImpl))
return false;
SheetImpl t = (SheetImpl) obj;
return implementation == t.implementation;
}
public String toString() {
return "SHT#" + getId() + "(" + getTitleText() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public Object getAdapter(Class adapter) {
if (adapter == Element.class || adapter == Node.class) {
return implementation;
} else if (adapter == IMarkerRefCounter.class) {
return getMarkerRefCounter();
} else if (adapter == ILabelRefCounter.class) {
return getLabelRefCounter();
} else if (adapter == ICoreEventSupport.class) {
return getCoreEventSupport();
}
return super.getAdapter(adapter);
}
/**
* @see org.xmind.core.internal.Sheet#getLocalTitleText()
*/
@Override
protected String getLocalTitleText() {
return DOMUtils.getTextContentByTag(implementation, TAG_TITLE);
}
/**
* @see org.xmind.core.ITitled#setTitleText(java.lang.String)
*/
public void setTitleText(String titleText) {
String oldValue = getLocalTitleText();
DOMUtils.setText(implementation, TAG_TITLE, titleText);
String newValue = getLocalTitleText();
fireValueChange(Core.TitleText, oldValue, newValue);
updateModifiedTime();
}
/**
* @see org.xmind.core.ISheet#getRootTopic()
*/
public ITopic getRootTopic() {
Element t = DOMUtils.getFirstChildElementByTag(implementation,
TAG_TOPIC);
return (ITopic) ownedWorkbook.getAdaptableRegistry().getAdaptable(t);
}
/**
* @see org.xmind.core.ISheet#getId()
*/
public String getId() {
return implementation.getAttribute(ATTR_ID);
}
public IWorkbook getOwnedWorkbook() {
return ownedWorkbook;
}
/*
* (non-Javadoc)
*
* @see org.xmind.core.IWorkbookComponent#isOrphan()
*/
public boolean isOrphan() {
return DOMUtils.isOrphanNode(implementation);
}
/**
* @see org.xmind.core.ISheet#getParent()
*/
public IWorkbook getParent() {
Node p = implementation.getParentNode();
if (p == ownedWorkbook.getWorkbookElement())
return ownedWorkbook;
return null;
}
/**
* @see org.xmind.core.ISheet#getIndex()
*/
public int getIndex() {
Node p = implementation.getParentNode();
if (p == ownedWorkbook.getWorkbookElement()) {
return DOMUtils.getElementIndex(p, DOMConstants.TAG_SHEET,
implementation);
}
return -1;
}
/**
* @see org.xmind.core.ISheet#getRelationships()
*/
public Set<IRelationship> getRelationships() {
Element rs = DOMUtils.getFirstChildElementByTag(implementation,
TAG_RELATIONSHIPS);
if (rs != null)
return DOMUtils.getChildSet(rs, TAG_RELATIONSHIP,
ownedWorkbook.getAdaptableRegistry());
return NO_RELATIONSHIPS;
}
/**
* @see org.xmind.core.ISheet#addRelationship(org.xmind.core.IRelationship)
*/
public void addRelationship(IRelationship rel) {
Element rs = DOMUtils.ensureChildElement(implementation,
TAG_RELATIONSHIPS);
Element r = ((RelationshipImpl) rel).getImplementation();
Node n = rs.appendChild(r);
if (n != null) {
if (!isOrphan()) {
((RelationshipImpl) rel).addNotify(ownedWorkbook, this);
}
fireTargetChange(Core.RelationshipAdd, rel);
}
}
/**
* @see org.xmind.core.ISheet#removeRelationship(org.xmind.core.IRelationship)
*/
public void removeRelationship(IRelationship rel) {
Element rs = DOMUtils.getFirstChildElementByTag(implementation,
TAG_RELATIONSHIPS);
if (rs != null) {
if (!isOrphan()) {
((RelationshipImpl) rel).removeNotify(ownedWorkbook, this);
}
Element r = ((RelationshipImpl) rel).getImplementation();
Node n = rs.removeChild(r);
if (!rs.hasChildNodes())
implementation.removeChild(rs);
if (n != null) {
fireTargetChange(Core.RelationshipRemove, rel);
updateModifiedTime();
}
}
}
public String getThemeId() {
return DOMUtils.getAttribute(implementation, ATTR_THEME);
}
public void setThemeId(String themeId) {
String oldValue = getThemeId();
WorkbookImpl workbook = (WorkbookImpl) getParent();
decreaseThemeRef(workbook);
DOMUtils.setAttribute(implementation, ATTR_THEME, themeId);
increaseThemeRef(workbook);
String newValue = getThemeId();
fireValueChange(Core.ThemeId, oldValue, newValue);
updateModifiedTime();
}
public String getStyleId() {
return DOMUtils.getAttribute(implementation, ATTR_STYLE_ID);
}
public void setStyleId(String styleId) {
String oldValue = getStyleId();
WorkbookImpl workbook = (WorkbookImpl) getParent();
WorkbookUtilsImpl.decreaseStyleRef(workbook, this);
DOMUtils.setAttribute(implementation, ATTR_STYLE_ID, styleId);
WorkbookUtilsImpl.increaseStyleRef(workbook, this);
String newValue = getStyleId();
fireValueChange(Core.Style, oldValue, newValue);
updateModifiedTime();
}
public void replaceRootTopic(ITopic newRootTopic) {
TopicImpl r1 = (TopicImpl) getRootTopic();
TopicImpl r2 = (TopicImpl) newRootTopic;
if (!isOrphan()) {
r1.removeNotify((WorkbookImpl) getParent(), this, null);
}
implementation.removeChild(r1.getImplementation());
implementation.appendChild(r2.getImplementation());
if (!isOrphan()) {
r2.addNotify((WorkbookImpl) getParent(), this, null);
}
fireValueChange(Core.RootTopic, r1, r2);
updateModifiedTime();
}
public ILegend getLegend() {
if (legend == null) {
legend = new LegendImpl(implementation, this);
}
return legend;
}
public ILabelRefCounter getLabelRefCounter() {
if (labelRefCounter == null)
labelRefCounter = new SheetLabelRefCounter(this);
return labelRefCounter;
}
public IMarkerRefCounter getMarkerRefCounter() {
if (markerRefCounter == null)
markerRefCounter = new SheetMarkerRefCounter(this);
return markerRefCounter;
}
protected void addNotify(WorkbookImpl workbook) {
getImplementation().setIdAttribute(DOMConstants.ATTR_ID, true);
workbook.getAdaptableRegistry().registerById(this, getId(),
getImplementation().getOwnerDocument());
((CoreEventSupport) getCoreEventSupport()).setParent(workbook
.getCoreEventSupport());
WorkbookUtilsImpl.increaseStyleRef(workbook, this);
increaseThemeRef(workbook);
((TopicImpl) getRootTopic()).addNotify(workbook, this, null);
for (IRelationship rel : getRelationships()) {
((RelationshipImpl) rel).addNotify(workbook, this);
}
}
protected void removeNotify(WorkbookImpl workbook) {
for (IRelationship rel : getRelationships()) {
((RelationshipImpl) rel).removeNotify(workbook, this);
}
((TopicImpl) getRootTopic()).removeNotify(workbook, this, null);
decreaseThemeRef(workbook);
WorkbookUtilsImpl.decreaseStyleRef(workbook, this);
((CoreEventSupport) getCoreEventSupport()).setParent(null);
workbook.getAdaptableRegistry().unregisterById(this, getId(),
getImplementation().getOwnerDocument());
getImplementation().setIdAttribute(DOMConstants.ATTR_ID, false);
}
private void decreaseThemeRef(WorkbookImpl workbook) {
String themeId = getThemeId();
if (themeId != null)
workbook.getStyleRefCounter().decreaseRef(themeId);
}
private void increaseThemeRef(WorkbookImpl workbook) {
String themeId = getThemeId();
if (themeId != null)
workbook.getStyleRefCounter().increaseRef(themeId);
}
public ICoreEventSupport getCoreEventSupport() {
if (coreEventSupport == null) {
coreEventSupport = new CoreEventSupport();
}
return coreEventSupport;
}
public ICoreEventRegistration registerCoreEventListener(String type,
ICoreEventListener listener) {
return getCoreEventSupport().registerCoreEventListener(this, type,
listener);
}
private void fireValueChange(String type, Object oldValue, Object newValue) {
ICoreEventSupport coreEventSupport = getCoreEventSupport();
if (coreEventSupport != null) {
coreEventSupport
.dispatchValueChange(this, type, oldValue, newValue);
}
}
private void fireTargetChange(String type, Object target) {
ICoreEventSupport coreEventSupport = getCoreEventSupport();
if (coreEventSupport != null) {
coreEventSupport.dispatchTargetChange(this, type, target);
}
}
public long getModifiedTime() {
String time = DOMUtils.getAttribute(implementation,
DOMConstants.ATTR_TIMESTAMP);
return NumberUtils.safeParseLong(time, 0);
}
public void updateModifiedTime() {
setModifiedTime(System.currentTimeMillis());
IWorkbook workbook = getParent();
if (workbook != null) {
((WorkbookImpl) workbook).updateModifiedTime();
}
}
public void setModifiedTime(long time) {
long oldTime = getModifiedTime();
DOMUtils.setAttribute(implementation, DOMConstants.ATTR_TIMESTAMP,
Long.toString(time));
long newTime = getModifiedTime();
fireValueChange(Core.ModifyTime, oldTime, newTime);
}
}