Syntax error for Map extension

Issue #37 invalid
Marco Bresciani created an issue

Using the plugin I’ve seen a PlantUML file generated with a syntax error.

Wrong line is: java.util.HashMap.Entry .up.|> java.util.Map.Entry<K,V> and probably depends on having a class declared as public class MyHashMap<K, V> extends HashMap<K, V> { (Commenting out such class, the wrong line does not appear)

Comments (15)

  1. Philippe MESMEUR repo owner

    Hello (once again) Marco,

    do you have a light java sample that reproduces the problem?

    Thank you very much

    Regards,

    Philippe

  2. Marco Bresciani reporter

    If I completely comment/uncomment this class, the error disappear: (don’t comment on code quality… not mine 😃)

    package a.b.c.b.e.f.g;
    
    import org.apache.log4j.Logger;
    
    import java.util.HashMap;
    
    public class MyHashMap<K, V> extends HashMap<K, V> {
    
        private Logger logger;
        private final String name;
    
        public MyHashMap(final String pName, final Logger logger) {
            name = pName;
            this.logger = logger;
        }
    
        public MyHashMap(final String pName) {
            name = pName;
            this.logger = null;
        }
    
        @Override
        public V put(final K key, final V value) {
            if(logger != null)
                logger.info(String.format("[HASHMAP %s] SIZE: %d", name, values().size()));
            return super.put(key, value);
        }
    
        @Override
        public V remove(final Object key) {
            if(logger != null)
                logger.info(String.format("[HASHMAP %s] SIZE: %d", name, values().size()));
            return super.remove(key);
        }
    }
    

    (The names have been changed to protect the innocent. 😃)

  3. Philippe MESMEUR repo owner
    • Using this code with Sketch.It! v0.06.01 generates me
      namespace a.b.c.d.e.f.g {
        class a.b.c.d.e.f.g.MyHashMap {
            - logger : Logger
            - name : String
            + MyHashMap()
            + MyHashMap()
            + put()
            + remove()
        }
      }
    
    
      a.b.c.d.e.f.g.MyHashMap -up-|> java.util.HashMap
    

    It seems to be good!!!

    • Using this code with Sketch.It! v0.06.00 triggers a StackOverflowException

    Marco, in your example, I do not see anything related to java.util.HashMap.Entry

  4. Marco Bresciani reporter

    I know. But it's the only class that triggers the wrong line in its package. If I comment it, I don't see the wrong line. The class is not used in its own package. Follows the generated PlantUML:

    @startuml
    
    title __UTILS's Class Diagram__\n
    
      namespace c.r.g.r.n {
        namespace common {
          namespace utils {
            class Platform {
                {static} + prepareAddProvisioning()
                {static} + prepareDeviceConnection()
                {static} + prepareDeviceDisconnection()
                {static} + prepareMergerTimeout()
                {static} + prepareDeviceAudioProgress()
                {static} + prepareDeviceSuspend()
            }
          }
        }
      }
    
    
      namespace c.r.g.r.n {
        namespace common {
          namespace utils {
            class ProbesProperties {
                - configuration : PropertiesConfiguration
                {static} - log : Logger
                - init()
                - createMissingFile()
                + getJsonString()
                + getJson()
                + getPrettyJsonString()
                + getProperty()
                ~ setProperty()
                ~ save()
            }
          }
        }
      }
    
    
      namespace c.r.g.r.n {
        namespace common {
          namespace utils {
            class ProbesConfigurationListener {
                {static} - log : Logger
                + configurationChanged()
            }
          }
        }
      }
    
    
      namespace c.r.g.r.n {
        namespace common {
          namespace utils {
            class ProbesPropertiesConstants {
                {static} - DEFAULT_RELOAD_DELAY : long
                {static} - PROBES_PROPERTIES_RELOAD : String
                - propertiesFilePath : File
                - configurationFilePath : File
                - refreshDelay : Long
                {static} - log : Logger
                + init()
                + getPropertiesFilePath()
                + getRefreshDelay()
            }
          }
        }
      }
    
    
      namespace c.r.g.r.n {
        namespace common {
          namespace utils {
            class MyHashMap {
                - logger : Logger
                - name : String
                + MyHashMap()
                + MyHashMap()
                + put()
                + remove()
            }
          }
        }
      }
    
    
      c.r.g.r.n.common.utils.ProbesProperties o-- c.r.g.r.n.c.u.ProbesPropertiesConstants : constants
      c.r.g.r.n.common.utils.ProbesProperties +-down- c.r.g.r.n.c.u.ProbesProperties.ProbesConfigurationListener
      c.r.g.r.n.common.utils.ProbesProperties.ProbesConfigurationListener .up.|> org.apache.commons.configuration.event.ConfigurationListener
      c.r.g.r.n.common.utils.MyHashMap -up-|> java.util.HashMap
      java.util.HashMap.Entry .up.|> java.util.Map.Entry<K,V>
      java.util.HashMap.EntryIterator -up-|> java.util.HashMap.HashIterator
      java.util.HashMap.EntrySet -up-|> java.util.AbstractSet
      java.util.HashMap.HashIterator .up.|> java.util.Iterator<E>
      java.util.HashMap.KeyIterator -up-|> java.util.HashMap.HashIterator
      java.util.HashMap.KeySet -up-|> java.util.AbstractSet
      java.util.HashMap.ValueIterator -up-|> java.util.HashMap.HashIterator
      java.util.HashMap.Values -up-|> java.util.AbstractCollection
      java.util.AbstractMap.SimpleEntry .up.|> java.util.Map.Entry<K,V>
      java.util.AbstractMap.SimpleEntry .up.|> java.io.Serializable
      java.util.AbstractMap.SimpleImmutableEntry .up.|> java.util.Map.Entry<K,V>
      java.util.AbstractMap.SimpleImmutableEntry .up.|> java.io.Serializable
    
    
    right footer
    
    
    PlantUML diagram generated by SketchIt! (https://bitbucket.org/pmesmeur/sketch.it)
    For more information about this tool, please contact philippe.mesmeur@gmail.com
    endfooter
    
    @enduml
    

    Could it be that such class, for some reason, cause the StackOverflow (the error, not the famous site :) ) and those lines (including the wrong one) are somehow generated? Removing (commenting out its whole content) the MyHashMap class, I see:

    @startuml
    
    title __UTILS's Class Diagram__\n
    
      namespace  {
        namespace om.r.g.r.n {
          namespace common {
            namespace utils {
              class Platform {
                  {static} + prepareAddProvisioning()
                  {static} + prepareDeviceConnection()
                  {static} + prepareDeviceDisconnection()
                  {static} + prepareMergerTimeout()
                  {static} + prepareDeviceAudioProgress()
                  {static} + prepareDeviceSuspend()
              }
            }
          }
        }
      }
    
    
      namespace  {
        namespace om.r.g.r.n {
          namespace common {
            namespace utils {
              class ProbesProperties {
                  - configuration : PropertiesConfiguration
                  {static} - log : Logger
                  - init()
                  - createMissingFile()
                  + getJsonString()
                  + getJson()
                  + getPrettyJsonString()
                  + getProperty()
                  ~ setProperty()
                  ~ save()
              }
            }
          }
        }
      }
    
    
      namespace  {
        namespace om.r.g.r.n {
          namespace common {
            namespace utils {
              class ProbesConfigurationListener {
                  {static} - log : Logger
                  + configurationChanged()
              }
            }
          }
        }
      }
    
    
      namespace  {
        namespace om.r.g.r.n {
          namespace common {
            namespace utils {
              class ProbesPropertiesConstants {
                  {static} - DEFAULT_RELOAD_DELAY : long
                  {static} - PROBES_PROPERTIES_RELOAD : String
                  - propertiesFilePath : File
                  - configurationFilePath : File
                  - refreshDelay : Long
                  {static} - log : Logger
                  + init()
                  + getPropertiesFilePath()
                  + getRefreshDelay()
              }
            }
          }
        }
      }
    
    
      c.r.g.r.n.common.utils.ProbesProperties o-- c.r.g.r.r.common.utils.ProbesPropertiesConstants : constants
      c.r.g.r.n.common.utils.ProbesProperties +-down- c.r.g.r.n.common.utils.ProbesProperties.ProbesConfigurationListener
      c.r.g.r.n.common.utils.ProbesProperties.ProbesConfigurationListener .up.|> org.apache.commons.configuration.event.ConfigurationListener
    
    
    right footer
    
    
    PlantUML diagram generated by SketchIt! (https://bitbucket.org/pmesmeur/sketch.it)
    For more information about this tool, please contact philippe.mesmeur@gmail.com
    endfooter
    
    @enduml
    

    Please also note, in this case, the error in namespace: instead of com.r.g.r.n.common.utils, I see

      namespace  {
        namespace om.r.g.r.n {
    

    With a blank initial namespace and om instead of com. But this could be due to the fact that some classes depends on that myHashMap and so, possibly, removing them I caused such error.

  5. Philippe MESMEUR repo owner

    I created the following Java file which seems to be correctly processed by Sketch.It! (at least for version 0.06.01).

    package a.b.c.d.e.f.g;
    
    import org.apache.log4j.Logger;
    
    import java.util.HashMap;
    
    public class MyHashMap<K, V> extends HashMap<K, V> {
    
        private Logger logger;
        private final String name;
    
        public MyHashMap(final String pName, final Logger logger) {
            name = pName;
            this.logger = logger;
        }
    
        public MyHashMap(final String pName) {
            name = pName;
            this.logger = null;
        }
    
        @Override
        public V put(final K key, final V value) {
            if(logger != null)
                logger.info(String.format("[HASHMAP %s] SIZE: %d", name, values().size()));
            return super.put(key, value);
        }
    
        @Override
        public V remove(final Object key) {
            if(logger != null)
                logger.info(String.format("[HASHMAP %s] SIZE: %d", name, values().size()));
            return super.remove(key);
        }
    
    
        public static class SimpleEntry<K,V>
                implements Entry<K,V>, java.io.Serializable
        {
            private static final long serialVersionUID = -8499721149061103585L;
    
            private final K key;
            private V value;
    
            /**
             * Creates an entry representing a mapping from the specified
             * key to the specified value.
             *
             * @param key the key represented by this entry
             * @param value the value represented by this entry
             */
            public SimpleEntry(K key, V value) {
                this.key   = key;
                this.value = value;
            }
    
            /**
             * Creates an entry representing the same mapping as the
             * specified entry.
             *
             * @param entry the entry to copy
             */
            public SimpleEntry(Entry<? extends K, ? extends V> entry) {
                this.key   = entry.getKey();
                this.value = entry.getValue();
            }
    
            /**
             * Returns the key corresponding to this entry.
             *
             * @return the key corresponding to this entry
             */
            public K getKey() {
                return key;
            }
    
            /**
             * Returns the value corresponding to this entry.
             *
             * @return the value corresponding to this entry
             */
            public V getValue() {
                return value;
            }
    
            /**
             * Replaces the value corresponding to this entry with the specified
             * value.
             *
             * @param value new value to be stored in this entry
             * @return the old value corresponding to the entry
             */
            public V setValue(V value) {
                V oldValue = this.value;
                this.value = value;
                return oldValue;
            }
    
            /**
             * Compares the specified object with this entry for equality.
             * Returns {@code true} if the given object is also a map entry and
             * the two entries represent the same mapping.  More formally, two
             * entries {@code e1} and {@code e2} represent the same mapping
             * if<pre>
             *   (e1.getKey()==null ?
             *    e2.getKey()==null :
             *    e1.getKey().equals(e2.getKey()))
             *   &amp;&amp;
             *   (e1.getValue()==null ?
             *    e2.getValue()==null :
             *    e1.getValue().equals(e2.getValue()))</pre>
             * This ensures that the {@code equals} method works properly across
             * different implementations of the {@code Map.Entry} interface.
             *
             * @param o object to be compared for equality with this map entry
             * @return {@code true} if the specified object is equal to this map
             *         entry
             * @see    #hashCode
             */
            public boolean equals(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                return eq(key, e.getKey()) && eq(value, e.getValue());
            }
    
            /**
             * Returns the hash code value for this map entry.  The hash code
             * of a map entry {@code e} is defined to be: <pre>
             *   (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
             *   (e.getValue()==null ? 0 : e.getValue().hashCode())</pre>
             * This ensures that {@code e1.equals(e2)} implies that
             * {@code e1.hashCode()==e2.hashCode()} for any two Entries
             * {@code e1} and {@code e2}, as required by the general
             * contract of {@link Object#hashCode}.
             *
             * @return the hash code value for this map entry
             * @see    #equals
             */
            public int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                        (value == null ? 0 : value.hashCode());
            }
    
            /**
             * Returns a String representation of this map entry.  This
             * implementation returns the string representation of this
             * entry's key followed by the equals character ("<tt>=</tt>")
             * followed by the string representation of this entry's value.
             *
             * @return a String representation of this map entry
             */
            public String toString() {
                return key + "=" + value;
            }
    
        }
    
    
    }
    

    @startuml
    
    title __G's Class Diagram__\n
    
      namespace a.b.c.d.e.f.g {
        class a.b.c.d.e.f.g.MyHashMap {
            - logger : Logger
            - name : String
            + MyHashMap()
            + MyHashMap()
            + put()
            + remove()
        }
      }
    
    
      namespace a.b.c.d.e.f.g {
        class a.b.c.d.e.f.g.MyHashMap.SimpleEntry {
            {static} - serialVersionUID : long
            + SimpleEntry()
            + SimpleEntry()
            + getKey()
            + getValue()
            + setValue()
            + equals()
            + hashCode()
            + toString()
        }
      }
    
    
      a.b.c.d.e.f.g.MyHashMap -up-|> java.util.HashMap
      a.b.c.d.e.f.g.MyHashMap +-down- a.b.c.d.e.f.g.MyHashMap.SimpleEntry
      a.b.c.d.e.f.g.MyHashMap.SimpleEntry .up.|> java.util.Map.Entry
      a.b.c.d.e.f.g.MyHashMap.SimpleEntry .up.|> java.io.Serializable
      a.b.c.d.e.f.g.MyHashMap.SimpleEntry o-- K : key
      a.b.c.d.e.f.g.MyHashMap.SimpleEntry o-- V : value
    
    
    right footer
    
    
    PlantUML diagram generated by SketchIt! (https://bitbucket.org/pmesmeur/sketch.it)
    For more information about this tool, please contact philippe.mesmeur@gmail.com
    endfooter
    
    @enduml
    
  6. Philippe MESMEUR repo owner

    Hello Marco,

    I will need more information to progress on this issue: on my side I still do not succeed to reproduce it

    Regards

    Philippe

  7. Marco Bresciani reporter

    Hello Philippe, sorry, can't: I've found the same errored package in another project, but no syntax error. :( Don't know what to do to find it properly.

  8. Philippe MESMEUR repo owner

    I've found the same errored package in another project, but no syntax error

    I don’t really understand what you mean

    do you mean that you found the same situation in another project but it does not generate an error (meaning it a plantuml file is correctly generated)?

  9. Marco Bresciani reporter

    I've found exactly the same code (whole package!) in another project, but the package UML diagram is generated properly. :(

  10. Philippe MESMEUR repo owner

    Really strange!!!

    Do you confirm that both plantuml files was generated with the same version of Sketch.It! running on the same version of IntelliJ?

    Other important point: when generating the incorrect file, you should have in your intellij logs a line closed to:

    generating implementation interface java.util.Map.Entry<K,V> of class java.util.HashMap.Entry
    

    (OK, I have to recognize that the sentence means nothing, I will correct it)

    And when generating the correct file, you should have something like:

    generating implementation interface java.util.Map.Entry of class java.util.HashMap.Entry
    

    Am I right?

  11. Log in to comment