Opened 8 years ago
Last modified 6 years ago
#15229 new enhancement
modular structure for JOSM core
Reported by: | bastiK | Owned by: | team |
---|---|---|---|
Priority: | major | Milestone: | Longterm |
Component: | Core | Version: | |
Keywords: | modularization hack-weekend-2018-10 | Cc: | wiktorn, michael2402 |
Description (last modified by )
In the spirit of project Jigsaw, we could try to create a more modular structure for the JOSM source repository. Not only is it easier to maintain a modular project and more accessible for new developers, there are practical goals as well, namely to create standalone libraries and tools that will be valuable for other projects.
Replying to Don-vip:
I'd like to see JOSM core classes become the standard OSM Java library :) There would be no need for other people to create their own (osm-common or osmapi for example)
Other goals would be:
- standalone validator (#15182)
- MapCSS library and renderer
- projection library and conversion tool
- IO for GPX, nmea, ...
- imagery (move WMS and WMTS support into JMapViewer)
- ...
I've started experimenting on GitHub: bastik:modules.
Attachments (11)
Change History (198)
comment:1 by , 8 years ago
follow-up: 5 comment:2 by , 8 years ago
I see you're listing individual files, I assume it's because you're experimenting in an iterative manner?
One important thing: Java 9 does now allow split packages (same package defined in two different modules); that's why in #15182 I moved a few classes around and created new packages.
comment:3 by , 8 years ago
Keywords: | modularization added |
---|---|
Type: | defect → enhancement |
comment:4 by , 8 years ago
Description: | modified (diff) |
---|
comment:5 by , 8 years ago
Replying to Don-vip:
I see you're listing individual files, I assume it's because you're experimenting in an iterative manner?
Yes, I try to keep it small and get the modules to compile in a bottom-up kind of way.
One important thing: Java 9 does now allow split packages (same package defined in two different modules); that's why in #15182 I moved a few classes around and created new packages.
Okay, I'll keep that in mind, but it can always be fixed later on.
comment:6 by , 8 years ago
See also the patch in #13036. Maybe you have an idea about Michael's comments?
by , 8 years ago
Attachment: | deprecate_ILatLon#getEastNorth().patch added |
---|
comment:8 by , 8 years ago
I'd like ILatLon
, LatLon
, EastNorth
, Bounds
, ProjectionBounds
, ... to be pure data classes without dependency on global singletons like Main.proj
and Main.pref
.
Attached patch deprecates ILatLon#getEastNorth()
and makes a few more classes accept ILatLon
instead of LatLon
.
follow-up: 29 comment:26 by , 8 years ago
Cc: | added |
---|
@Wiktor, Michael: the use of org.openstreetmap.gui.jmapviewer.FeatureAdapter.getLogger
in JCSCachedTileLoaderJob
and JCSCacheManager
is problematic. Could you please see if it can be replaced by an API solely based on josm.tools.Logging
?
follow-ups: 31 34 comment:29 by , 8 years ago
Replying to Don-vip:
@Wiktor, Michael: the use of
org.openstreetmap.gui.jmapviewer.FeatureAdapter.getLogger
inJCSCachedTileLoaderJob
andJCSCacheManager
is problematic. Could you please see if it can be replaced by an API solely based onjosm.tools.Logging
?
This shouldn't be a problem. I'll take a look in the evening.
Do you plan to move WMS/WMTS support together with caching to JMapViewer or you'd like to keep this separate?
comment:31 by , 8 years ago
Replying to wiktorn:
This shouldn't be a problem. I'll take a look in the evening.
Do you plan to move WMS/WMTS support together with caching to JMapViewer or you'd like to keep this separate?
Ah, maybe simply do nothing. I thought cache was needed for my standalone validator project, but in fact I can skip these classes. Paul has plans to move wms/wmts support to JMapViewer, I let this to him :)
comment:34 by , 8 years ago
Replying to wiktorn:
Do you plan to move WMS/WMTS support together with caching to JMapViewer or you'd like to keep this separate?
Moving WMS/WMTS support to JMapViewer is more like a brainstorming idea. At the moment, I have no concrete plans for this project.
As for the cache, it makes sense to define an abstract caching interface and offer a way to select different caching implementations.
follow-up: 41 comment:40 by , 8 years ago
I have several problematic calls to GuiHelper.runInEDT*
outside of GUI.
Here is a proposition, what do you think? I don't know if it's the best one.
-
src/org/openstreetmap/josm/gui/util/GuiHelper.java
24 24 import java.awt.event.MouseAdapter; 25 25 import java.awt.event.MouseEvent; 26 26 import java.awt.image.FilteredImageSource; 27 import java.lang.reflect.InvocationTargetException;28 27 import java.util.Arrays; 29 28 import java.util.Collection; 30 29 import java.util.Enumeration; 31 30 import java.util.EventObject; 32 31 import java.util.Locale; 33 32 import java.util.concurrent.Callable; 34 import java.util.concurrent.ExecutionException;35 import java.util.concurrent.FutureTask;36 33 37 34 import javax.swing.GrayFilter; 38 35 import javax.swing.ImageIcon; … … 59 56 import org.openstreetmap.josm.gui.widgets.HtmlPanel; 60 57 import org.openstreetmap.josm.tools.CheckParameterUtil; 61 58 import org.openstreetmap.josm.tools.ColorHelper; 59 import org.openstreetmap.josm.tools.EdtHelper; 62 60 import org.openstreetmap.josm.tools.GBC; 63 61 import org.openstreetmap.josm.tools.ImageOverlay; 64 62 import org.openstreetmap.josm.tools.ImageProvider; … … 66 64 import org.openstreetmap.josm.tools.LanguageInfo; 67 65 import org.openstreetmap.josm.tools.Logging; 68 66 import org.openstreetmap.josm.tools.PlatformHook; 69 import org.openstreetmap.josm.tools.bugreport.BugReport;70 67 import org.openstreetmap.josm.tools.bugreport.ReportedException; 71 68 72 69 /** … … 194 191 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 195 192 * @param task The runnable to execute 196 193 * @see SwingUtilities#invokeLater 194 * @deprecated to be removed end of 2017. Use {@link EdtHelper#runInEDT(Runnable)} instead 197 195 */ 196 @Deprecated 198 197 public static void runInEDT(Runnable task) { 199 if (SwingUtilities.isEventDispatchThread()) { 200 task.run(); 201 } else { 202 SwingUtilities.invokeLater(task); 203 } 198 EdtHelper.runInEDT(task); 204 199 } 205 200 206 201 /** … … 208 203 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 209 204 * @param task The runnable to execute 210 205 * @see SwingUtilities#invokeAndWait 206 * @deprecated to be removed end of 2017. Use {@link EdtHelper#runInEDTAndWait(Runnable)} instead 211 207 */ 208 @Deprecated 212 209 public static void runInEDTAndWait(Runnable task) { 213 if (SwingUtilities.isEventDispatchThread()) { 214 task.run(); 215 } else { 216 try { 217 SwingUtilities.invokeAndWait(task); 218 } catch (InterruptedException | InvocationTargetException e) { 219 Logging.error(e); 220 } 221 } 210 EdtHelper.runInEDTAndWait(task); 222 211 } 223 212 224 213 /** … … 230 219 * @param task The runnable to execute 231 220 * @see SwingUtilities#invokeAndWait 232 221 * @since 10271 222 * @deprecated to be removed end of 2017. Use {@link EdtHelper#runInEDTAndWaitWithException(Runnable)} instead 233 223 */ 224 @Deprecated 234 225 public static void runInEDTAndWaitWithException(Runnable task) { 235 if (SwingUtilities.isEventDispatchThread()) { 236 task.run(); 237 } else { 238 try { 239 SwingUtilities.invokeAndWait(task); 240 } catch (InterruptedException | InvocationTargetException e) { 241 throw BugReport.intercept(e).put("task", task); 242 } 243 } 226 EdtHelper.runInEDTAndWaitWithException(task); 244 227 } 245 228 246 229 /** … … 251 234 * @param callable The callable to execute 252 235 * @return The computed result 253 236 * @since 7204 237 * @deprecated to be removed end of 2017. Use {@link EdtHelper#runInEDTAndWaitAndReturn(Callable)} instead 254 238 */ 239 @Deprecated 255 240 public static <V> V runInEDTAndWaitAndReturn(Callable<V> callable) { 256 if (SwingUtilities.isEventDispatchThread()) { 257 try { 258 return callable.call(); 259 } catch (Exception e) { // NOPMD 260 Logging.error(e); 261 return null; 262 } 263 } else { 264 FutureTask<V> task = new FutureTask<>(callable); 265 SwingUtilities.invokeLater(task); 266 try { 267 return task.get(); 268 } catch (InterruptedException | ExecutionException e) { 269 Logging.error(e); 270 return null; 271 } 272 } 241 return EdtHelper.runInEDTAndWaitAndReturn(callable); 273 242 } 274 243 275 244 /** 276 245 * This function fails if it was not called from the EDT thread. 277 246 * @throws IllegalStateException if called from wrong thread. 278 247 * @since 10271 248 * @deprecated to be removed end of 2017. Use {@link EdtHelper#assertCallFromEdt()} instead 279 249 */ 250 @Deprecated 280 251 public static void assertCallFromEdt() { 281 if (!SwingUtilities.isEventDispatchThread()) { 282 throw new IllegalStateException( 283 "Needs to be called from the EDT thread, not from " + Thread.currentThread().getName()); 284 } 252 EdtHelper.assertCallFromEdt(); 285 253 } 286 254 287 255 /** -
src/org/openstreetmap/josm/tools/EdtHelper.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.tools; 3 4 import java.lang.reflect.InvocationTargetException; 5 import java.util.concurrent.Callable; 6 import java.util.concurrent.ExecutionException; 7 import java.util.concurrent.FutureTask; 8 9 import javax.swing.SwingUtilities; 10 11 import org.openstreetmap.josm.tools.bugreport.BugReport; 12 import org.openstreetmap.josm.tools.bugreport.ReportedException; 13 14 /** 15 * Utilities to make life with Event Dispatch Thread (EDT) easier. 16 * @since xxx 17 */ 18 public final class EdtHelper { 19 20 private EdtHelper() { 21 // Hide default constructor for utils classes 22 } 23 24 /** 25 * Executes asynchronously a runnable in 26 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 27 * @param task The runnable to execute 28 * @see SwingUtilities#invokeLater 29 */ 30 public static void runInEDT(Runnable task) { 31 if (SwingUtilities.isEventDispatchThread()) { 32 task.run(); 33 } else { 34 SwingUtilities.invokeLater(task); 35 } 36 } 37 38 /** 39 * Executes synchronously a runnable in 40 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 41 * @param task The runnable to execute 42 * @see SwingUtilities#invokeAndWait 43 */ 44 public static void runInEDTAndWait(Runnable task) { 45 if (SwingUtilities.isEventDispatchThread()) { 46 task.run(); 47 } else { 48 try { 49 SwingUtilities.invokeAndWait(task); 50 } catch (InterruptedException | InvocationTargetException e) { 51 Logging.error(e); 52 } 53 } 54 } 55 56 /** 57 * Executes synchronously a runnable in 58 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 59 * <p> 60 * Passes on the exception that was thrown to the thread calling this. 61 * The exception is wrapped using a {@link ReportedException}. 62 * @param task The runnable to execute 63 * @see SwingUtilities#invokeAndWait 64 */ 65 public static void runInEDTAndWaitWithException(Runnable task) { 66 if (SwingUtilities.isEventDispatchThread()) { 67 task.run(); 68 } else { 69 try { 70 SwingUtilities.invokeAndWait(task); 71 } catch (InterruptedException | InvocationTargetException e) { 72 throw BugReport.intercept(e).put("task", task); 73 } 74 } 75 } 76 77 /** 78 * Executes synchronously a callable in 79 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a> 80 * and return a value. 81 * @param <V> the result type of method <tt>call</tt> 82 * @param callable The callable to execute 83 * @return The computed result 84 */ 85 public static <V> V runInEDTAndWaitAndReturn(Callable<V> callable) { 86 if (SwingUtilities.isEventDispatchThread()) { 87 try { 88 return callable.call(); 89 } catch (Exception e) { // NOPMD 90 Logging.error(e); 91 return null; 92 } 93 } else { 94 FutureTask<V> task = new FutureTask<>(callable); 95 SwingUtilities.invokeLater(task); 96 try { 97 return task.get(); 98 } catch (InterruptedException | ExecutionException e) { 99 Logging.error(e); 100 return null; 101 } 102 } 103 } 104 105 /** 106 * This function fails if it was not called from the EDT thread. 107 * @throws IllegalStateException if called from wrong thread. 108 */ 109 public static void assertCallFromEdt() { 110 if (!SwingUtilities.isEventDispatchThread()) { 111 throw new IllegalStateException( 112 "Needs to be called from the EDT thread, not from " + Thread.currentThread().getName()); 113 } 114 } 115 }
comment:41 by , 8 years ago
Replying to Don-vip:
I have several problematic calls to
GuiHelper.runInEDT*
outside of GUI.
For example?
Here is a proposition, what do you think? I don't know if it's the best one.
Why not, as long as javax.swing.SwingUtilities
import is fine.
follow-up: 44 comment:42 by , 8 years ago
In the github branch, I can now compile the projection classes with just the following minimal dependencies:
org.openstreetmap.josm.data.Bounds org.openstreetmap.josm.data.coor.Coordinate org.openstreetmap.josm.data.coor.EastNorth org.openstreetmap.josm.data.coor.ILatLon org.openstreetmap.josm.data.coor.LatLon org.openstreetmap.josm.data.coor.LatLonToEastNorthConverter org.openstreetmap.josm.data.osm.BBox org.openstreetmap.josm.data.osm.BBoxProvider org.openstreetmap.josm.data.ProjectionBounds org.openstreetmap.josm.tools.bugreport.BugReport org.openstreetmap.josm.tools.bugreport.BugReportQueue org.openstreetmap.josm.tools.bugreport.ReportedException org.openstreetmap.josm.tools.CheckParameterUtil org.openstreetmap.josm.tools.I18n org.openstreetmap.josm.tools.JosmRuntimeException org.openstreetmap.josm.tools.LanguageInfo org.openstreetmap.josm.tools.Logging org.openstreetmap.josm.tools.MultiMap org.openstreetmap.josm.tools.Platform org.openstreetmap.josm.tools.PlatformVisitor org.openstreetmap.josm.tools.StreamUtils org.openstreetmap.josm.tools.SubclassFilteredCollection org.openstreetmap.josm.tools.Utils
I will commit those changes (except methods will be deprecated and not deleted + javadoc). You are welcome to review the patches!
Now, the MapCSS code looks a bit more difficult to disentangle... :)
follow-up: 46 comment:43 by , 8 years ago
I have 5 occurences:
data.osm.ChangesetCache.java 82: GuiHelper.runInEDT(() -> { gui.mappaint.ElemStyles.java 84: GuiHelper.runInEDT(() -> { gui.tagging.presets.TaggingPreset.java 220: GuiHelper.runInEDT(() -> result.attachImageIcon(this)); io.auth.AbstractCredentialsAgent.java 54: GuiHelper.runInEDTAndWait(() -> { io.MessageNotifier.java 73: GuiHelper.runInEDT(() -> {
Ideally I'd like to not depend on AWT and Swing but it is more and more difficult!
comment:44 by , 8 years ago
Replying to bastiK:
You are welcome to review the patches!
You can move Utils.getJavaExpirationDate()
alongside Utils.getJavaLatestVersion()
. These two methods are meant to be together :)
Now, the MapCSS code looks a bit more difficult to disentangle... :)
Agreed! Didn't start to look at it yet. I think I'll go with the presets first.
comment:46 by , 8 years ago
Replying to Don-vip:
I have 5 occurences:
data.osm.ChangesetCache.java 82: GuiHelper.runInEDT(() -> {
Convenience code, can be moved to ChangesetCacheListener.changesetCacheUpdated
methods.
gui.mappaint.ElemStyles.java 84: GuiHelper.runInEDT(() -> {
Tricky, not sure how to deal with that.
gui.tagging.presets.TaggingPreset.java 220: GuiHelper.runInEDT(() -> result.attachImageIcon(this)); io.auth.AbstractCredentialsAgent.java 54: GuiHelper.runInEDTAndWait(() -> { io.MessageNotifier.java 73: GuiHelper.runInEDT(() -> {
These 3 seem closely tied to GUI code. If that GUI code is extracted, the runInEDT*
calls can be moved as well.
follow-up: 66 comment:63 by , 8 years ago
Jenkins is stuck, maybe because of projection changes, see jenkins.txt.
by , 8 years ago
Attachment: | jenkins.txt added |
---|
comment:66 by , 8 years ago
Replying to Don-vip:
Jenkins is stuck, maybe because of projection changes, see jenkins.txt.
This thread gets a lock on Main
, then tries to do DataSet.beginUpdate
, but somehow gets stuck. Not sure what is blocking the DataSet
lock.
follow-up: 88 comment:85 by , 8 years ago
how do you think we should proceed for mappaint and tagging presets?
- move data/model classes that do not depend on GUI components to
data.mappaint
/data.tagging.presets
(major impact, many classes to move, many plugins will break)
or:
- keep as many classes in the current packages, but move pure GUI classes to another package. But how should we name it?
follow-up: 89 comment:88 by , 8 years ago
Replying to Don-vip:
how do you think we should proceed for mappaint and tagging presets?
- move data/model classes that do not depend on GUI components to
data.mappaint
/data.tagging.presets
I haven't really looked into it, but when we have a command line renderer without dependency on swing, then it would make sense to move the packages org.openstreetmap.josm.gui.mappaint.*
to org.openstreetmap.josm.rendering.*
.
(major impact, many classes to move, many plugins will break)
If it is just a change of package/class name, we could create a TODO list and then make all the plugin-breaking changes in one go.
or:
- keep as many classes in the current packages, but move pure GUI classes to another package. But how should we name it?
gui.mappaint.gui
;)
follow-up: 93 comment:89 by , 8 years ago
comment:90 by , 8 years ago
One thing I'm still struggling with are the service interfaces. We have a number "client" modules:
- validation, rendering, imagery/jmapviewer, osmapi, ...
and a number of service modules:
- projection, i18n, preferences, logging, ...
(The service implementations like logging and i18n don't actually need to be separate modules, but for the sake of argument, lets say they are.)
Each client depends on a number of services, but it would be advantageous to make that a loose coupling:
- For example, the renderer should be capable to draw in any given projection. In the majority of cases, all you want is to draw with standard Mercator projection, so no need to always include the full-blown projection module. Likewise for an imagery module: if all you want is TMS, then there is no need for all those projection classes and data files.
- Another example would be the preference handling: If one of the client modules is included in another application as a library, then this application should be able to inject a custom implementation of the preferences handling.
What this calls for, is an intermediate service API, i.e. something like the FeatureAdapter
class in jmapviewer. Only that the service API will be required by several different clients. This means the service interface cannot be placed in the client module (unless you accept massive code duplication). It also cannot be placed inside the service module, or else the JOSM service implementation becomes a mandatory dependency and there is no loose coupling.
For now, the only solution I can think of, is to make each service API a Java 9 module of its own. Those would be very small modules, with just an interface and possibly a fallback-/default implementation of the service. Not sure if this is ugly, or how it is supposed to be. :)
comment:93 by , 8 years ago
comment:102 by , 8 years ago
Next step is to replace calls to Main.pref.get(key)
by something like Config.getPref().get(key)
.
This removes dependencies on the JOSM-specific class org.openstreetmap.josm.data.Preferences
. Instead, classes only need to know about the interface IPreferences
in order to get or set preferences. Then a module, which runs standalone or as part of some other software, can still have preferences, but a custom handler may be installed:
-
src/org/openstreetmap/josm/gui/MainApplication.java
144 144 import org.openstreetmap.josm.io.remotecontrol.RemoteControl; 145 145 import org.openstreetmap.josm.plugins.PluginHandler; 146 146 import org.openstreetmap.josm.plugins.PluginInformation; 147 import org.openstreetmap.josm.spi.preferences.Config; 147 148 import org.openstreetmap.josm.tools.FontsManager; 148 149 import org.openstreetmap.josm.tools.GBC; 149 150 import org.openstreetmap.josm.tools.HttpClient; … … 920 921 I18n.set(Main.pref.get("language", null)); 921 922 } 922 923 Main.pref.updateSystemProperties(); 924 Config.setPreferencesInstance(Main.pref); 923 925 924 926 checkIPv6(); 925 927 -
src/org/openstreetmap/josm/gui/util/WindowGeometry.java
19 19 import javax.swing.JComponent; 20 20 21 21 import org.openstreetmap.josm.Main; 22 import org.openstreetmap.josm.spi.preferences.Config; 22 23 import org.openstreetmap.josm.tools.CheckParameterUtil; 23 24 import org.openstreetmap.josm.tools.JosmRuntimeException; 24 25 import org.openstreetmap.josm.tools.Logging; … … 205 206 } 206 207 207 208 protected final void initFromPreferences(String preferenceKey) throws WindowGeometryException { 208 String value = Main.pref.get(preferenceKey);209 String value = Config.getPref().get(preferenceKey); 209 210 if (value.isEmpty()) 210 211 throw new WindowGeometryException( 211 212 tr("Preference with key ''{0}'' does not exist. Cannot restore window geometry from preferences.", preferenceKey)); … … 274 275 StringBuilder value = new StringBuilder(32); 275 276 value.append("x=").append(topLeft.x).append(",y=").append(topLeft.y) 276 277 .append(",width=").append(extent.width).append(",height=").append(extent.height); 277 Main.pref.put(preferenceKey, value.toString());278 Config.getPref().put(preferenceKey, value.toString()); 278 279 } 279 280 280 281 /** -
src/org/openstreetmap/josm/spi/preferences/Config.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.spi.preferences; 3 4 import org.openstreetmap.josm.data.preferences.IPreferences; 5 6 /** 7 * Class to hold the global preferences object. 8 */ 9 public class Config { 10 11 private static IPreferences preferences; 12 13 /** 14 * Get the preferences. 15 * @return the preferences 16 */ 17 public static IPreferences getPref() { 18 return preferences; 19 } 20 21 /** 22 * Install the global preference instance. 23 * @param preferences the global preference instance to set 24 */ 25 public static void setPreferencesInstance(IPreferences preferences) { 26 Config.preferences = preferences; 27 } 28 }
comment:103 by , 8 years ago
Nice. For the global setters, I like to add null-check as follows:
public static void setPreferencesInstance(IPreferences preferences) { Config.preferences = Objects.requireNonNull(preferences, "preferences"); }
This allows to detect bad configuration earlier, before a real problem happens :)
comment:104 by , 8 years ago
In [12845]:
new class Config
to hold a global IPreferences
singleton, replacing calls to Main.pref
as far as the interface supports it
makes it possible to easily replace org.openstreetmap.josm.data.Preferences
by
another preferences handler (implementation of IPreferences
)
comment:107 by , 8 years ago
Replying to bastiK:
In 12846/josm:
I wonder if you didn't just beat the JOSM world record for the highest number of files modified in a single commit :D
comment:108 by , 8 years ago
Yes, and I had to install Eclipse for refactoring as Netbeans wasn't up to the task. :)
follow-up: 113 comment:110 by , 8 years ago
@Don-Vip I think you're still in the lead with:
- https://josm.openstreetmap.de/changeset/7491/josm (images, which you optimized, so maybe not really countable)
- https://josm.openstreetmap.de/changeset/8510/josm (mostly whitespace)
- https://josm.openstreetmap.de/changeset/12620/josm (mostly non-whitespace)
But still impressive @bastiK ;) 😉
comment:113 by , 8 years ago
Replying to floscher:
@Don-Vip I think you're still in the lead with:
- https://josm.openstreetmap.de/changeset/7491/josm (images, which you optimized, so maybe not really countable)
- https://josm.openstreetmap.de/changeset/8510/josm (mostly whitespace)
- https://josm.openstreetmap.de/changeset/12620/josm (mostly non-whitespace)
But still impressive @bastiK ;) 😉
haha nice :) Yes, r7491 was only running a script and does not count. I remember the two other ones now. I used some regex, but still there was a lot of manual work.
comment:125 by , 8 years ago
Replying to Don-vip:
Don't forget the
package-info.java
for new packages :)
Okay, didn't really know those were a thing.
comment:129 by , 7 years ago
In [o33632], [o33633]: [indoorhelper] avoid usage of data.preferences.Setting
class in anticipation of JOSM-core rework
comment:132 by , 7 years ago
comment:147 by , 7 years ago
Priority: | normal → major |
---|
by , 7 years ago
Attachment: | graph-cda-20180811.png added |
---|
by , 7 years ago
Attachment: | graph-jdeps-20180811.png added |
---|
comment:150 by , 7 years ago
Same graph using jdeps:
jdeps --dot-output dots -f "java.*|org.apache.*|org.xml.*|org.w3c.*|org.openstreetmap.gui.*|oauth.*|gnu.*| com.*|org.jdesktop.*|sun.*" *.jar dot -Tpng -O dots/summary.dot
comment:157 by , 7 years ago
by , 7 years ago
Attachment: | josm-without-dependencies.png added |
---|
by , 7 years ago
Attachment: | josm-with-direct-dependencies.png added |
---|
by , 7 years ago
Attachment: | josm-with-all-dependencies.png added |
---|
comment:162 by , 7 years ago
by , 7 years ago
Attachment: | josm-without-dependencies-20180916.png added |
---|
by , 6 years ago
Attachment: | modules.png added |
---|
comment:183 by , 6 years ago
comment:186 by , 6 years ago
Keywords: | hack-weekend-2018-10 added |
---|
by , 6 years ago
Attachment: | hack-weekend-2018-10-modules.png added |
---|
comment:187 by , 6 years ago
Milestone: | → Longterm |
---|
In 12713/josm: