text:
package au.edu.labshare.rigclient.action.files.tests;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;

import java.io.File;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;

import junit.framework.TestCase;

import org.junit.Before;
import org.junit.Test;

import au.edu.labshare.rigclient.action.files.DirectoryContentsFilesDetector;
import au.edu.uts.eng.remotelabs.rigclient.util.ConfigFactory;
import au.edu.uts.eng.remotelabs.rigclient.util.IConfig;

/**
 * Tests the {@link DirectoryContentsFilesDetector} class.
 */
public class DirectoryContentsFilesDetectorTester extends TestCase
{
    /** Object of class under test. */
    private DirectoryContentsFilesDetector detector;

    /** Mock configuration. */
    private IConfig mockConfig;

    @Override
    @Before
    protected void setUp() throws Exception
    {
        super.setUp();

        this.mockConfig = createMock(IConfig.class);

        /* Logging configuration. */
        expect(this.mockConfig.getProperty("Logger_Type")).andReturn("SystemErr");
        expect(this.mockConfig.getProperty("Log_Level")).andReturn("DEBUG");
        expect(this.mockConfig.getProperty("Default_Log_Format", "[__LEVEL__] - [__ISO8601__] - __MESSAGE__"))
            .andReturn("[__LEVEL__] - [__ISO8601__] - __MESSAGE__");
        expect(this.mockConfig.getProperty("FATAL_Log_Format")).andReturn(null);
        expect(this.mockConfig.getProperty("PRIORITY_Log_Format")).andReturn(null);
        expect(this.mockConfig.getProperty("ERROR_Log_Format")).andReturn(null);
        expect(this.mockConfig.getProperty("WARN_Log_Format")).andReturn(null);
        expect(this.mockConfig.getProperty("INFO_Log_Format")).andReturn(null);
        expect(this.mockConfig.getProperty("DEBUG_Log_Format")).andReturn(null);

        /* Directory detector configuration. */
        expect(this.mockConfig.getProperty("Files_Detector_Directory")).andReturn("/tmp");
        expect(this.mockConfig.getProperty("Files_Detector_Included_Files", "")).andReturn("");
        expect(this.mockConfig.getProperty("Files_Detector_Excluded_Files", "")).andReturn("");
        expect(this.mockConfig.getProperty("Files_Detector_Nest_Depth", "-1")).andReturn("-1");
        replay(this.mockConfig);

        Field f = ConfigFactory.class.getDeclaredField("instance");
        f.setAccessible(true);
        f.set(null, this.mockConfig);

        this.detector = new DirectoryContentsFilesDetector();
    }
    @SuppressWarnings("unchecked")
    @Test
    public void testDefaultConf() throws Exception
    {
        verify(this.mockConfig);

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        String tmp = (String)f.get(this.detector);
        assertNotNull(tmp);
        assertEquals("/tmp", tmp);

        f = DirectoryContentsFilesDetector.class.getDeclaredField("nestDepth");
        f.setAccessible(true);
        int dep = (Integer)f.get(this.detector);
        assertEquals(-1, dep);

        f = DirectoryContentsFilesDetector.class.getDeclaredField("includedFiles");
        f.setAccessible(true);
        Set<String> inc = (Set<String>)f.get(this.detector);
        assertNotNull(inc);
        assertEquals(0, inc.size());

        f = DirectoryContentsFilesDetector.class.getDeclaredField("excludedFiles");
        f.setAccessible(true);
        Set<String> exc = (Set<String>)f.get(this.detector);
        assertNotNull(exc);
        assertEquals(0, exc.size());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testDefault() throws Exception
    {
        reset(this.mockConfig);
        expect(this.mockConfig.getProperty("Files_Detector_Directory")).andReturn("foobar");
        expect(this.mockConfig.getProperty("Files_Detector_Included_Files", "")).andReturn(" file2; file3;*.fi");
        expect(this.mockConfig.getProperty("Files_Detector_Excluded_Files", "")).andReturn("*.tmp; *~");
        expect(this.mockConfig.getProperty("Files_Detector_Nest_Depth", "-1")).andReturn("3");
        replay(this.mockConfig);

        DirectoryContentsFilesDetector cfd = new DirectoryContentsFilesDetector();
        verify(this.mockConfig);

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        String tmp = (String)f.get(cfd);
        assertNotNull(tmp);
        assertEquals("foobar", tmp);

        f = DirectoryContentsFilesDetector.class.getDeclaredField("nestDepth");
        f.setAccessible(true);
        int dep = (Integer)f.get(cfd);
        assertEquals(3, dep);

        f = DirectoryContentsFilesDetector.class.getDeclaredField("includedFiles");
        f.setAccessible(true);
        Set<String> inc = (Set<String>)f.get(cfd);
        assertNotNull(inc);
        assertEquals(3, inc.size());
        assertTrue(inc.contains("file2"));
        assertTrue(inc.contains("file3"));
        assertTrue(inc.contains("*.fi"));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("excludedFiles");
        f.setAccessible(true);
        Set<String> exc = (Set<String>)f.get(cfd);
        assertNotNull(exc);
        assertEquals(2, exc.size());
        assertTrue(exc.contains("*.tmp"));
        assertTrue(exc.contains("*~"));
    }

    @Test
    public void testDetermineTargetAbsolute() throws Exception
    {
        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("tmp", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(new File("/tmp")));
    }

    @Test
    public void testDetermineTargetRelative() throws Exception
    {
        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "./conf/conf.example");

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("conf.example", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(new File("./conf/conf.example").getAbsoluteFile()));
    }

    @Test
    public void testDetermineTargetRelative2() throws Exception
    {
        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "conf/conf.example");

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("conf.example", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(new File("./conf/conf.example").getCanonicalFile()));
    }

    @Test
    public void testDetermineTargetAbsoluteNested() throws Exception
    {
        File targetDir = new File("/tmp/targetDir/");
        assertTrue(targetDir.mkdir());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, targetDir.getAbsolutePath());

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("targetDir", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(targetDir));

        targetDir.delete();
    }

    @Test
    public void testDetermineTargetAbsoluteNestedDeep() throws Exception
    {
        File targetDir = new File("/tmp/");
        for (int i = 0; i < 10; i++)
        {
            targetDir = new File(targetDir, "nest" + i);
        }

        targetDir = new File(targetDir, "targetDir");
        assertTrue(targetDir.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, targetDir.getAbsolutePath());

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("targetDir", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(targetDir));

        targetDir.delete();
        for (int i = 10; i >= 0; i--)
        {
            String path = "/tmp";
            for (int j = 0; j < i; j++)
            {
                path += "/nest" + j;
            }

            new File(path).delete();
        }
    }

    @Test
    public void testDetermineTargetDoesNotExist() throws Exception
    {
        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/does/not/exists");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNull(target);
    }

    @Test
    public void testDetermineTargetUser() throws Exception
    {
        File file = new File("/tmp/mdiponio/dir");
        assertTrue(file.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__USER__/dir");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("dir", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(file));

        file.delete();
        new File("/tmp/mdiponio").delete();
    }

    @Test
    public void testDetermineTargetUser2() throws Exception
    {
        File file = new File("/tmp/mdiponio");
        assertTrue(file.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__USER__/");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals("mdiponio", target.getName());
        assertTrue(target.isDirectory());
        assertTrue(target.equals(file));

        file.delete();
    }

    @Test
    public void testDetermineTargetUser3() throws Exception
    {
        File file = new File("/tmp/mdiponio");
        assertTrue(file.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__USER__/dir");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNull(target);
        file.delete();
    }

    @Test
    public void testDetermineTargetUser4() throws Exception
    {
        File file = new File("/tmp/mdiponio/foo");
        assertTrue(file.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__USER__/dir");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "tuser");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNull(target);
        file.delete();
        new File("/tmp/mdiponio").delete();
    }

    @Test
    public void testDetermineTargetEpoch() throws Exception
    {
        Date date = new Date();
        Thread.sleep(1000);

        File file = new File("/tmp/mdiponio/" + System.currentTimeMillis() / 1000);
        assertTrue(file.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__USER__/__EPOCH_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
        new File("/tmp/mdiponio").delete();
    }

    @Test
    public void testDetermineTargetEpochEarlierDir() throws Exception
    {
        File file = new File("/tmp/" + (System.currentTimeMillis() / 1000) + "/__USER__/");
        assertTrue(file.mkdirs());

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__EPOCH_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        Thread.sleep(1000);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);
        assertNull(target);

        File parent = file.getParentFile();
        file.delete();
        parent.delete();
    }

    @Test
    public void testDetermineTargetISO() throws Exception
    {
        File file = new File("/tmp/2013-03-12");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 11);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO2() throws Exception
    {
        File file = new File("/tmp/2013-03-12");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 12);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO3() throws Exception
    {
        File file = new File("/tmp/2013-03-12");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 13);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNull(target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO4() throws Exception
    {
        File file = new File("/tmp/2013-03-12T11:00:00");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 12);
        cal.set(Calendar.HOUR_OF_DAY, 11);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO5() throws Exception
    {
        File file = new File("/tmp/2013-03-12T11:00:01");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 12);
        cal.set(Calendar.HOUR_OF_DAY, 11);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO6() throws Exception
    {
        File file = new File("/tmp/2013-03-12T11:01:00");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 12);
        cal.set(Calendar.HOUR_OF_DAY, 11);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO7() throws Exception
    {
        File file = new File("/tmp/2013-03-12T12:00:00");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 12);
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        file.delete();
    }

    @Test
    public void testDetermineTargetISO8() throws Exception
    {
        File file = new File("/tmp/2013-03-12T10:59:59");
        file.mkdir();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2013);
        cal.set(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, 12);
        cal.set(Calendar.HOUR_OF_DAY, 11);
        cal.set(Calendar.MINUTE, 00);
        cal.set(Calendar.SECOND, 00);
        Date date = cal.getTime();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__ISO8601_AFTER_ASSIGN__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNull(target);

        file.delete();
    }

    @Test
    public void testDetermineTargetGlob() throws Exception
    {
        File file = new File("/tmp/nested3/dir");
        file.mkdirs();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/*/dir");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        File par = file.getParentFile();
        file.delete();
        par.delete();
    }

    @Test
    public void testDetermineTargetGlobGlob() throws Exception
    {
        File file = new File("/tmp/nested3/nested4/dir");
        file.mkdirs();

        File falsePath = new File("/tmp/nested1/nested2");
        falsePath.mkdirs();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/*/*/dir");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        File par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }

        file = falsePath;
        par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }
    }

    @Test
    public void testDetermineTargetGlobGlob2() throws Exception
    {
        File file = new File("/tmp/nested3/nested4/mdiponio");
        file.mkdirs();

        File falsePath = new File("/tmp/nested1/nested2");
        falsePath.mkdirs();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/*/*/__USER__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, new Date());

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        File par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }

        file = falsePath;
        par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }
    }

    @Test
    public void testDetermineTargetGlobGlob3() throws Exception
    {
        Date date = new Date();
        Thread.sleep(1001);

        File file = new File("/tmp/" + (System.currentTimeMillis() / 1000) + "/nested4/mdiponio");
        file.mkdirs();

        File falsePath = new File("/tmp/nested1/nested2");
        falsePath.mkdirs();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__EPOCH_AFTER_ASSIGN__/*/__USER__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertTrue((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNotNull(target);
        assertEquals(file, target);

        File par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }

        file = falsePath;
        par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }
    }

    @Test
    public void testDetermineTargetGlobNotFound() throws Exception
    {
        Date date = new Date();
        Thread.sleep(1001);

        File file = new File("/tmp/" + (System.currentTimeMillis() / 1000) + "/nested4/");
        file.mkdirs();

        File falsePath = new File("/tmp/nested1/nested2");
        falsePath.mkdirs();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("targetPattern");
        f.setAccessible(true);
        f.set(this.detector, "/tmp/__EPOCH_AFTER_ASSIGN__/*/__USER__");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionUser");
        f.setAccessible(true);
        f.set(this.detector, "mdiponio");

        f = DirectoryContentsFilesDetector.class.getDeclaredField("sessionStarted");
        f.setAccessible(true);
        f.set(this.detector, date);

        Method meth = DirectoryContentsFilesDetector.class.getDeclaredMethod("determineTarget", File.class,
                String[].class, int.class);
        meth.setAccessible(true);
        assertFalse((Boolean)meth.invoke(this.detector, null, null, 0));

        f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        File target = (File)f.get(this.detector);

        assertNull(target);

        File par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }

        file = falsePath;
        par = file.getParentFile();
        while (!"tmp".equals(file.getName()))
        {
            file.delete();
            file = par;
            par = file.getParentFile();
        }
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveList() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 10, false);

        assertNotNull(contents);

        assertEquals(5, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertTrue(contents.contains(file4));
        assertTrue(contents.contains(file5));

        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveListEmpty() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 10, false);

        assertNotNull(contents);

        assertEquals(0, contents.size());

        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveNesting() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 0, false);

        assertNotNull(contents);

        assertEquals(3, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertFalse(contents.contains(file4));
        assertFalse(contents.contains(file5));

        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveNesting2() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 0, false);

        assertNotNull(contents);

        assertEquals(3, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertFalse(contents.contains(file4));
        assertFalse(contents.contains(file5));

        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveNesting3() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 1, false);

        assertNotNull(contents);

        assertEquals(5, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertTrue(contents.contains(file4));
        assertTrue(contents.contains(file5));

        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveNesting4() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        File nested2 = new File("/tmp/target/nested/nested2");
        nested2.mkdir();
        File file6 = new File("/tmp/target/nested/nested2/file6");
        file6.createNewFile();
        File file7 = new File("/tmp/target/nested/nested2/file7");
        file7.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 2, false);

        assertNotNull(contents);

        assertEquals(7, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertTrue(contents.contains(file4));
        assertTrue(contents.contains(file5));
        assertTrue(contents.contains(file6));
        assertTrue(contents.contains(file7));

        file7.delete();
        file6.delete();
        nested2.delete();
        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveNesting5() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        File nested2 = new File("/tmp/target/nested/nested2");
        nested2.mkdir();
        File file6 = new File("/tmp/target/nested/nested2/file6");
        file6.createNewFile();
        File file7 = new File("/tmp/target/nested/nested2/file7");
        file7.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 1, false);

        assertNotNull(contents);

        assertEquals(5, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertTrue(contents.contains(file4));
        assertTrue(contents.contains(file5));
        assertFalse(contents.contains(file6));
        assertFalse(contents.contains(file7));

        file7.delete();
        file6.delete();
        nested2.delete();
        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testRecursiveNesting6() throws Exception
    {
        File target = new File("/tmp/target");
        target.mkdir();

        File file1 = new File("/tmp/target/file1");
        file1.createNewFile();
        File file2 = new File("/tmp/target/file2");
        file2.createNewFile();
        File file3 = new File("/tmp/target/file3");
        file3.createNewFile();

        File nested = new File("/tmp/target/nested");
        nested.mkdir();
        File file4 = new File("/tmp/target/nested/file4");
        file4.createNewFile();
        File file5 = new File("/tmp/target/nested/file5");
        file5.createNewFile();

        File nested2 = new File("/tmp/target/nested/nested2");
        nested2.mkdir();
        File file6 = new File("/tmp/target/nested/nested2/file6");
        file6.createNewFile();
        File file7 = new File("/tmp/target/nested/nested2/file7");
        file7.createNewFile();

        Field f = DirectoryContentsFilesDetector.class.getDeclaredField("target");
        f.setAccessible(true);
        f.set(this.detector, target);

        Method m = DirectoryContentsFilesDetector.class.getDeclaredMethod("recursiveList", File.class, int.class, boolean.class);
        m.setAccessible(true);
        Set<File> contents = (Set<File>)m.invoke(this.detector, target, 0, false);

        assertNotNull(contents);

        assertEquals(3, contents.size());

        assertTrue(contents.contains(file1));
        assertTrue(contents.contains(file2));
        assertTrue(contents.contains(file3));
        assertFalse(contents.contains(file4));
        assertFalse(contents.contains(file5));
        assertFalse(contents.contains(file6));
        assertFalse(contents.contains(file7));

        file7.delete();
        file6.delete();
        nested2.delete();
        file4.delete();
        file5.delete();
        nested.delete();
        file3.delete();
        file2.delete();
        file1.delete();
        target.delete();
    }

    @Test
    public void testIsFileOpen() throws Exception
    {
        File file = new File("/tmp/test-open-file");
        file.createNewFile();

        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("isFileOpen", File.class);
        method.setAccessible(true);
        assertFalse((Boolean)method.invoke(this.detector, file));

        file.delete();
    }

    @Test
    public void testIsFileOpenAlreadyLockedInProcess() throws Exception
    {
        File file = new File("/tmp/test-open-file");
        file.createNewFile();

        FileChannel chan = new RandomAccessFile(file, "rw").getChannel();
        FileLock lock = chan.tryLock();
        assertNotNull(lock);

        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("isFileOpen", File.class);
        method.setAccessible(true);
        assertTrue((Boolean)method.invoke(this.detector, file));

        lock.release();
        assertFalse((Boolean)method.invoke(this.detector, file));

        chan.close();
        file.delete();
    }

    @Test
    public void testIsFileOpenAlreadyLockedOutOfProcess() throws Exception
    {
        File file = new File("/tmp/test-open-file");
        file.createNewFile();

        Process proc = new ProcessBuilder("java", "-cp", "test/resources/DirectoryContentsFilesDetector/",
                "TestFileLock", file.getAbsolutePath()).start();
        Thread.sleep(500);

        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("isFileOpen", File.class);
        method.setAccessible(true);
        assertTrue((Boolean)method.invoke(this.detector, file));

        proc.waitFor();
        assertFalse((Boolean)method.invoke(this.detector, file));

        file.delete();
    }

    @Test
    public void testIsFileOpenAlreadyLockedOutOfProcessFnctl() throws Exception
    {
        File file = new File("/tmp/foo.txt");
        file.createNewFile();

        Process proc = new ProcessBuilder("./test/resources/DirectoryContentsFilesDetector/test-file-lock-fnctl", file.getAbsolutePath()).start();
        PrintWriter writer = new PrintWriter(proc.getOutputStream());
        Thread.sleep(500);

        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("isFileOpen", File.class);
        method.setAccessible(true);
        assertTrue((Boolean)method.invoke(this.detector, file));
        writer.print('a'); // Tell to unlock
        writer.flush();

        assertFalse((Boolean)method.invoke(this.detector, file));
        writer.print('a'); // Tell to shutdown
        writer.flush();

        assertEquals(0, proc.waitFor());
        assertFalse((Boolean)method.invoke(this.detector, file));

        writer.close();
        file.delete();
    }

    @Test
    public void testIsFileOpenAlreadyLockedOutOfProcessLockf() throws Exception
    {
        File file = new File("/tmp/foo.txt");
        file.createNewFile();

        Process proc = new ProcessBuilder("./test/resources/DirectoryContentsFilesDetector/test-file-lock-lockf",
                file.getAbsolutePath()).start();
        PrintWriter writer = new PrintWriter(proc.getOutputStream());
        Thread.sleep(500);

        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("isFileOpen", File.class);
        method.setAccessible(true);
        assertTrue((Boolean)method.invoke(this.detector, file));
        writer.print('a'); // Tell to unlock
        writer.flush();

        assertFalse((Boolean)method.invoke(this.detector, file));
        writer.print('a'); // Tell to shutdown
        writer.flush();

        assertEquals(0, proc.waitFor());
        assertFalse((Boolean)method.invoke(this.detector, file));

        writer.close();
        file.delete();
    }

    @Test
    public void testMatchPatternEquals() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "foo.txt", "foo.txt"));
    }

    @Test
    public void testMatchPatternEqualsFalse() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertFalse((Boolean)method.invoke(this.detector, "foo.txt", "bar.txt"));
    }

    @Test
    public void testMatchPatternEndGlob() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "foo.*", "foo.txt"));
    }

    @Test
    public void testMatchPatternEndGlobFalse() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertFalse((Boolean)method.invoke(this.detector, "foo.*", "bar.txt"));
    }

    @Test
    public void testMatchPatternStartGlob() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "*.txt", "foo.txt"));
    }

    @Test
    public void testMatchPatternStartGlobFalse() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertFalse((Boolean)method.invoke(this.detector, "*.txt", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "*", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob1() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "f*.bar", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob2() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "f*o.b*r", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob3() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "*o.b*r", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob4() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "**r", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob5() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertFalse((Boolean)method.invoke(this.detector, "*fo.b*r", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob6() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertTrue((Boolean)method.invoke(this.detector, "foo*.bar", "foo.bar"));
    }

    @Test
    public void testMatchPatternGlob7() throws Exception
    {
        Method method = DirectoryContentsFilesDetector.class.getDeclaredMethod("matchPattern", String.class, String.class);
        method.setAccessible(true);

        assertFalse((Boolean)method.invoke(this.detector, "f*s*.bar", "foo.bar"));
    }

    @Test
    public void testGetActionType()
    {
        assertEquals("Directory Files Detector", this.detector.getActionType());
    }
}


text:
//
//  ACRegisterViewController.m
//  A-cyclist
//
//  Created by tunny on 15/7/18.
//  Copyright (c) 2015年 tunny. All rights reserved.
//

#import "ACRegisterViewController.h"
#import "ACDataBaseTool.h"
#import "ACCacheDataTool.h"
#import "ACGlobal.h"
#import "ACUtility.h"
#import "ACUserModel.h"
#import "NSString+Extension.h"
#import "ACSettingProfileInfoViewController.h"

@interface ACRegisterViewController ()
/** 手机号 */
@property (weak, nonatomic) IBOutlet UITextField *registerPhone;
/** 验证码 */
@property (weak, nonatomic) IBOutlet UITextField *registerSms;
/** 密码 */
@property (weak, nonatomic) IBOutlet UITextField *registerPwd;
/** 输入框容器view */
@property (weak, nonatomic) IBOutlet UIView *containterView;
/** 获取验证码按钮 */
@property (weak, nonatomic) IBOutlet UIButton *smsNumBtn;
/** timer */
@property (nonatomic, strong) NSTimer *timer;
/** 记录秒数 */
@property (nonatomic, assign) NSUInteger seconds;
@property (weak, nonatomic) IBOutlet UIButton *registerBtn;

@end

@implementation ACRegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initSomethingForSuper];

    if (RegisterPushFromTypeRegister == self.from) {    //登录
        [self.registerBtn setTitle:@"注册" forState:UIControlStateNormal];
    } else if (RegisterPushFromTypeRestPwd == self.from) {  //重置
        [self.registerBtn setTitle:@"重置" forState:UIControlStateNormal];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-  (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    /* 手动移除通知,并退出键盘 */
    [self.view endEditing:YES];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    // 销毁timer
    [self.timer invalidate];
    // 置nil
    self.timer = nil;
}

/**
 *  设置基类属性
 */
- (void)initSomethingForSuper
{
    //传入textField数组
    self.textFieldArray = [NSMutableArray arrayWithArray:@[self.registerPhone, self.registerSms, self.registerPwd]];
    //传入textField与键盘的偏移位置(64为多余的导航栏高度)
    self.textFieldOffset = 10 + 64;
    //传入需要移动和参照的View
    self.contentView = self.containterView;
}

/**
 *  返回登录界面
 */
- (IBAction)cancleBack
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

/**
 *  点击获取验证码
 */
- (IBAction)getMaskNum:(id)sender
{
    if (![self.registerPhone.text isAvailPhoneNumber]) {
        [self showMsgCenter:ACInvalidPhone];
        return;
    }
    __weak typeof (self)weakSelf = self;
    if (RegisterPushFromTypeRegister == self.from) {
        //如果已经注册过了禁止注册
        [ACDataBaseTool checkAlreadyUserWithPhoneNum:self.registerPhone.text withResultBlock:^(BOOL isSuccessful, NSError *error) {
            if (isSuccessful) {
                [weakSelf showMsgCenter:@"该号码已注册"];
                return;
            }
        }];
    }

    //请求验证码
    [ACDataBaseTool requestSMSCodeWithPhoneNum:self.registerPhone.text template:nil block:^(int number, NSError *error) {
        if (error) {
            [weakSelf showMsgCenter:@"发送验证码失败,请稍后再试"];
        } else {
            //创建一个时钟
            weakSelf.seconds = 60;
            weakSelf.smsNumBtn.userInteractionEnabled = NO;
            weakSelf.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop] addTimer:weakSelf.timer forMode:NSRunLoopCommonModes];
        }
    }];
}

- (void)updateTimer:(NSTimer *)timer
{
    if (0 == self.seconds) {
        //停止时钟
        [self.timer invalidate];
        [self.smsNumBtn setTitle:@"获取验证码" forState:UIControlStateNormal];
        self.smsNumBtn.userInteractionEnabled = YES;
    } else {
        NSString *temp = [NSString stringWithFormat:@"%lu 秒", (unsigned long)self.seconds];
        [self.smsNumBtn setTitle:temp forState:UIControlStateNormal];
        self.seconds--;
    }

}

/**
 *  注册账户
 */
- (IBAction)registerAcount
{
    __block NSString *phoneNum = self.registerPhone.text;
    if (![phoneNum isAvailPhoneNumber]) {
        [self.HUD hideErrorMessage:ACInvalidPhone];
        return;
    }
    if (self.registerSms.text.length <= 0) {
        [self.HUD hideErrorMessage:ACInvalidSMSMask];
        return;
    }

    __block NSString *pwd = self.registerPwd.text;
    if (!pwd) {
        [self.HUD hideErrorMessage:ACPasswordError];
        return;
    }
    //验证用户
    __weak typeof (self)weakSelf = self;
    if (RegisterPushFromTypeRegister == self.from) {    //注册
        //注册登录
        [self showHUD_Msg:@"注册登录中"];
        [ACDataBaseTool signUpWithPhone:phoneNum smsMask:self.registerSms.text passWord:pwd success:^(ACUserModel *user) {
            [weakSelf.HUD hide:YES];
            UIWindow *window = [UIApplication sharedApplication].keyWindow;
            user.password = pwd;
            //本地缓存
            [ACCacheDataTool saveUserInfo:user withObjectId:user.objectId];
            //跳转至settingProfileVC
            ACSettingProfileInfoViewController *setProfileVC = [[ACSettingProfileInfoViewController alloc] init];
            setProfileVC.pushFromType = PushFromTypeLogin;
            UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:setProfileVC];
            window.rootViewController = nav;
        } failure:^(NSError *error) {
            [weakSelf.HUD hide:YES];
            [weakSelf.HUD hideErrorMessage:ACLoginError];
        }];
    } else if (RegisterPushFromTypeRestPwd == self.from) {  //重置密码
        [self showHUD_Msg:@"正在加载"];
        [ACDataBaseTool resetPasswordWithCode:weakSelf.registerSms.text password:pwd block:^(BOOL isSuccessful, NSError *error) {
            if (isSuccessful) {
                [weakSelf.HUD hide:YES];
                [weakSelf.HUD hideSuccessMessage:ACRestPasswordSuccess];
                [weakSelf dismissViewControllerAnimated:YES completion:nil];
            } else {
                [weakSelf.HUD hide:YES];
                [weakSelf.HUD hideErrorMessage:ACRestPasswordError];
            }
        }];
    }
}

@end

redpajama_set_name: RedPajamaGithub


text:
package scato
package clazz

trait MonadInstances {
  implicit val identity: Monad[Identity] = new MonadClass[Identity] {
    override def map[A, B](fa: Identity[A])(f: A => B): Identity[B] = Identity(f(fa.run))
    override def ap[A, B](fa: Identity[A])(f: Identity[A => B]): Identity[B] = Identity(f.run.apply(fa.run))
    override def pure[A](a: A): Identity[A] = Identity(a)
    override def flatMap[A, B](oa: Identity[A])(f: A => Identity[B]): Identity[B] = f(oa.run)
  }
}


text:
.. Copyright 2018 The Cartographer Authors

.. 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.

=============
Going further
=============

Cartographer is not only a great SLAM algorithm, it also comes with a fully-featured implementation that brings lots of "extra" features.
This page lists some of those less known functionalities.

More input
==========

If you have a source of odometry (such as a wheel encoder) publishing on a ``nav_msgs/Odometry`` topic and want to use it to improve Cartographer's localization, you can add an input to your ``.lua`` configuration files:

..  code-block:: lua

    use_odometry = true

The messages will be expected on the ``odom`` topic.

A GPS publishing on a ``sensor_msgs/NavSatFix`` topic named ``fix`` can improve the global SLAM:

..  code-block:: lua

    use_nav_sat = true

For landmarks publishing on a ``cartographer_ros_msgs/LandmarkList`` (`message defined in cartographer_ros`_) topic named ``landmark``:

..  code-block:: lua

    use_landmarks = true

.. _message defined in cartographer_ros: https://github.com/cartographer-project/cartographer_ros/blob/4b39ee68c7a4d518bf8d01a509331e2bc1f514a0/cartographer_ros_msgs/msg/LandmarkList.msg

Localization only
=================

If you have a map you are happy with and want to reduce computations, you can use the localization-only mode of Cartographer which will run SLAM against the existing map and won't build a new one.
This is enabled by running ``cartographer_node`` with a ``-load_state_filename`` argument and by defining the following line in your lua config:

..  code-block:: lua

    TRAJECTORY_BUILDER.pure_localization_trimmer = {
        max_submaps_to_keep = 3,
    }

IMU Calibration
===============

When performing the global optimization, Ceres tries to improve the pose between your IMU and range finding sensors.
A well chosen acquisition with lots of loop closure constraints (for instance if your robot goes on a straight line and then back) can improve the quality of those corrections and become a reliable source of pose correction.
You can then use Cartographer as part of your calibration process to improve the quality of your robot's extrinsic calibration.

Multi-trajectories SLAM
=======================

Cartographer can perform SLAM from multiple robots emitting data in parallel.
The global SLAM is able to detect shared paths and will merge the maps built by the different robots as soon as it becomes possible.
This is achieved through the usage of two ROS services ``start_trajectory`` and ``finish_trajectory``. (refer to the ROS API reference documentation for more details on their usage)

Cloud integration with gRPC
===========================

Cartographer is built around Protobuf messages which make it very flexible and interoperable.
One of the advantages of that architecture is that it is easy to distribute on machines spread over the Internet.
The typical use case would be a fleet of robots navigating on a known map, they could have their SLAM algorithm run on a remote powerful centralized localization server running a multi-trajectories Cartographer instance.

**TODO**: Instructions on how to get started with a gRPC Cartographer instance


text:
<?php

namespace backend\models\customer;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use backend\models\customer\DomainRecord;
use yii\db\Query;

/**
 * DomainRecordSearch represents the model behind the search form about `backend\models\customer\DomainRecord`.
 */
class DomainRecordSearch extends DomainRecord
{
    public $customerName;
    public $paymentStatus;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id', 'customer_id', 'domain_choice_value', 'payment_status_value', 'domain_status_value', 'theme_id', 'created_by', 'updated_by', 'payment_method_value'], 'integer'],
            [['name', 'created_at', 'updated_at'], 'safe'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = DomainRecord::find();

        // add conditions that should always apply here

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'customer_id' => $this->customer_id,
            'domain_choice_value' => $this->domain_choice_value,
            'payment_status_value' => $this->payment_status_value,
            'domain_status_value' => $this->domain_status_value,
            'theme_id' => $this->theme_id,
            'created_at' => $this->created_at,
            'created_by' => $this->created_by,
            'updated_at' => $this->updated_at,
            'updated_by' => $this->updated_by,
            'payment_method_value' => $this->payment_method_value,
        ]);

        $query->andFilterWhere(['like', 'name', $this->name]);

        return $dataProvider;
    }

    public function searchDomainsPendingForFirstPayment()
    {
        $query = DomainRecordSearch::find();

        $dataProvider = (new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                    'pageSize' => 10,
                ],
            ]));

        $dataProvider->setSort([
            'attributes' => [
                'id' => [
                    'asc' => ['id' => SORT_ASC],
                    'desc' => ['id' => SORT_DESC],
                    'label' => 'Id'
                ],
                'customer_id' => [
                    'asc' => ['customer_id' => SORT_ASC],
                    'desc' => ['customer_id' => SORT_DESC],
                    'label' => 'Customer Id'
                ],
                'customerName' => [
                    'asc' => ['customer.name' => SORT_ASC],
                    'desc' => ['customer.name' => SORT_DESC],
                    'label' => 'Full Name'
                ],
                'name' => [
                    'asc' => ['domain.name' => SORT_ASC],
                    'desc' => ['domain.name' => SORT_DESC],
                    'label' => 'Domain Name'
                ],
                'domainChoiceOrder' => [
                    'asc' => ['domain.domain_choice_value' => SORT_ASC],
                    'desc' => ['domain.domain_choice_value' => SORT_DESC],
                    'label' => 'Domain domain_choice_value'
                ],
                'paymentStatus' => [
                    'asc' => ['domain.payment_status_value' => SORT_ASC],
                    'desc' => ['domain.payment_status_value' => SORT_DESC],
                    'label' => 'Payment Status'
                ],
            ]
        ]);

        $subQuery = (new Query())->select('name')
                                ->from('payment_status')
                                ->where(['value' => 10]);

        $query->select(['domain.id AS id', 'customer_id', 'customer.name AS customerName', 'domain.name','domain.domain_choice_value' ,'paymentStatus' => $subQuery])
            ->innerjoin('customer', 'domain.customer_id = customer.id')
            ->where(['payment_status_value' => 10])
            ->all();

        //$this->load($params);

        return $dataProvider;
    }

    public function searchMyDomainsForDevelopment($params)
    {
        $query = DomainRecordSearch::find();

        $dataProvider = (new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                    'pageSize' => 10,
                ],
            ]));

        $dataProvider->setSort([
            'attributes' => [
                'id' => [
                    'asc' => ['id' => SORT_ASC],
                    'desc' => ['id' => SORT_DESC],
                    'label' => 'Id'
                ],
                'customer_id' => [
                    'asc' => ['customer_id' => SORT_ASC],
                    'desc' => ['customer_id' => SORT_DESC],
                    'label' => 'Customer Id'
                ],
                'customerName' => [
                    'asc' => ['customer.name' => SORT_ASC],
                    'desc' => ['customer.name' => SORT_DESC],
                    'label' => 'Full Name'
                ],
                'name' => [
                    'asc' => ['domain.name' => SORT_ASC],
                    'desc' => ['domain.name' => SORT_DESC],
                    'label' => 'Domain Name'
                ],
                'paymentStatus' => [
                    'asc' => ['domain.payment_status_value' => SORT_ASC],
                    'desc' => ['domain.payment_status_value' => SORT_DESC],
                    'label' => 'Payment Status'
                ],
            ]
        ]);

        /*$subQuery = (new Query())->select('name')
                                ->from('domain_status')
                                ->where(['value' => 20]);*/

        $query->select(['domain.id AS id', 'customer_id', 'customer.name AS customerName', 'domain.name'])
            ->innerjoin('customer', 'domain.customer_id = customer.id')
            ->where(['domain.created_by' => $params['seller_user_id']])
            ->andWhere(['payment_status_value' => 20])
            ->innerJoin(['ds' => 'domain_status'], 'domain.domain_status_value = ds.value')
            ->where(['ds.name' => 20])
            ->all();

        $this->load($params);

        return $dataProvider;
    }

    public function searchMyPublishedDomains($params)
    {
        $query = DomainRecordSearch::find();

        $dataProvider = (new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                    'pageSize' => 10,
                ],
            ]));

        $dataProvider->setSort([
            'attributes' => [
                'id' => [
                    'asc' => ['domain.id' => SORT_ASC],
                    'desc' => ['domain.id' => SORT_DESC],
                    'label' => 'Domain Id'
                ],
                'name' => [
                    'asc' => ['domain.name' => SORT_ASC],
                    'desc' => ['domain.name' => SORT_DESC],
                    'label' => 'Domain Name'
                ],
                'customerName' => [
                    'asc' => ['customer.name' => SORT_ASC],
                    'desc' => ['customer.name' => SORT_DESC],
                    'label' => 'Full Name'
                ],
                'paymentStatus' => [
                    'asc' => ['domain.payment_status_value' => SORT_ASC],
                    'desc' => ['domain.payment_status_value' => SORT_DESC],
                    'label' => 'Payment Status'
                ],
            ]
        ]);

        $subQuery = (new Query())->select('name')
                                ->from('payment_status')
                                ->where(['value' => 20]);

        $query->select(['domain.id', 'domain.name', 'customer.name AS customerName', 'paymentStatus' => $subQuery])
            ->innerjoin('customer', 'domain.customer_id = customer.id')
            ->where(['domain.created_by' => $params['seller_user_id']])
            ->andWhere(['domain.payment_status_value' => 30])
            ->andwhere(['domain.domain_status_value' => 50])
            ->all();

        $this->load($params);

        return $dataProvider;
    }

    public function searchTemporaryDomains()
    {
        $query = DomainRecordSearch::find();

        $dataProvider = (new ActiveDataProvider([
            'query' => $query,
            'pagination' => [
                    'pageSize' => 10,
                ],
            ]));

        $dataProvider->setSort([
            'attributes' => [
                'id' => [
                    'asc' => ['id' => SORT_ASC],
                    'desc' => ['id' => SORT_DESC],
                    'label' => 'Id'
                ],
                'customer_id' => [
                    'asc' => ['customer_id' => SORT_ASC],
                    'desc' => ['customer_id' => SORT_DESC],
                    'label' => 'Customer Id'
                ],
                'customerName' => [
                    'asc' => ['customer.name' => SORT_ASC],
                    'desc' => ['customer.name' => SORT_DESC],
                    'label' => 'Full Name'
                ],
                'name' => [
                    'asc' => ['domain.name' => SORT_ASC],
                    'desc' => ['domain.name' => SORT_DESC],
                    'label' => 'Domain Name'
                ],
                'paymentStatus' => [
                    'asc' => ['domain.payment_status_value' => SORT_ASC],
                    'desc' => ['domain.payment_status_value' => SORT_DESC],
                    'label' => 'Payment Status'
                ],
            ]
        ]);

        /*$subQuery = (new Query())->select('name')
                                ->from('domain_status')
                                ->where(['value' => 20]);*/

        $query->select(['domain.id AS id', 'customer_id', 'customer.name AS customerName', 'domain.name'])
            ->innerjoin('customer', 'domain.customer_id = customer.id')
            ->where(['payment_status_value' => 20])
            ->andWhere(['domain.domain_status_value' => 20])
            ->all();

        return $dataProvider;
    }
}


text:
package com.jonasgerdes.schauburgr.model;

import android.util.Log;

import com.jonasgerdes.schauburgr.R;
import com.jonasgerdes.schauburgr.model.schauburg.SchauburgDataLoader;
import com.jonasgerdes.schauburgr.model.schauburg.entity.Guide;
import com.jonasgerdes.schauburgr.model.schauburg.entity.Movie;
import com.jonasgerdes.schauburgr.model.schauburg.entity.Screening;
import com.jonasgerdes.schauburgr.model.schauburg.entity.ScreeningDay;
import com.jonasgerdes.schauburgr.model.tmdb.TheMovieDatabaseDataLoader;

import org.joda.time.LocalDate;

import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.BehaviorSubject;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
import retrofit2.HttpException;

/**
 * Repository for easy access to local cache of movies and fetching data from server
 *
 * @author Jonas Gerdes <dev@jonasgerdes.com>
 * @since 26.04.2017
 */

public class MovieRepository implements Disposable {

    private final Realm mRealm;
    private SchauburgDataLoader mSchauburgDataLoader;
    private TheMovieDatabaseDataLoader mTheMovieDatabaseDataLoader;
    private CompositeDisposable mDisposables = new CompositeDisposable();
    private BehaviorSubject<NetworkState> mState
            = BehaviorSubject.createDefault(NetworkState.DEFAULT);

    public MovieRepository(SchauburgDataLoader schauburgDataLoader,
                           TheMovieDatabaseDataLoader theMovieDatabaseDataLoader) {
        mSchauburgDataLoader = schauburgDataLoader;
        mTheMovieDatabaseDataLoader = theMovieDatabaseDataLoader;
        mRealm = Realm.getDefaultInstance();
    }

    /**
     * Gets observable network state. State changes when some network request are triggered
     *
     * @return Observable NetworkState
     */
    public Observable<NetworkState> getNetworkState() {
        return mState.share();
    }

    /**
     * Loads movie and screening data from schauburg and try to get matching movie data via
     * TMDb. Invalidates local cache as soon as data from schauburg is available and saves all data
     * in local cache. Triggers {@link NetworkState} got via {@link #getNetworkState()} accordingly.
     */
    public void loadMovieData() {
        mState.onNext(NetworkState.LOADING);
        mDisposables.add(mSchauburgDataLoader.fetchGuideData()
                .flatMapIterable(Guide::getMovies)
                //ignore operas, since TMDb doesn't list those and may return movies
                //with similar name(s) which leads to confusion
                .filter(movie -> !movie.getGenres().contains(Movie.GENRE_MET_OPERA))
                .concatMap(mTheMovieDatabaseDataLoader::searchAndSaveMovie)
                .ignoreElements()
                .subscribe(() -> mState.onNext(NetworkState.DEFAULT), this::propagateErrorState)
        );
    }

    /**
     * Loads data of relevant videos (like trailers, teasers) for given movie
     *
     * @param movie Movie to load video data for
     */
    public void loadVideos(Movie movie) {
        if (movie.getTmdbId() == Movie.NO_ID || movie.getVideos().size() > 0) {
            return;
        }
        mState.onNext(NetworkState.LOADING);
        mDisposables.add(mTheMovieDatabaseDataLoader.getVideosAndSave(movie)
                .ignoreElements()
                .subscribe(() -> mState.onNext(NetworkState.DEFAULT), this::propagateErrorState)
        );
    }

    /**
     * Propagates error state via {@link #mState} by breaking down given throwable to get an
     * matching error message
     *
     * @param throwable Thrown error
     */
    private void propagateErrorState(Throwable throwable) {
        Log.d("MovieRepository", "Error during network request", throwable);
        NetworkState state = new NetworkState(NetworkState.STATE_ERROR);
        if (throwable instanceof HttpException) {
            HttpException httpError = ((HttpException) throwable);
            state.setHttpStatusCode(httpError.code());
            switch (httpError.code()) {
                case 429:
                    state.setMessage(R.string.network_error_request_limit);
                    break;
                default:
                    state.setMessage(httpError.getMessage());
            }
        } else {
            if (throwable instanceof SocketTimeoutException
                    || throwable instanceof UnknownHostException
                    || throwable instanceof SocketException) {
                state.setMessage(R.string.network_error_no_connection);
            } else {
                state.setMessage(throwable.getClass().getCanonicalName());
            }
        }

        mState.onNext(state);
    }

    /**
     * Gets all locally cached screenings grouped by time and date in {@link ScreeningDay}s
     *
     * @return Cached {@link ScreeningDay}s
     */
    public Observable<RealmResults<ScreeningDay>> getScreeningDays() {
        return RealmObservable.from(mRealm.where(ScreeningDay.class)
                .greaterThanOrEqualTo("date", new LocalDate().toDate())
                .findAllSorted("date", Sort.ASCENDING));
    }

    /**
     * Gets all movies which were released during last 14 days or shows as preview
     * Ordered by release date
     *
     * @return Observable RealmResults of recent released movies
     */
    public Observable<RealmResults<Movie>> getNewMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .greaterThanOrEqualTo("releaseDate", new LocalDate().minusDays(14).toDate())
                .or().contains("extras", Movie.EXTRA_PREVIEW)
                .findAllSorted("releaseDate", Sort.DESCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all movies having comedy as genre and a contentRating of 12+.
     * Ordered by title
     *
     * @return Observable RealmResults of action movies
     */
    public Observable<RealmResults<Movie>> getActionMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .contains("genres", "Action")
                .greaterThanOrEqualTo("contentRating", 12)
                .findAllSorted("title", Sort.ASCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all movies having comedy as genre and aren't movies for kids
     * Ordered by title
     *
     * @return Observable RealmResults of comedy movies
     */
    public Observable<RealmResults<Movie>> getComedyMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .contains("genres", "Komödie")
                //don't include family and animation movies,
                //otherwise (almost) all kids movies end up here
                .not().contains("genres", "Familie")
                .not().contains("genres", "Animation")
                .findAllSorted("title", Sort.ASCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all movies having thriller or horror as genre
     * Ordered by title
     *
     * @return Observable RealmResults of action movies
     */
    public Observable<RealmResults<Movie>> getThrillerMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .contains("genres", "Thriller")
                .or()
                .contains("genres", "Horror")
                .findAllSorted("title", Sort.ASCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all movies fitting for kids (having animation or family as genre
     * and  a contentRating of 0 or 6)
     * Ordered by title
     *
     * @return Observable RealmResults of movies for kids
     */
    public Observable<RealmResults<Movie>> getKidsMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .contains("genres", "Animation")
                .or()
                .contains("genres", "Familie")
                .or()
                .contains("genres", "Family")
                .lessThanOrEqualTo("contentRating", 6)
                .findAllSorted("title", Sort.ASCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all movies having given extra
     * Ordered by title
     *
     * @return Observable RealmResults of matching movies
     */
    public Observable<RealmResults<Movie>> getMoviesWithExtra(String extra) {
        return RealmObservable.from(mRealm.where(Movie.class)
                .contains("extras", extra)
                .findAllSorted("title", Sort.ASCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all movies having a duration of {@link Movie#DURATION_EXCESS_LENGTH_STATE_1} or longer
     * Ordered by duration
     *
     * @return Observable RealmResults of movies with excess length
     */
    public Observable<RealmResults<Movie>> getExcessLengthMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .greaterThanOrEqualTo("duration", Movie.DURATION_EXCESS_LENGTH_STATE_1)
                .not().contains("genres", "Met Opera")
                .findAllSorted("duration", Sort.DESCENDING)
                .where().isNotEmpty("description").distinct("title"));
    }

    /**
     * Gets all "special" movies like Met Opera streamings, movies of "Filmrolle", movies screened
     * with original audio ("O-Ton") or generally got a "Film-Tipp" recommendation.
     * Ordered by title
     *
     * @return Observable RealmResults of "special" movies
     */
    public Observable<RealmResults<Movie>> getSpecialMovies() {
        return RealmObservable.from(mRealm.where(Movie.class)
                .contains("genres", "Met Opera")
                .or()
                .contains("extras", Movie.EXTRA_REEL)
                .or()
                .contains("extras", Movie.EXTRA_TIP)
                .or()
                .contains("extras", Movie.EXTRA_OT)
                .or()
                .contains("title", "Malteser")
                .findAllSorted("releaseDate", Sort.DESCENDING));
    }

    /**
     * Gets all movies which are not in any of the given observables
     *
     * @param exclude List of Observable RealmResults of Movies to exclude
     * @return Observable Movies not contained in parameters
     */
    @SuppressWarnings("unchecked")
    public Observable<RealmResults<Movie>> getRemainingMovies(List<Observable<RealmResults<Movie>>> exclude) {
        return Observable.zip(exclude, objects -> {
            List<String> moviesIds = new ArrayList<>();
            for (Object object : objects) {
                for (Movie movie : (RealmResults<Movie>) object) {
                    moviesIds.add(movie.getResourceId());
                }
            }
            return mRealm.where(Movie.class)
                    .not().in("resourceId", moviesIds.toArray(new String[0]))
                    .findAll();
        });
    }

    /**
     * Gets a movie with given id ({@link Movie#resourceId})
     *
     * @param movieId id of movie
     * @return Movie with given id
     */
    public Observable<Movie> getMovieById(String movieId) {
        return RealmObservable.from(mRealm.where(Movie.class)
                .equalTo("resourceId", movieId)
                .findFirst());
    }

    /**
     * Finds all screenings for given movie and movies which are actually the same by looking at
     * the title of the movie and ignoring different extras like 3D, atmos etc.
     *
     * @param movie Movie to find screenings for
     * @return Observable RealmResult list of screenings for given and similar movies
     */
    public Observable<RealmResults<Screening>> getAllScreeningsFor(Movie movie) {
        return RealmObservable.from(mRealm.where(Screening.class)
                .equalTo("movie.title", movie.getTitle())
                .greaterThan("startDate", new Date())
                .findAllSorted("startDate", Sort.ASCENDING));
    }

    /**
     * Disposes repository by removing all internal listeners and subcribers and closing the db.
     */
    @Override
    public void dispose() {
        mDisposables.dispose();
        mRealm.close();
    }

    /**
     * Checks whether repository is already disposed
     *
     * @return true if repository was already disposed, false otherwise
     */
    @Override
    public boolean isDisposed() {
        return mDisposables.isDisposed();
    }
}


text:
USE [master]
GO

/****** Object:  StoredProcedure [dbo].[SP_INDEX_MAINTENANCE_ENTERPRISE]    Script Date: 18/04/2018 15.52.18 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[SP_INDEX_MAINTENANCE_ENTERPRISE]

AS

DECLARE @RowThreshold INT
DECLARE @PercentThreshold DECIMAL(38,10)

/***********************************************************************************************************************************
*************SET PARAMETERS*********************************************************************************************************/

SET @RowThreshold		= 1000	--Threshold for the number of rows.  In the number of rows in the index is less that the threshold
								--then it will skip it completely.
SET @PercentThreshold	= 50	--FOR THIS SCRIPT 50 = 50%
								--Fragmentation threshold percentage.  If greater than or equal to this amount them REBUILD the Index
								--If less than this amount REORGANIZE the index

/************SET PARAMETERS*********************************************************************************************************
************************************************************************************************************************************/

SET NOCOUNT ON

--INDEXES THAT CAN BE REBUILT ONLINE

DECLARE @tablename SYSNAME;
DECLARE @index_name SYSNAME;
DECLARE @percentfrag DECIMAL(38,10);
DECLARE @command VARCHAR(8000);
DECLARE @command2 VARCHAR(8000);
DECLARE Index_Maint CURSOR FOR

SELECT
o.name,
i.name,
f.avg_fragmentation_in_percent
FROM SYS.DM_DB_INDEX_PHYSICAL_STATS (DB_ID(), NULL, NULL , NULL, 'LIMITED') f
JOIN sys.objects o on o.object_id = f.object_id
JOIN sys.indexes i on i.object_id = f.object_id and i.index_id = f.index_depth
WHERE f.index_id > 0
AND NOT EXISTS (							--eliminate indexes that can not be rebuilt ONLINE
  SELECT 1 FROM sys.index_columns AS ic
  INNER JOIN sys.columns AS c
  ON ic.object_id = c.object_id
  AND ic.column_id = c.column_id
  AND ((c.system_type_id IN (34,35,99,241)) -- image, text, ntext, xml
   OR (c.system_type_id IN (167,231,165) -- varchar, nvarchar, varbinary
       AND max_length = -1))
  WHERE ic.object_id = I.object_id
  AND ic.index_id = I.index_id
)

OPEN Index_Maint

FETCH NEXT FROM Index_Maint INTO
	  @tablename, @index_name, @percentfrag

While @@FETCH_STATUS = 0
BEGIN

	IF @percentfrag >= @PercentThreshold
		BEGIN
			SELECT @command2 = 'ALTER INDEX ' + '[' + @index_name + ']' + ' ON ' + '[' + @tablename + ']' + ' REBUILD WITH(MAXDOP=0, ONLINE=ON)'; --Take advantage of parallelism and ONLINE INDEX REBUILDS
			EXEC (@command2);
			PRINT 'Executed ' + @command2;
		END;
	ELSE
		BEGIN
			SELECT @command = 'ALTER INDEX ' + '[' + @index_name + ']' + ' ON ' + '[' + @tablename + ']' + ' REORGANIZE';
			EXEC (@command);
			PRINT 'Executed ' + @command;
		END;

FETCH NEXT FROM Index_Maint INTO
	  @tablename, @index_name, @percentfrag
END

CLOSE Index_Maint
DEALLOCATE Index_Maint

--INDEXES THAT CANNOT BE REBUILT ONLINE

DECLARE @tablename2 SYSNAME;
DECLARE @index_name2 SYSNAME;
DECLARE @percentfrag2 DECIMAL(38,10);
DECLARE @command3 VARCHAR(8000);
DECLARE @command2b VARCHAR(8000);
DECLARE Index_Maint2 CURSOR FOR

SELECT
o.name,
i.name,
f.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED') f
JOIN sys.objects o on o.object_id = f.object_id
JOIN sys.indexes i on i.object_id = f.object_id and i.index_id = f.index_depth
WHERE f.index_id > 0
AND EXISTS (							--Select only indexes that CANNOT be rebuilt ONLINE
  SELECT 1 FROM sys.index_columns AS ic
  INNER JOIN sys.columns AS c
  ON ic.object_id = c.object_id
  AND ic.column_id = c.column_id
  AND ((c.system_type_id IN (34,35,99,241)) -- image, text, ntext, xml
   OR (c.system_type_id IN (167,231,165) -- varchar, nvarchar, varbinary
       AND max_length = -1))
  WHERE ic.object_id = I.object_id
  AND ic.index_id = I.index_id
)

OPEN Index_Maint2

FETCH NEXT FROM Index_Maint2 INTO
	  @tablename2, @index_name2, @percentfrag2

While @@FETCH_STATUS = 0
BEGIN

	IF @percentfrag2 >= @PercentThreshold
		BEGIN
			SELECT @command2b = 'ALTER INDEX ' + '[' + @index_name2 + ']' + ' ON ' + '[' + @tablename2 + ']' + ' REBUILD WITH(MAXDOP=0)'; --Take advantage of parallelism and ONLINE INDEX REBUILDS
			EXEC (@command2b);
			--PRINT 'Executed ' + @command2b;
		END;
	ELSE
		BEGIN
			SELECT @command3 = 'ALTER INDEX ' + '[' + @index_name2 + ']' + ' ON ' + '[' + @tablename2 + ']' + ' REORGANIZE';
			EXEC (@command3);
			--PRINT 'Executed ' + @command3;
		END;

FETCH NEXT FROM Index_Maint2 INTO
	  @tablename2, @index_name2, @percentfrag2
END

CLOSE Index_Maint2
DEALLOCATE Index_Maint2

GO