text:
// HTMLParser Library v0.7 - A java-based parser for HTML
// Copyright (C) Dec 31, 2000 Somik Raha
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// For any questions or suggestions, you can write to me at :
// Email :somik@kizna.com
//
// Postal Address :
// Somik Raha
// R&D Team
// Kizna Corporation
// 2-1-17-6F, Sakamoto Bldg., Moto Azabu, Minato ku, Tokyo, 106 0046, JAPAN

package com.liyo.html;
//////////////////
// Java Imports //
//////////////////

import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.net.*;
import java.util.*;

/**
 * This is the class that the user will use, either to get an iterator into
 * the html page or to directly parse the page and print the results
 */
public class HTMLParser {
    /**
     * The URL or filename to be parsed.
     */
    protected String resourceUrl;
    /**
     * The html reader associated with this parser
     */
    protected HTMLReader reader;
    /**
     * The last read HTML node.
     */
    protected HTMLNode node;
    /**
     * Keeps track of whether the first reading has been performed.
     */
    protected boolean readFlag = false;

    /**
     * 当前解析的数据输入流
     */
    private InputStreamReader inputStreamReader;

    /**
     * 输入流编码格式
     */
    private String charSetName = "SJIS";
    /**
     * Creates a HTMLParser object with the location of the resource (URL or file)
     *
     * @param resourceUrl Either the URL or the filename (autodetects)
     */
    public HTMLParser(String resourceUrl) {
        this.resourceUrl = resourceUrl;
        openConnection();
    }

    public HTMLParser(InputStream inputStream, String url, String charSet){
        this.resourceUrl= url;
        if(StringUtils.isNotBlank(charSet)){
            this.charSetName = charSet;
        }
        try {
            this.inputStreamReader = new InputStreamReader(inputStream, charSetName);
            this.resourceUrl = removeEscapeCharacters(resourceUrl);
            this.resourceUrl = checkEnding(resourceUrl);
            reader = new HTMLReader(inputStreamReader, resourceUrl);
        }catch (IOException e){
            System.err.println("I/O Exception occured while reading " + resourceUrl);        }
    }

    /**
     * Opens the connection with the resource to begin reading, by creating a HTML reader
     * object.
     */
    private void openConnection() {
        try {
            if (resourceUrl.indexOf("http") != -1 || resourceUrl.indexOf("www.") != -1) {
                // Its a web address
                resourceUrl = removeEscapeCharacters(resourceUrl);
                resourceUrl = checkEnding(resourceUrl);
                URL url = new URL(resourceUrl);
                URLConnection uc = url.openConnection();
                reader = new HTMLReader(new InputStreamReader(uc.getInputStream(), charSetName), resourceUrl);
            } else {
                reader = new HTMLReader(new FileReader(resourceUrl), resourceUrl);
            }
        } catch (FileNotFoundException e) {
            System.err.println("Error! File " + resourceUrl + " not found!");
        } catch (MalformedURLException e) {
            System.err.println("Error! URL " + resourceUrl + " Malformed!");
        } catch (IOException e) {
            System.err.println("I/O Exception occured while reading " + resourceUrl);
        }
    }

    /**
     * Returns an iterator (enumeration) to the html nodes. Each node can be a tag/endtag/
     * string/link/image
     */
    public Enumeration elements() {
        return new Enumeration() {
            public boolean hasMoreElements() {
                if (reader == null) return false;
                try {
                    node = reader.readElement();
                    readFlag = true;
                    if (node == null) {
                        return false;
                    } else {
                        return true;
                    }
                } catch (IOException e) {
                    System.err.println("I/O Exception occured while reading " + resourceUrl);
                    return false;
                }
            }

            public Object nextElement() {
                try {
                    if (!readFlag) node = reader.readElement();
                    return node;
                } catch (IOException e) {
                    System.err.println("I/O Exception occured while reading " + resourceUrl);
                    return null;
                }
            }
        };
    }

    /**
     * Parse the given resource, using the filter provided
     */
    public void parse(String filter) {
        HTMLNode node;
        for (Enumeration e = elements(); e.hasMoreElements(); ) {
            node = (HTMLNode) e.nextElement();
            if (node != null) {
                if (filter == null) {
                    node.print();
                } else {
                    // There is a filter. Find if the associated filter of this node
                    // matches the specified filter
                    if (!(node instanceof HTMLTag)) continue;
                    HTMLTag tag = (HTMLTag) node;
                    HTMLTagScanner scanner = tag.getThisScanner();
                    if (scanner == null) continue;
                    String tagFilter = scanner.getFilter();
                    if (tagFilter == null) continue;
                    if (tagFilter.equals(filter)) {
                        node.print();
                    }
                }
            } else {
                System.out.println("Node is null");
            }
        }

    }

    public static String checkEnding(String link) {
        // Check if the link ends in html, htm, or /. If not, add a slash
        int l1 = link.indexOf("html");
        int l2 = link.indexOf("htm");
        if (l1 == -1 && l2 == -1) {
            if (link.charAt(link.length() - 1) != '/') {
                link += "/index.html";
            }
            return link;
        } else {
            return link;
        }
    }

    public static String removeEscapeCharacters(String link) {
        int state = 0;
        String temp = "", retVal = "";
        for (int i = 0; i < link.length(); i++) {
            char ch = link.charAt(i);
            if (state == 4) {
                state = 0;
            }
            if (ch == '#' && state == 0) {
                state = 1;
                continue;
            }
            if (state == 1) {
                if (ch == '3') {
                    state = 2;
                    continue;
                } else {
                    state = 0;
                    retVal += temp;
                }
            }
            if (state == 2) {
                if (ch == '8') {
                    state = 3;
                    continue;
                } else {
                    state = 0;
                    retVal += temp;
                }
            }
            if (state == 3) {
                if (ch == ';') {
                    state = 4;
                    continue;
                } else {
                    state = 0;
                    retVal += temp;
                }
            }
            if (state == 0) {
                retVal += ch;
            } else {
                temp += ch;
            }
        }
        return retVal;
    }

    /*
     * The main program, which can be executed from the command line
     */
    public static void main(String[] args) {
        new HTMLLinkScanner("-l");
        new HTMLImageScanner("-i");
        if (args.length < 1 || args[0].equals("-help")) {
            System.out.println("java -jar Parse.jar <resourceLocn/website> -l");
            System.out.println("   <resourceLocn> the name of the file to be parsed (with complete path if not in current directory)");
            System.out.println("   -l Show only the link tags extracted from the document");
            System.out.println("   -i Show only the image tags extracted from the document");
            System.out.println("   -help This screen");
            System.exit(-1);
        }
        if (args[0].indexOf("http") != -1 || args[0].indexOf("www.") != -1) {
            System.out.println("Parsing website " + args[0]);
        } else {
            System.out.println("Parsing file " + args[0] + "...");
        }
        HTMLParser parser = new HTMLParser(args[0]);
        if (args.length == 2) {
            parser.parse(args[1]);
        } else {
            parser.parse(null);
        }
    }

}


text:
package org.kuali.kra.protocol.actions.submit;

import org.apache.commons.lang.StringUtils;
import org.kuali.kra.infrastructure.KeyConstants;
import org.kuali.kra.rules.KraMaintenanceDocumentRuleBase;
import org.kuali.rice.kns.document.MaintenanceDocument;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * This class is the maintenance document rule for valid submission/type qualifier table.
 */
public abstract class ValidProtoSubTypeQualMaintenanceDocumentRuleBase extends KraMaintenanceDocumentRuleBase {

    private Long oldTypeId = null;
    /**
     *
     * @see org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.core.document.MaintenanceDocument)
     */
    protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
        setOldTYpeId(document);
        ValidProtoSubTypeQual validProtoSubTypeQual = (ValidProtoSubTypeQual) document.getDocumentBusinessObject();
        return validate(validProtoSubTypeQual);
    }

    private void setOldTYpeId(MaintenanceDocument document) {
        if (document.getNewMaintainableObject().getMaintenanceAction().equals(KRADConstants.MAINTENANCE_EDIT_ACTION) ||
            document.getNewMaintainableObject().getMaintenanceAction().equals(KRADConstants.MAINTENANCE_DELETE_ACTION)    ) {
            oldTypeId = ((ValidProtoSubTypeQual)document.getOldMaintainableObject().getDataObject()).getValidProtoSubTypeQualId();
         }
    }
    /**
     *
     * @see org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.core.document.MaintenanceDocument)
     */
    @Override
    protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
        setOldTYpeId(document);
        ValidProtoSubTypeQual validProtoSubTypeQual = (ValidProtoSubTypeQual) document.getDocumentBusinessObject();
        return validate(validProtoSubTypeQual);
    }

    private boolean validate(ValidProtoSubTypeQual validProtoSubTypeQual) {
        boolean valid = validateSubmissionType(validProtoSubTypeQual);
        valid &= validateTypeQualifier(validProtoSubTypeQual) && checkSubmTypeQualifierExists(validProtoSubTypeQual);
        return valid;
    }

    private boolean validateSubmissionType(ValidProtoSubTypeQual validProtoSubTypeQual) {
        boolean valid = true;
        if (StringUtils.isNotBlank(validProtoSubTypeQual.getSubmissionTypeCode())) {
            Map<String, String> fieldValues = new HashMap<String, String>();
            fieldValues.put("submissionTypeCode", validProtoSubTypeQual.getSubmissionTypeCode());
            List<ProtocolSubmissionTypeBase> submissionTypes = (List<ProtocolSubmissionTypeBase>) boService.findMatching(getProtocolSubmissionTypeBOClassHook(), fieldValues);
            if (submissionTypes.isEmpty()) {
                GlobalVariables.getMessageMap().putError("document.newMaintainableObject.submissionTypeCode",
                        KeyConstants.ERROR_SUBMISSION_TYPE_NOT_EXISTS,
                        new String[] { validProtoSubTypeQual.getSubmissionTypeCode() });
                valid = false;
            }
        }
        return valid;
    }

    protected abstract Class<? extends ProtocolSubmissionTypeBase> getProtocolSubmissionTypeBOClassHook();

    private boolean validateTypeQualifier(ValidProtoSubTypeQual validProtoSubTypeQual) {
        boolean valid = true;
        if (StringUtils.isNotBlank(validProtoSubTypeQual.getSubmissionTypeQualCode())) {
            Map<String, String> fieldValues = new HashMap<String, String>();
            fieldValues.put("submissionQualifierTypeCode", validProtoSubTypeQual.getSubmissionTypeQualCode());
            List<ProtocolSubmissionQualifierTypeBase> typeQualifiers = (List<ProtocolSubmissionQualifierTypeBase>) boService.findMatching(getProtocolSubmissionQualifierTypeBOClassHook(), fieldValues);
            if (typeQualifiers.isEmpty()) {
                GlobalVariables.getMessageMap().putError("document.newMaintainableObject.submissionTypeQualCode",
                        KeyConstants.ERROR_TYPE_QUALIFIER_NOT_EXISTS,
                        new String[] { validProtoSubTypeQual.getSubmissionTypeQualCode() });
                valid = false;
            }
        }
        return valid;
    }

    protected abstract Class<? extends ProtocolSubmissionQualifierTypeBase> getProtocolSubmissionQualifierTypeBOClassHook();

    protected abstract Class<? extends ValidProtoSubTypeQual> getValidProtoSubTypeQualBOClassHook();

    private boolean checkSubmTypeQualifierExists(ValidProtoSubTypeQual validProtoSubTypeQual) {
        boolean valid = true;
        if (StringUtils.isNotBlank(validProtoSubTypeQual.getSubmissionTypeCode())
                && StringUtils.isNotBlank(validProtoSubTypeQual.getSubmissionTypeQualCode())) {
            Map<String, String> fieldValues = new HashMap<String, String>();
            fieldValues.put("submissionTypeCode", validProtoSubTypeQual.getSubmissionTypeCode());
            fieldValues.put("submissionTypeQualCode", validProtoSubTypeQual.getSubmissionTypeQualCode());
            List<ValidProtoSubTypeQual> validProtoSubTypeQuals = (List<ValidProtoSubTypeQual>) boService.findMatching(getValidProtoSubTypeQualBOClassHook(), fieldValues);
            if (!validProtoSubTypeQuals.isEmpty()) {
                ValidProtoSubTypeQual existvalidProtoSubTypeQual = validProtoSubTypeQuals.get(0);
                if ((oldTypeId == null || !existvalidProtoSubTypeQual.getValidProtoSubTypeQualId().equals(oldTypeId))
                        &&  validProtoSubTypeQual.getSubmissionTypeCode().equals(existvalidProtoSubTypeQual.getSubmissionTypeCode())
                        &&  validProtoSubTypeQual.getSubmissionTypeQualCode().equals(existvalidProtoSubTypeQual.getSubmissionTypeQualCode())) {
                    GlobalVariables.getMessageMap().putError(
                            "document.newMaintainableObject.submissionTypeCode",
                            KeyConstants.ERROR_SUBMISSION_TYPE_QUALIFIER_EXISTS,
                            new String[] { validProtoSubTypeQual.getSubmissionType().getDescription(),
                                    validProtoSubTypeQual.getSubmissionTypeQualifier().getDescription() });
                    valid = false;
                }
            }
        }
        return valid;

    }
}

redpajama_set_name: RedPajamaGithub


text:
import System.Environment
import System.IO
import Text.ParserCombinators.Parsec
import Control.Monad
import Data.ByteString.Lazy.Char8 as BS hiding (filter,head,drop,take,reverse)
import Control.Applicative hiding ((<|>), many)

{--
kasan(Open usp Tukubai)

designed by Nobuaki Tounaka
written by Ryuichi Ueda

The MIT License

Copyright (C) 2012 Universal Shell Programming Laboratory

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--}

showUsage :: IO ()
showUsage = do System.IO.hPutStr stderr ("Usage    : kasan [+r] [ref=<ref>] key=<n> <file>\n" ++
                "Tue Aug 20 10:23:06 JST 2013\n" ++
                "Open usp Tukubai (LINUX+FREEBSD), Haskell ver.\n")

main :: IO ()
main = do args <- getArgs
          case args of
              ["-h"]     -> showUsage
              ["--help"] -> showUsage
              _          -> mainProc (setOpts args)

mainProc :: Opts -> IO ()
mainProc (Opts rep ref key file) = readF file >>= mainProc' rep ref key

mainProc' :: Bool -> Int -> [Int] -> BS.ByteString -> IO ()
mainProc' rep ref ks cs = out rep [ parseLine ref ks ln | ln <- BS.lines cs ] nullRecord
 where nullRecord = Record [] (BS.pack "") [] []

out :: Bool -> [Record] -> Record -> IO ()
out rep []     _    = do return ()
out rep (r:rs) prep = BS.putStrLn (out' rep newr) >> out rep rs newr
                      where newr = newRecord r prep

out' :: Bool -> Record -> BS.ByteString
out' rep (Record ws refstr fs vs) = BS.unwords $ out'' [1..(Prelude.length ws)] rep fs vs ws

out'' :: [Int] -> Bool -> [Int] -> [Double] -> [BS.ByteString] -> [BS.ByteString]
out'' []     _   _  _  _  = []
out'' (n:ns) rep fs vs ws = ans : out'' ns rep fs rvs ws
        where x = filter (==n) fs
              w = ws !! (n-1)
              nstr = BS.pack $ formatNum $ show $ head vs
              repstr = if rep then nstr else BS.unwords [w,nstr]
              ans = if x == [] then w else repstr
              rvs = if x == [] then vs else (drop 1 vs)

formatNum :: String -> String
formatNum str = if x == [] then str else reverse $ cutZero (reverse str)
        where x = filter (== '.') str

cutZero :: String -> String
cutZero ('.':cs) = cs
cutZero ('0':cs) = cutZero cs
cutZero (c:cs)   = c:cs

newRecord :: Record -> Record -> Record
newRecord (Record ws refstr fs vs) (Record pws prefstr pfs pvs)
  | pvs == []         = Record ws refstr fs vs
  | refstr /= prefstr = Record ws refstr fs vs
  | refstr == prefstr = Record ws refstr fs [ (fst x) + (snd x) | x <- Prelude.zip vs pvs]

parseLine :: Int -> [Int] -> BS.ByteString -> Record
parseLine ref ks ln = Record ws refstr nks vs
          where ws = myWords ln
                nks = [ if k > 0 then k else k + (Prelude.length ws) | k <- ks ]
                refstr = if ref == 0 then (BS.pack "") else (ws !! (ref-1))
                vs = f nks ws
                f [] _      = []
                f (k:nks) ws = (read (BS.unpack $ ws !! (k-1))::Double ) : f nks ws

myWords :: BS.ByteString -> [BS.ByteString]
myWords line = filter (/= x) $ BS.split ' ' line
               where x = BS.pack ""

data Record = Record [BS.ByteString] BS.ByteString [Int] [Double] deriving Show

readF :: String -> IO BS.ByteString
readF "-" = BS.getContents
readF f   = BS.readFile f

data Opts = Opts Bool Int [Int] String | Error String deriving Show

setOpts :: [String] -> Opts
setOpts as = case parse args "" ((Prelude.unwords as) ++ " ") of
                  Right opt -> opt
                  Left err -> Error ( show err )

args = Opts <$> (try(string "+r " >> return True) <|> return False)
            <*> (try(ref) <|> return 0)
            <*> (try(key) <|> return [0])
            <*> (try(filename) <|> return "-")

ref = do string "ref="
         a <- many1 digit
         char ' '
         return (read a)

key = do string "key="
         a <- try(atnums) <|> try(slashnums) <|> simplepos
         char ' '
         return a

atnums = do a <- posnum
            nums <- many1 atnum
            return (a:nums)

atnum = char '@' >> posnum

slashnums = do a <- posnum
               char '/'
               b <- posnum
               return [a..b]

simplepos = do a <- posnum
               return [a]

posnum = try(nfmnum) <|> try(nfnum) <|> intnum

intnum = many1 digit >>= return . read

nfnum = string "NF" >> return 0

nfmnum = do string "NF-"
            a <- many1 digit
            return $ (read a) * (-1)

filename =  many1 ( letter <|> digit <|> symbol )

symbol = oneOf "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"


text:
                Upcoming Rewards

                Past Rewards

          No rewards yet!
          Collected rewards will appear here


text:
package com.intellij.openapi.vfs.impl;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.TraceableDisposable;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author dsl
 */
public class VirtualFilePointerContainerImpl extends TraceableDisposable implements VirtualFilePointerContainer, Disposable {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer");
  @NotNull private final List<VirtualFilePointer> myList = ContainerUtil.createLockFreeCopyOnWriteList();
  @NotNull private final VirtualFilePointerManager myVirtualFilePointerManager;
  @NotNull private final Disposable myParent;
  private final VirtualFilePointerListener myListener;
  private volatile Trinity<String[], VirtualFile[], VirtualFile[]> myCachedThings;
  private volatile long myTimeStampOfCachedThings = -1;
  @NonNls private static final String URL_ATTR = "url";
  private boolean myDisposed;
  private static final boolean TRACE_CREATION = LOG.isDebugEnabled() || ApplicationManager.getApplication().isUnitTestMode();
  VirtualFilePointerContainerImpl(@NotNull VirtualFilePointerManager manager,
                                  @NotNull Disposable parentDisposable,
                                  @Nullable VirtualFilePointerListener listener) {
    //noinspection HardCodedStringLiteral
    super(TRACE_CREATION && !ApplicationInfoImpl.isInStressTest());
    myVirtualFilePointerManager = manager;
    myParent = parentDisposable;
    myListener = listener;
  }

  @Override
  public void readExternal(@NotNull final Element rootChild, @NotNull final String childElements) throws InvalidDataException {
    final List<Element> urls = rootChild.getChildren(childElements);
    for (Element url : urls) {
      final String urlAttribute = url.getAttributeValue(URL_ATTR);
      if (urlAttribute == null) throw new InvalidDataException("path element without url");
      add(urlAttribute);
    }
  }

  @Override
  public void writeExternal(@NotNull final Element element, @NotNull final String childElementName) {
    for (VirtualFilePointer pointer : myList) {
      String url = pointer.getUrl();
      final Element rootPathElement = new Element(childElementName);
      rootPathElement.setAttribute(URL_ATTR, url);
      element.addContent(rootPathElement);
    }
  }

  @Override
  public void moveUp(@NotNull String url) {
    int index = indexOf(url);
    if (index <= 0) return;
    dropCaches();
    ContainerUtil.swapElements(myList, index - 1, index);
  }

  @Override
  public void moveDown(@NotNull String url) {
    int index = indexOf(url);
    if (index < 0 || index + 1 >= myList.size()) return;
    dropCaches();
    ContainerUtil.swapElements(myList, index, index + 1);
  }

  private int indexOf(@NotNull final String url) {
    for (int i = 0; i < myList.size(); i++) {
      final VirtualFilePointer pointer = myList.get(i);
      if (url.equals(pointer.getUrl())) {
        return i;
      }
    }

    return -1;
  }

  @Override
  public void killAll() {
    myList.clear();
  }

  @Override
  public void add(@NotNull VirtualFile file) {
    assert !myDisposed;
    dropCaches();
    final VirtualFilePointer pointer = create(file);
    myList.add(pointer);
  }

  @Override
  public void add(@NotNull String url) {
    assert !myDisposed;
    dropCaches();
    final VirtualFilePointer pointer = create(url);
    myList.add(pointer);
  }

  @Override
  public void remove(@NotNull VirtualFilePointer pointer) {
    assert !myDisposed;
    dropCaches();
    final boolean result = myList.remove(pointer);
    LOG.assertTrue(result);
  }

  @Override
  @NotNull
  public List<VirtualFilePointer> getList() {
    assert !myDisposed;
    return Collections.unmodifiableList(myList);
  }

  @Override
  public void addAll(@NotNull VirtualFilePointerContainer that) {
    assert !myDisposed;
    dropCaches();

    for (final VirtualFilePointer pointer : that.getList()) {
      myList.add(duplicate(pointer));
    }
  }

  private void dropCaches() {
    myTimeStampOfCachedThings = -1; // make it never equal to myVirtualFilePointerManager.getModificationCount()
    myCachedThings = EMPTY;
  }

  @Override
  @NotNull
  public String[] getUrls() {
    return getOrCache().first;
  }

  @NotNull
  private Trinity<String[], VirtualFile[], VirtualFile[]> getOrCache() {
    assert !myDisposed;
    long timeStamp = myTimeStampOfCachedThings;
    Trinity<String[], VirtualFile[], VirtualFile[]> cached = myCachedThings;
    return timeStamp == myVirtualFilePointerManager.getModificationCount() ? cached : cacheThings();
  }

  private static final Trinity<String[], VirtualFile[], VirtualFile[]> EMPTY =
    Trinity.create(ArrayUtil.EMPTY_STRING_ARRAY, VirtualFile.EMPTY_ARRAY, VirtualFile.EMPTY_ARRAY);

  @NotNull
  private Trinity<String[], VirtualFile[], VirtualFile[]> cacheThings() {
    Trinity<String[], VirtualFile[], VirtualFile[]> result;
    if (myList.isEmpty()) {
      result = EMPTY;
    }
    else {
      List<VirtualFile> cachedFiles = new ArrayList<>(myList.size());
      List<String> cachedUrls = new ArrayList<>(myList.size());
      List<VirtualFile> cachedDirectories = new ArrayList<>(myList.size() / 3);
      boolean allFilesAreDirs = true;
      for (VirtualFilePointer v : myList) {
        VirtualFile file = v.getFile();
        String url = v.getUrl();
        cachedUrls.add(url);
        if (file != null) {
          cachedFiles.add(file);
          if (file.isDirectory()) {
            cachedDirectories.add(file);
          }
          else {
            allFilesAreDirs = false;
          }
        }
      }
      VirtualFile[] directories = VfsUtilCore.toVirtualFileArray(cachedDirectories);
      VirtualFile[] files = allFilesAreDirs ? directories : VfsUtilCore.toVirtualFileArray(cachedFiles);
      String[] urlsArray = ArrayUtil.toStringArray(cachedUrls);
      result = Trinity.create(urlsArray, files, directories);
    }
    myCachedThings = result;
    myTimeStampOfCachedThings = myVirtualFilePointerManager.getModificationCount();
    return result;
  }

  @Override
  @NotNull
  public VirtualFile[] getFiles() {
    return getOrCache().second;
  }

  @Override
  @NotNull
  public VirtualFile[] getDirectories() {
    return getOrCache().third;
  }

  @Override
  @Nullable
  public VirtualFilePointer findByUrl(@NotNull String url) {
    assert !myDisposed;
    for (VirtualFilePointer pointer : myList) {
      if (url.equals(pointer.getUrl())) return pointer;
    }
    return null;
  }

  @Override
  public void clear() {
    dropCaches();
    killAll();
  }

  @Override
  public int size() {
    return myList.size();
  }

  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof VirtualFilePointerContainerImpl)) return false;

    final VirtualFilePointerContainerImpl virtualFilePointerContainer = (VirtualFilePointerContainerImpl)o;

    return myList.equals(virtualFilePointerContainer.myList);
  }

  public int hashCode() {
    return myList.hashCode();
  }

  protected VirtualFilePointer create(@NotNull VirtualFile file) {
    return myVirtualFilePointerManager.create(file, myParent, myListener);
  }

  protected VirtualFilePointer create(@NotNull String url) {
    return myVirtualFilePointerManager.create(url, myParent, myListener);
  }

  protected VirtualFilePointer duplicate(@NotNull VirtualFilePointer virtualFilePointer) {
    return myVirtualFilePointerManager.duplicate(virtualFilePointer, myParent, myListener);
  }

  @NotNull
  @NonNls
  @Override
  public String toString() {
    return "VFPContainer: " + myList/*+"; parent:"+myParent*/;
  }

  @Override
  @NotNull
  public VirtualFilePointerContainer clone(@NotNull Disposable parent) {
    return clone(parent, null);
  }

  @Override
  @NotNull
  public VirtualFilePointerContainer clone(@NotNull Disposable parent, @Nullable VirtualFilePointerListener listener) {
    assert !myDisposed;
    VirtualFilePointerContainer clone = myVirtualFilePointerManager.createContainer(parent, listener);
    for (VirtualFilePointer pointer : myList) {
      clone.add(pointer.getUrl());
    }
    return clone;
  }

  @Override
  public void dispose() {
    assert !myDisposed;
    myDisposed = true;
    kill(null);
  }
}