Community
Participate
Working Groups
IModelManager#calculateId() returns the different id even if the exact same IFile is passed to. This happens when existing model is Save-As'ed. Given that we have the following pseudo code : IStructuredModel orgModel; // This represents for the existing file IFile newFile; // This represents for the non existing file, but points to the inside of the workspace // let's say C:/workspace/dynamicWeb/WebContent/frame/a15.html IStructuredModel newModel = IModelManager#getNewModelForEdit(newFile); // In this timing, newModel's id is // C:/workspace/dynamicWeb/WebContent/frame/a15.html IStructuredDocument newDoc = newModel.getStructuredDocument(); IStructuredDocument orgDoc = orgModel.getStructuredDocument(); newDoc.setText(this, orgDoc.getText()); // copy // due to the bug of https://bugs.eclipse.org/bugs/show_bug.cgi?id=107311 // we first create the file, and refresh it later newFile.create(null, true, new NullProgressMonitor()); newModel.save(newFile); newFile.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor()); String id = IModelManager#calculateId(newFile); In this time, id is "dynamicWeb/WebContent/frame/a15.html" but id in the model is still "C:/workspace/dynamicWeb/WebContent/frame/a15.html". This is very critical problem. We can't find out the model we created any more. .
Ok, I've investigated some, and will more, but we basically "interet" the behavior of normalizeLocation(IPath) in FileFullers. I'd like to understand why our ID is so critical for you. As we've discussed in the past, I'd like to get rid of ID completely as an external variable. What, exactly, do you need it for? If you just need to manage you own models, I would think you could do that with a HastMap, your own ids (however you'd like to create them) and the model you get back from 'get'. Given all that, please let us know the fundamental thing you need. We could probably store full file name, but, can you work to get ride of ID alltogther? (Some day, the Ids/base location may not be anything related to files, per say. So, would like to avoid making that data and its behavior if at all possible. Thanks.
As you guess, our editor depends on 'id' to identify models. For example, if it is going to open the model which is referred by <FRAME src="..."> tag, first it checks to see if the corresponding model is already opened. To do this, it resolves the link (FRAME src) to retrieve the file name, and it gets IFile from that filename, then it calculates id by calling ModelManager api, and at last it checks to see if the model is already opened. ( This is just an example and we have many id usages. ) But again, we are using the id to manage models inside of our editor. We don't expect id is same as the filename, but we do expect that passing the same IFile returns the exact same id from ModelManager apis. ( Currently it is varied when the file does exist and when the file doesn't exist, which causes the problems. ) We can generate our own id from something in the model, and can manage model with that id as the model's metadata. However, it requires us very huge design change/code change and at this moment, I can't predict when we can remove the id usage. We will try removing the id usage anyway, but again, we can't commit to declaring any date to complete this work. .
I think the underlying cause of this was probably the same problem as in 106324. If that's not the case, please reopen and provide JUnit tests if possible. Thanks. *** This bug has been marked as a duplicate of 106324 ***
If the fix for bugzilla 106324 is only org.eclipse.wst.sse.core.internal.model.ModelManagerImple.java : 1.13, I'm afraid that doesn't fix this. As usualy, I can't put our JUnit test here ( because it depends on our own code. ) But here is a net Junit code. Given that you have a project called "/Project", but you don't have the file of "/Project/WebContent/a.jsp", IModelManager modelManager = StructuredModelManager.getModelManager(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IFile input = root.getFile(new Path("/Project/WebContent/a.jsp")); if (input.exists()) { input.delete(true, new NullProgressMonitor()); } IStructuredModel model = modelManager.getNewModelForEdit(input,true); model.setNewState(true); String id0 = modelManager.calculateId(input); String id_model = model.getId(); //assertEquals(id0, id_model); model.getStructuredDocument().setText(this, "<HTML></HTML>"); model.save(input); input.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor()); String id1 = modelManager.calculateId(input); //assertEquals(id0, id1); input.delete(true, new NullProgressMonitor()); input.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor()); String id2 = modelManager.calculateId(input); //assertEquals(id0, id2); //assertEquals(id1, id2); id0, id_model, id1, id2 need to be same, but they are different. The result I got is like : id0= "c:/proj/v7dev/junit-workbench-workspace/Project/WebContent/a.jsp" id_model= "c:/proj/v7dev/junit-workbench-workspace/Project/WebContent/a.jsp" id1= "/Project/WebContent/a.jsp" id2= "c:/proj/v7dev/junit-workbench-workspace/Project/WebContent/a.jsp"
Regarding comment 2, is that just an example or are there multiple places where you calculate a model ID for an IFile just to see if the model already exists? Looking at the implementation code from TextFileBufferManager, it's written to return a different value for IFiles that don't exist. That's why id1 is the only one with the correct value--the IFile either hasn't been created yet or has been deleted when the other 3 are calculated. Even supplying the path, "/Project/WebContent/a.jsp", directly to the text file buffer manager just creates a file at that location on the current filesystem, and not in the workspace. It's not a good situation to be in, but I'm not sure we can change the behavior to guarantee the result is the same at all times and still have IModelManager.saveModel(IFile, String, EncodingRule) process the IFile argument at all. Perhaps the cleanest solution for now is to add a saveAs method to the model that calls ModelManagerImpl.saveStructuredDocument() with the passed-in IFile and have the current save always save to the original buffer?
(In reply to comment #5) > Regarding comment 2, is that just an example or are there multiple places where > you calculate a model ID for an IFile just to see if the model already exists? When the design of the the original model was discussed, we were asked to use model's 'id' to identify the model. So if sombody tells us the filename( or IFile ), we calculate id from IFile and see if our editor manages this model. If somebody tells us the model itself, we get the id from the model, and check to see if we manage this id. Why we use id is, again, we were told that id should be used to identify the model. Our request is that passing the same IFile returns the exact same id from ModelManager apis. This shouldn't depend on IFile exists or not. As you asked us, we are making a feasibility research to see if removing the dependency to id is doable or not, but we believe that this is very large 'architectural' change and switching new architecture in a short time isn't basicaly doable. I could think that the alternative solution for now would be that the model provides the transitinal api (i.e. IStructuredModel#getOldId, IModelManager#calculateOldId ) to have the consistent id, so we can switch using this new api for a while.
Changing priority so won't be confused with "P1" meaning "do not declare milestone". They are just as important and high priority as they were.
*** Bug 107420 has been marked as a duplicate of this bug. ***
Will give focus for M9.
I'm changing milestone to acknowledge I did not get this done for M9, but do still believe its important, and will attempt to find a safe fix to put in before R1.0. Thanks very much.
Please see https://bugs.eclipse.org/bugs/show_bug.cgi?id=107320. If we will apply the fix I proposed ( to change FileBufferModelManager#getModel to use IFile#getFullPath, not IFile#getLocation. ), this problem is also fixed. I understand that the proposed solution highly depends on how FileBuffers#normalizeLocation and IPath#makeAbsolute behave, but I don't think their behaviour will be changed ( because lots of component may depend this behaviour already... )
Marking as fixed because bug 107320 is fixed.
I'm marking as verified, as component owner. If origantor disagrees, or sees other similar bugs, please open new ones (with reference to this one).
I'm closing this for now. If I will find another one, I'll open up new bugzilla. .