/* * Copyright 2013 Serdar. * * 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 de.fub.maps.project; import de.fub.maps.project.actions.CopyImpl; import de.fub.maps.project.actions.DeleteImpl; import de.fub.maps.project.actions.MapsProjectActionProvider; import de.fub.maps.project.actions.MoveImpl; import de.fub.maps.project.actions.RenameImpl; import de.fub.maps.project.xml.Maps; import de.fub.utilsmodule.synchronizer.ModelSynchronizer2; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.MessageFormat; import java.util.HashSet; import java.util.Set; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.xml.bind.JAXBException; import org.netbeans.api.project.Project; import org.netbeans.spi.project.ProjectState; import org.openide.filesystems.FileAlreadyLockedException; import org.openide.filesystems.FileChangeAdapter; import org.openide.filesystems.FileEvent; import org.openide.filesystems.FileObject; import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; /** * * @author Serdar */ public class MapsProject extends FileChangeAdapter implements Project, ModelSynchronizer2<Maps> { private final FileObject projectDir; private final ProjectState state; private Lookup lkp; private Maps mapsProjectData = null; private Set<ChangeListener> cs = new HashSet<ChangeListener>(); private final Object MUTEX = new Object(); MapsProject(FileObject projectDirectory, ProjectState state) { this.projectDir = projectDirectory; this.state = state; projectDirectory.addFileChangeListener(MapsProject.this); } @Override public FileObject getProjectDirectory() { return projectDir; } public Maps getProjectData() throws JAXBException, IOException { if (mapsProjectData == null) { FileObject fileObject = getProjectDirectory().getFileObject(MapsProjectFactory.MAPS_PROJECT_FILE); if (fileObject == null) { throw new FileNotFoundException( MessageFormat.format("Couldn't find {0} of project folder {1} ", MapsProjectFactory.MAPS_PROJECT_FILE, getProjectDirectory().getName())); } InputStream inputStream = null; try { inputStream = fileObject.getInputStream(); javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(Maps.class); javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller(); mapsProjectData = (Maps) unmarshaller.unmarshal(inputStream); //NOI18N } finally { if (inputStream != null) { inputStream.close(); } } } return mapsProjectData; } @Override public Lookup getLookup() { if (lkp == null) { lkp = Lookups.fixed( MapsProject.this, state, new DeleteImpl(this), new RenameImpl(this), new MoveImpl(this), new CopyImpl(this), new MapsProjectActionProvider(this), // CommonProjectActions.closeProjectAction(), new MapsProjectInfo(MapsProject.this), new MapsLogicalView(MapsProject.this)); } return lkp; } @Override public void fileChanged(FileEvent fe) { try { if (fe.getFile().getNameExt().equals(getProjectFile().getNameExt())) { mapsProjectData = null; fireChangeEvent(); } } catch (FileNotFoundException ex) { Exceptions.printStackTrace(ex); } } @NbBundle.Messages({"CLT_Project_Xml_File_Not_Found=Couldn't find mapsforge.xml file in project folder!"}) private FileObject getProjectFile() throws FileNotFoundException { FileObject fileObject = getProjectDirectory().getFileObject(MapsProjectFactory.MAPS_PROJECT_FILE); if (fileObject == null) { // NotifyDescriptor.Message nm = new NotifyDescriptor.Message(Bundle.CLT_Project_Xml_File_Not_Found(), NotifyDescriptor.Message.ERROR_MESSAGE); throw new FileNotFoundException(Bundle.CLT_Project_Xml_File_Not_Found()); } return fileObject; } @Override public void modelChanged(Object o, Maps mapsForge) { OutputStream outputStream = null; try { FileObject projectFile = getProjectFile(); outputStream = projectFile.getOutputStream(); javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(Maps.class); javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller(); marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal(mapsForge, outputStream); mapsProjectData = mapsForge; fireChangeEvent(o); } catch (FileAlreadyLockedException ex) { Exceptions.printStackTrace(ex); } catch (IOException ex) { Exceptions.printStackTrace(ex); } catch (javax.xml.bind.JAXBException ex) { Exceptions.printStackTrace(ex); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } } } private void fireChangeEvent(Object o) { synchronized (MUTEX) { for (ChangeListener listener : cs) { if (listener != o) { listener.stateChanged(new ChangeEvent(MapsProject.this)); } } } } private void fireChangeEvent() { fireChangeEvent(MapsProject.this); } @Override public void addChangeListener(ChangeListener cl) { synchronized (MUTEX) { cs.add(cl); } } @Override public void removeChangeListener(ChangeListener cl) { synchronized (MUTEX) { cs.remove(cl); } } }