/*
* Copyright 2015 Igor Maznitsa.
*
* 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 com.igormaznitsa.nbmindmap.nb.refactoring;
import com.igormaznitsa.mindmap.model.MindMap;
import com.igormaznitsa.mindmap.model.MindMapController;
import com.igormaznitsa.mindmap.model.logger.Logger;
import com.igormaznitsa.mindmap.model.logger.LoggerFactory;
import com.igormaznitsa.nbmindmap.nb.editor.MMDDataObject;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import org.apache.commons.io.IOUtils;
import org.openide.filesystems.FileAlreadyLockedException;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
public class MindMapLink {
private static final Logger LOGGER = LoggerFactory.getLogger(MindMapLink.class);
private final DataObject dataObject;
private volatile FileObject theFile;
private volatile MindMap model;
public MindMapLink(final FileObject file) {
this.theFile = file;
this.dataObject = findDataObject(file);
}
private static DataObject findDataObject(final FileObject fileObj) {
DataObject doj = null;
if (fileObj != null) {
try {
doj = DataObject.find(fileObj);
}
catch (DataObjectNotFoundException ex) {
LOGGER.warn("Can't find data object for file " + fileObj);
}
}
return doj;
}
public FileObject getFile() {
DataObject doj = this.dataObject == null ? findDataObject(this.theFile) : this.dataObject;
return doj == null ? this.theFile : doj.getPrimaryFile();
}
public File asFile(){
File result = null;
final FileObject fo = getFile();
if (fo != null){
result = FileUtil.toFile(fo);
}else{
LOGGER.warn("Can't find file object ["+this.dataObject+"; "+this.theFile+']');
}
return result;
}
private void delay(final long time){
try{
Thread.sleep(time);
}catch(InterruptedException ex){
LOGGER.warn("Delay has been interrupted");
}
}
private FileLock lock(final FileObject fo) throws IOException {
if (fo!=null){
FileLock lock = null;
while(!Thread.currentThread().isInterrupted()){
try{
lock = fo.lock();
break;
}catch(FileAlreadyLockedException ex){
delay(500L);
}
}
return lock;
}else{
return null;
}
}
public void writeUTF8Text(final String text) throws IOException {
final FileObject foj = getFile();
final FileLock flock = lock(foj);
try{
final OutputStream out = foj.getOutputStream(flock);
try{
IOUtils.write(text, out, "UTF-8");
}finally{
IOUtils.closeQuietly(out);
}
}finally{
flock.releaseLock();
}
final DataObject doj = DataObject.find(foj);
if (doj!=null && doj instanceof MMDDataObject){
LOGGER.info("Notify about change primary file");
((MMDDataObject)doj).firePrimaryFileChanged();
}
}
public String readUTF8Text() throws IOException {
final FileObject foj = getFile();
final FileLock flock = lock(foj);
try{
return foj.asText("UTF-8");
}finally{
flock.releaseLock();
}
}
public synchronized MindMap asMindMap(final MindMapController controller) throws IOException {
if (this.model == null){
this.model = new MindMap(controller, new StringReader(readUTF8Text()));
}
return this.model;
}
public synchronized void writeMindMap() throws IOException {
if (this.model != null){
writeUTF8Text(this.model.packToString());
}
}
}