@Override
  public void writeExternal(Element element) throws WriteExternalException {
    List<HighlightSeverity> list = getOrderAsList(getOrderMap());
    for (HighlightSeverity severity : list) {
      Element info = new Element(INFO_TAG);
      String severityName = severity.getName();
      final SeverityBasedTextAttributes infoType = getAttributesBySeverity(severity);
      if (infoType != null) {
        infoType.writeExternal(info);
        final Color color = myRendererColors.get(severityName);
        if (color != null) {
          info.setAttribute(COLOR_ATTRIBUTE, Integer.toString(color.getRGB() & 0xFFFFFF, 16));
        }
        element.addContent(info);
      }
    }

    if (myReadOrder != null && !myReadOrder.isEmpty()) {
      myReadOrder.writeExternal(element);
    } else if (!getDefaultOrder().equals(list)) {
      final JDOMExternalizableStringList ext =
          new JDOMExternalizableStringList(Collections.nCopies(getOrderMap().size(), ""));
      getOrderMap()
          .forEachEntry(
              new TObjectIntProcedure<HighlightSeverity>() {
                @Override
                public boolean execute(HighlightSeverity orderSeverity, int oIdx) {
                  ext.set(oIdx, orderSeverity.getName());
                  return true;
                }
              });
      ext.writeExternal(element);
    }
  }
  private static void updateExistingPluginInfo(
      IdeaPluginDescriptor descr, IdeaPluginDescriptor existing) {
    int state = StringUtil.compareVersionNumbers(descr.getVersion(), existing.getVersion());
    final PluginId pluginId = existing.getPluginId();
    final String idString = pluginId.getIdString();
    final JDOMExternalizableStringList installedPlugins =
        PluginManagerUISettings.getInstance().getInstalledPlugins();
    if (!installedPlugins.contains(idString)
        && !((IdeaPluginDescriptorImpl) existing).isDeleted()) {
      installedPlugins.add(idString);
    }
    final PluginManagerUISettings updateSettings = PluginManagerUISettings.getInstance();
    if (state > 0
        && !PluginManager.isIncompatible(descr)
        && !updatedPlugins.contains(descr.getPluginId())) {
      NewVersions2Plugins.put(pluginId, 1);
      if (!updateSettings.myOutdatedPlugins.contains(idString)) {
        updateSettings.myOutdatedPlugins.add(idString);
      }

      final IdeaPluginDescriptorImpl plugin = (IdeaPluginDescriptorImpl) existing;
      plugin.setDownloadsCount(descr.getDownloads());
      plugin.setVendor(descr.getVendor());
      plugin.setVendorEmail(descr.getVendorEmail());
      plugin.setVendorUrl(descr.getVendorUrl());
      plugin.setUrl(descr.getUrl());

    } else {
      updateSettings.myOutdatedPlugins.remove(idString);
      if (NewVersions2Plugins.remove(pluginId) != null) {
        updatedPlugins.add(pluginId);
      }
    }
  }
  @Override
  public boolean isEntryPoint(@NotNull PsiElement element) {
    if (!(element instanceof PsiModifierListOwner)) return false;
    PsiModifierListOwner owner = (PsiModifierListOwner) element;
    if (!ADDITIONAL_ANNOTATIONS.isEmpty()
        && ADDITIONAL_ANNOTATIONS.contains(Deprecated.class.getName())
        && element instanceof PsiDocCommentOwner
        && ((PsiDocCommentOwner) element).isDeprecated()) {
      return true;
    }

    if (element instanceof PsiClass) {
      final String qualifiedName = ((PsiClass) element).getQualifiedName();
      if (qualifiedName != null) {
        for (ClassPattern pattern : getPatterns()) {
          if (isAcceptedByPattern((PsiClass) element, qualifiedName, pattern, new HashSet<>())) {
            return true;
          }
        }
      }
    }

    return AnnotationUtil.checkAnnotatedUsingPatterns(owner, ADDITIONAL_ANNOTATIONS)
        || AnnotationUtil.checkAnnotatedUsingPatterns(owner, getAdditionalAnnotations());
  }
  protected static JDOMExternalizableStringList reparseProperties(
      @NotNull final String properties) {
    final JDOMExternalizableStringList result = new JDOMExternalizableStringList();

    final StringTokenizer tokenizer = new StringTokenizer(properties, ",");
    while (tokenizer.hasMoreTokens()) {
      result.add(tokenizer.nextToken().toLowerCase().trim());
    }

    return result;
  }
  @Override
  public void readExternal(Element element) throws InvalidDataException {
    myMap.clear();
    myRendererColors.clear();
    final List children = element.getChildren(INFO_TAG);
    for (Object child : children) {
      final Element infoElement = (Element) child;

      final SeverityBasedTextAttributes highlightInfo =
          new SeverityBasedTextAttributes(infoElement);

      Color color = null;
      final String colorStr = infoElement.getAttributeValue(COLOR_ATTRIBUTE);
      if (colorStr != null) {
        color = new Color(Integer.parseInt(colorStr, 16));
      }
      registerSeverity(highlightInfo, color);
    }
    myReadOrder = new JDOMExternalizableStringList();
    myReadOrder.readExternal(element);
    List<HighlightSeverity> read = new ArrayList<HighlightSeverity>(myReadOrder.size());
    final List<HighlightSeverity> knownSeverities = getDefaultOrder();
    for (String name : myReadOrder) {
      HighlightSeverity severity = getSeverity(name);
      if (severity == null || !knownSeverities.contains(severity)) continue;
      read.add(severity);
    }
    OrderMap orderMap = fromList(read);
    if (orderMap.isEmpty()) {
      orderMap = fromList(knownSeverities);
    } else {
      // enforce include all known
      List<HighlightSeverity> list = getOrderAsList(orderMap);
      for (int i = 0; i < knownSeverities.size(); i++) {
        HighlightSeverity stdSeverity = knownSeverities.get(i);
        if (!list.contains(stdSeverity)) {
          for (int oIdx = 0; oIdx < list.size(); oIdx++) {
            HighlightSeverity orderSeverity = list.get(oIdx);
            HighlightInfoType type = STANDARD_SEVERITIES.get(orderSeverity.getName());
            if (type != null && knownSeverities.indexOf(type.getSeverity(null)) > i) {
              list.add(oIdx, stdSeverity);
              myReadOrder = null;
              break;
            }
          }
        }
      }
      orderMap = fromList(list);
    }
    myOrderMap = orderMap;
    severitiesChanged();
  }
 @Override
 public void loadState(Element state) {
   try {
     DefaultJDOMExternalizer.readExternal(this, state);
     if (myNullables.isEmpty()) {
       Collections.addAll(myNullables, DEFAULT_NULLABLES);
     }
     if (myNotNulls.isEmpty()) {
       Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
     }
   } catch (InvalidDataException e) {
     LOG.error(e);
   }
 }
  @Override
  @SuppressWarnings({"HardCodedStringLiteral"})
  public void loadState(Element element) {
    Element entryPointsElement = element.getChild("entry_points");
    if (entryPointsElement != null) {
      final String version = entryPointsElement.getAttributeValue(VERSION_ATTR);
      if (!Comparing.strEqual(version, VERSION)) {
        convert(entryPointsElement, myPersistentEntryPoints);
      } else {
        List content = entryPointsElement.getChildren();
        for (final Object aContent : content) {
          Element entryElement = (Element) aContent;
          if (ENTRY_POINT_ATTR.equals(entryElement.getName())) {
            SmartRefElementPointerImpl entryPoint = new SmartRefElementPointerImpl(entryElement);
            myPersistentEntryPoints.put(entryPoint.getFQName(), entryPoint);
          }
        }
      }
    }
    try {
      ADDITIONAL_ANNOTATIONS.readExternal(element);
    } catch (Throwable ignored) {
    }

    getPatterns().clear();
    for (Element pattern : element.getChildren("pattern")) {
      final ClassPattern classPattern = new ClassPattern();
      XmlSerializer.deserializeInto(classPattern, pattern);
      getPatterns().add(classPattern);
    }
  }
  @SuppressWarnings({"HardCodedStringLiteral"})
  public static void writeExternal(
      final Element element,
      final Map<String, SmartRefElementPointer> persistentEntryPoints,
      final JDOMExternalizableStringList additional_annotations) {
    Element entryPointsElement = new Element("entry_points");
    entryPointsElement.setAttribute(VERSION_ATTR, VERSION);
    for (SmartRefElementPointer entryPoint : persistentEntryPoints.values()) {
      assert entryPoint.isPersistent();
      entryPoint.writeExternal(entryPointsElement);
    }

    element.addContent(entryPointsElement);
    if (!additional_annotations.isEmpty()) {
      additional_annotations.writeExternal(element);
    }
  }
  public void addCustomPropertyName(@NotNull final String text) {
    final String s = text.trim().toLowerCase();
    if (!isCustomValue(s)) {
      myValues.add(s);
    }

    if (!isCustomValuesEnabled()) {
      myCustomValuesEnabled = true;
    }
  }
 private void readOldFormat(final Element e) {
   final JDOMExternalizableStringList list = new JDOMExternalizableStringList();
   try {
     list.readExternal(e);
   } catch (IllegalDataException ignored) {
   }
   if (list.isEmpty()) return;
   final boolean[] selection = new boolean[list.size()];
   for (int i = 0; i < list.size(); i++) {
     selection[i] = Boolean.parseBoolean(list.get(i));
   }
   final String methodSignature = fixSignature(JDOMExternalizer.readString(e, "METHOD"), false);
   myParameterMap.put(methodSignature, new MethodInfo(methodSignature, selection, false));
 }
 @SuppressWarnings({"HardCodedStringLiteral"})
 public void loadState(Element element) {
   Element entryPointsElement = element.getChild("entry_points");
   if (entryPointsElement != null) {
     final String version = entryPointsElement.getAttributeValue(VERSION_ATTR);
     if (!Comparing.strEqual(version, VERSION)) {
       convert(entryPointsElement, myPersistentEntryPoints);
     } else {
       List content = entryPointsElement.getChildren();
       for (final Object aContent : content) {
         Element entryElement = (Element) aContent;
         if (ENTRY_POINT_ATTR.equals(entryElement.getName())) {
           SmartRefElementPointerImpl entryPoint = new SmartRefElementPointerImpl(entryElement);
           myPersistentEntryPoints.put(entryPoint.getFQName(), entryPoint);
         }
       }
     }
   }
   try {
     ADDITIONAL_ANNOTATIONS.readExternal(element);
   } catch (InvalidDataException ignored) {
   }
 }
 protected boolean isCustomValue(@NotNull final String value) {
   return myValues.contains(value.toLowerCase());
 }
 public void setNullables(String... annotations) {
   myNullables.clear();
   addAllIfNotPresent(myNullables, DEFAULT_NULLABLES);
   addAllIfNotPresent(myNullables, annotations);
 }
 public void setNotNulls(String... annotations) {
   myNotNulls.clear();
   addAllIfNotPresent(myNotNulls, DEFAULT_NOT_NULLS);
   addAllIfNotPresent(myNotNulls, annotations);
 }