All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.igormaznitsa.mindmap.model.Extra Maven / Gradle / Ivy

/*
 * Copyright (C) 2015-2022 Igor A. Maznitsa
 *
 * 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 com.igormaznitsa.mindmap.model;

import static java.util.Objects.requireNonNull;
import static org.apache.commons.text.StringEscapeUtils.unescapeHtml3;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Abstract class describing extra part of a mind maven topic
 *
 * @param  type of saved value
 */
public abstract class Extra implements Serializable, Constants, Cloneable {

  private static final long serialVersionUID = 2547528075256486018L;

  /**
   * Get saved value
   *
   * @return saved value must not be null
   */
  public abstract T getValue();

  /**
   * Type of saved value
   *
   * @return type of saved value, must not e null
   */
  public abstract ExtraType getType();

  /**
   * Get value string representation
   *
   * @return string representation of value, must not be null
   */
  public abstract String getAsString();

  /**
   * Check that the extra is allowed for export operations.
   *
   * @return true if allows, false otherwise
   */
  public boolean isExportable() {
    return true;
  }

  /**
   * Called during write operations and allows to add attributes based on value.
   *
   * @param attributesForWrite map to be saved, can be empty but can't be null
   */
  void addAttributesForWrite(final Map attributesForWrite) {
  }

  /**
   * Called when it is attached to topic and provides way to set some attributes
   *
   * @param topic new target topic, can't be null
   */
  void attachedToTopic(final Topic topic) {

  }

  /**
   * Called when it is removed from topic and provides way to remove some attributes
   *
   * @param topic topic, can't be null
   */
  void detachedToTopic(final Topic topic) {

  }

  /**
   * Get as string during save mind map file.
   *
   * @return string to be saved into mind map file, must not be null
   */
  public abstract String provideAsStringForSave();

  /**
   * Check content for pattern if allowed.
   *
   * @param baseFolder base folder for mind map file, can be null
   * @param pattern    pattern to be tested, must not be null
   * @return true if extra contains content matches with pattern, false otherwise
   */
  public abstract boolean containsPattern(File baseFolder, Pattern pattern);

  /**
   * Write extra into writer.
   *
   * @param out target writer, must not be null
   * @throws IOException thrown if any error
   */
  public final void write(final Writer out) throws IOException {
    out.append("- ").append(getType().name()).append(NEXT_LINE);
    out.append(ModelUtils.makePreBlock(provideAsStringForSave()));
  }

  @Override
  protected abstract Object clone() throws CloneNotSupportedException;

  /**
   * Type of extra.
   */
  public enum ExtraType {
    /**
     * File extension
     */
    FILE,
    /**
     * Link extension
     */
    LINK,
    /**
     * Text note extension
     */
    NOTE,
    /**
     * Link to another topic extension
     */
    TOPIC,
    /**
     * Unknown
     */
    UNKNOWN;

    /**
     * Used during parse extra text from mind map file.
     *
     * @param str string to be preprocessed, can be null
     * @return preprocessed one or null
     */
    public String preprocessString(final String str) {
      String result = null;
      if (str != null) {
        switch (this) {
          case FILE:
          case LINK: {
            try {
              result = str.trim();
              requireNonNull(URI.create(result));
            } catch (IllegalArgumentException ex) {
              result = null;
            }
          }
          break;
          case TOPIC: {
            result = str.trim();
          }
          break;
          default:
            result = str;
            break;
        }
      }
      return result;
    }

    /**
     * Parse loaded extra text as an extra object.
     *
     * @param text       loaded text, can't be null
     * @param attributes map of attributes, can't be null
     * @return parsed extra object
     * @throws URISyntaxException if there is malformed uri
     */
    public Extra parseLoaded(final String text, final Map attributes)
        throws URISyntaxException {
      final String preprocessed = unescapeHtml3(text);
      switch (this) {
        case FILE:
          return new ExtraFile(preprocessed);
        case LINK:
          return new ExtraLink(preprocessed);
        case NOTE: {
          final boolean encrypted = Boolean.parseBoolean(attributes.get(ExtraNote.ATTR_ENCRYPTED));
          final String passwordTip = attributes.get(ExtraNote.ATTR_PASSWORD_HINT);
          return new ExtraNote(preprocessed, encrypted, passwordTip);
        }
        case TOPIC:
          return new ExtraTopic(preprocessed);
        default:
          throw new Error("Unexpected value [" + this.name() + ']');
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy