/*
* Copyright 2003-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.nodeEditor.cells;
import jetbrains.mps.openapi.editor.EditorComponent;
import jetbrains.mps.openapi.editor.EditorContext;
import jetbrains.mps.openapi.editor.cells.CellInfo;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.smodel.ModelAccess;
import jetbrains.mps.util.EqualUtil;
import jetbrains.mps.util.Reference;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeReference;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;
public class DefaultCellInfo implements CellInfo {
private static final String CELL_ID = "cellId";
private static final String CELL_NUMBER = "cellNumber";
private static final String IS_IN_LIST = "isInList";
private static final String NODE = "node";
private static final String NODE_REFERENCE = "node_reference";
private static final String PARENT = "parent";
private SNodeReference myNodeReference;
private String myCellId;
private int myCellNumber = 0;
private boolean myIsInList = false;
private CellInfo myParentInfo;
public DefaultCellInfo(final EditorCell cell) {
ModelAccess.instance().runReadAction(() -> {
SNode node = cell.getSNode();
if (node == null || node.getModel() == null) {
myNodeReference = null;
} else {
myNodeReference = node.getReference();
}
});
myCellId = cell.getCellId();
EditorCell_Collection parent = (EditorCell_Collection) cell.getParent();
if (parent != null && myCellId == null) {
myParentInfo = parent.getCellInfo();
myIsInList = parent.hasCellListHandler();
if (myIsInList || myCellId == null) {
for (EditorCell editorCell : parent) {
if (editorCell.equals(cell)) {
break;
}
myCellNumber++;
}
}
}
}
private DefaultCellInfo() {
}
public void saveTo(Element e) {
if (myCellId != null) {
e.setAttribute(CELL_ID, myCellId);
}
e.setAttribute(CELL_NUMBER, "" + myCellNumber);
e.setAttribute(IS_IN_LIST, "" + myIsInList);
Element nodeElement = new Element(NODE);
if (myNodeReference != null) {
nodeElement.setAttribute(NODE_REFERENCE, myNodeReference.toString());
}
e.addContent(nodeElement);
if (myParentInfo instanceof DefaultCellInfo) {
Element parentElement = new Element(PARENT);
((DefaultCellInfo) myParentInfo).saveTo(parentElement);
e.addContent(parentElement);
}
}
public static DefaultCellInfo loadFrom(Element e) {
String cellId;
int cellNumber;
boolean isInList;
final String nodeReference;
DefaultCellInfo parentInfo = null;
cellId = e.getAttributeValue(CELL_ID);
String num = e.getAttributeValue(CELL_NUMBER);
if (num == null) {
return null;
}
try {
cellNumber = Integer.parseInt(num);
} catch (NumberFormatException ex) {
return null;
}
isInList = "true".equals(e.getAttributeValue(IS_IN_LIST));
Element nodeElem = e.getChild(NODE);
if (nodeElem == null) {
return null;
}
nodeReference = nodeElem.getAttributeValue(NODE_REFERENCE);
if (nodeReference == null) {
return null;
}
Element parentElem = e.getChild(PARENT);
if (parentElem != null) {
parentInfo = loadFrom(parentElem);
if (parentInfo == null) {
return null;
}
}
final DefaultCellInfo result = new DefaultCellInfo();
result.myNodeReference = PersistenceFacade.getInstance().createNodeReference(nodeReference);
result.myCellId = cellId;
result.myParentInfo = parentInfo;
result.myIsInList = isInList;
result.myCellNumber = cellNumber;
return result;
}
public int hashCode() {
return (myParentInfo == null ? 0 : myParentInfo.hashCode()) +
(myNodeReference == null ? 0 : myNodeReference.hashCode()) + (myCellId == null ? 0 : myCellId.hashCode()) + myCellNumber;
}
@Override
public EditorCell findCell(@NotNull final EditorComponent editorComponent) {
if (myCellId != null) {
final EditorContext editorContext = editorComponent.getEditorContext();
if (myNodeReference == null) {
return null;
}
Reference<EditorCell> cellRef = new Reference<>();
editorContext.getRepository().getModelAccess().runReadAction(
() -> cellRef.set(editorComponent.findCellWithId(myNodeReference.resolve(editorContext.getRepository()), myCellId)));
return cellRef.get();
} else if (myParentInfo != null) {
EditorCell parentCell = myParentInfo.findCell(editorComponent);
if (!(parentCell instanceof EditorCell_Collection)) {
return null;
}
EditorCell_Collection parentCollection = (EditorCell_Collection) parentCell;
if (myCellNumber >= parentCollection.getCellsCount()) {
return null;
}
EditorCell editorCell = null;
int i = 0;
for (EditorCell nextCell : parentCollection) {
if (i == myCellNumber) {
editorCell = nextCell;
break;
}
i++;
}
assert editorCell != null;
// This editorCell should not have any cellId due to corresponding conditions in constructor
return editorCell.getCellId() == null ? editorCell : null;
}
return null;
}
@Override
public EditorCell findClosestCell(@NotNull EditorComponent editorComponent) {
return findCell(editorComponent);
}
public boolean equals(Object o) {
if (!(o instanceof DefaultCellInfo)) {
return false;
}
DefaultCellInfo cellInfo = (DefaultCellInfo) o;
if (!EqualUtil.equals(cellInfo.myParentInfo, myParentInfo)) {
return false;
}
if (cellInfo.myNodeReference == null) {
return false;
}
return (cellInfo.myCellId == null ?
myCellId == null :
cellInfo.myCellId.equals(myCellId)) && (cellInfo.myNodeReference.equals(myNodeReference)) && cellInfo.myCellNumber == myCellNumber;
}
@Override
public String toString() {
return "DefaultCellInfo[" +
"myNodePointer=" + (myNodeReference == null ? null : myNodeReference.toString()) +
", myCellId='" + myCellId + '\'' +
", myCellNumber=" + myCellNumber +
", myIsInList=" + myIsInList +
", myParentInfo=" + myParentInfo +
']';
}
}