FileEntity.java

  1. /*
  2.  * *************************************************************************************************************************************************************
  3.  *
  4.  * SteelBlue: DCI User Interfaces
  5.  * http://tidalwave.it/projects/steelblue
  6.  *
  7.  * Copyright (C) 2015 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *************************************************************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
  12.  * You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * 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
  17.  * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
  18.  *
  19.  * *************************************************************************************************************************************************************
  20.  *
  21.  * git clone https://bitbucket.org/tidalwave/steelblue-src
  22.  * git clone https://github.com/tidalwave-it/steelblue-src
  23.  *
  24.  * *************************************************************************************************************************************************************
  25.  */
  26. package it.tidalwave.role.ui.example.model;

  27. import javax.annotation.Nonnegative;
  28. import javax.annotation.Nonnull;
  29. import javax.annotation.concurrent.Immutable;
  30. import java.time.ZoneId;
  31. import java.time.ZonedDateTime;
  32. import java.util.Collections;
  33. import java.util.Comparator;
  34. import java.util.List;
  35. import java.util.Optional;
  36. import java.io.IOException;
  37. import java.io.UncheckedIOException;
  38. import java.nio.file.Files;
  39. import java.nio.file.Path;
  40. import java.nio.file.attribute.BasicFileAttributeView;
  41. import java.nio.file.attribute.BasicFileAttributes;
  42. import java.nio.file.attribute.FileTime;
  43. import it.tidalwave.util.As;
  44. import it.tidalwave.util.spi.SimpleFinderSupport;
  45. import it.tidalwave.role.SimpleComposite;
  46. import it.tidalwave.role.ui.Displayable;
  47. import lombok.EqualsAndHashCode;
  48. import lombok.RequiredArgsConstructor;
  49. import lombok.ToString;
  50. import lombok.experimental.Delegate;
  51. import lombok.extern.slf4j.Slf4j;
  52. import static java.util.stream.Collectors.*;

  53. /***************************************************************************************************************************************************************
  54.  *
  55.  * A class that models a file with its attributes and children.
  56.  *
  57.  * @author  Fabrizio Giudici
  58.  *
  59.  **************************************************************************************************************************************************************/
  60. @Immutable @EqualsAndHashCode @ToString @Slf4j
  61. public class FileEntity implements As, Displayable
  62.   {
  63.     @RequiredArgsConstructor
  64.     public static class FileEntityFinder extends SimpleFinderSupport<FileEntity>
  65.       {
  66.         private static final long serialVersionUID = 5780394869213L;

  67.         @Nonnull
  68.         private final Path path;

  69.         public FileEntityFinder (@Nonnull final FileEntityFinder other, @Nonnull final Object override)
  70.           {
  71.             super(other, override);
  72.             final var source = getSource(FileEntityFinder.class, other, override);
  73.             this.path = source.path;
  74.           }

  75.         @Nonnull @Override
  76.         protected List<FileEntity> computeNeededResults()
  77.           {
  78.             try (final var stream = Files.list(path))
  79.               {
  80.                 return stream.sorted(Comparator.comparing(Path::toString)).map(FileEntity::of).collect(toList());
  81.               }
  82.             catch (IOException e)
  83.               {
  84.                 log.error("While listing directory " + path, e);
  85.                 throw new UncheckedIOException(e);
  86.               }
  87.           }
  88.       }

  89.     /** The path of the file.*/
  90.     @Nonnull
  91.     private final Path path;

  92.     /** Support object for implementing {@link As} functions.*/
  93.     @Delegate
  94.     private final As delegate;

  95.     /***********************************************************************************************************************************************************
  96.      * Creates a new instance related to the given path.
  97.      *
  98.      * @param   path    the path
  99.      **********************************************************************************************************************************************************/
  100.     // START SNIPPET: constructor
  101.     private FileEntity (@Nonnull final Path path)
  102.       {
  103.         this.path = path;
  104.         delegate = As.forObject(this, Files.isDirectory(path)
  105.                                                 ? List.of(SimpleComposite.of(new FileEntityFinder(path)))
  106.                                                 : Collections.emptyList());
  107.       }
  108.     // END SNIPPET: constructor

  109.     /***********************************************************************************************************************************************************
  110.      * {@return a new instance} related to the given path.
  111.      * @param   path    the path
  112.      **********************************************************************************************************************************************************/
  113.     // START SNIPPET: constructor
  114.     @Nonnull
  115.     public static FileEntity of (@Nonnull final Path path)
  116.       {
  117.         return new FileEntity(path);
  118.       }

  119.     /***********************************************************************************************************************************************************
  120.      * {@return the display name}. It's a static implementation of the {@link Displayable} role.
  121.      **********************************************************************************************************************************************************/
  122.     // START SNIPPET: constructor
  123.     @Override @Nonnull
  124.     public String getDisplayName()
  125.       {
  126.         return Optional.ofNullable(path.getFileName()).map(Path::toString).orElse("/");
  127.       }

  128.     /***********************************************************************************************************************************************************
  129.      * {@return the creation date-time} of the file.
  130.      * @throws  IOException if the file does not exist or cannot be accessed
  131.      **********************************************************************************************************************************************************/
  132.     @Nonnull
  133.     public ZonedDateTime getCreationDateTime()
  134.             throws IOException
  135.       {
  136.         return toZoneDateTime(getBasicFileAttributes().creationTime());
  137.       }

  138.     /***********************************************************************************************************************************************************
  139.      * {@return the last access date-time} of the file.
  140.      * @throws  IOException if the file does not exist or cannot be accessed
  141.      **********************************************************************************************************************************************************/
  142.     @Nonnull
  143.     public ZonedDateTime getLastAccessDateTime()
  144.             throws IOException
  145.       {
  146.         return toZoneDateTime(getBasicFileAttributes().lastAccessTime());
  147.       }

  148.     /***********************************************************************************************************************************************************
  149.      * {@return the last modified date-time} of the file.
  150.      * @throws  IOException if the file does not exist or cannot be accessed
  151.      **********************************************************************************************************************************************************/
  152.     @Nonnull
  153.     public ZonedDateTime getLastModifiedDateTime()
  154.             throws IOException
  155.       {
  156.         return toZoneDateTime(getBasicFileAttributes().lastModifiedTime());
  157.       }

  158.     /***********************************************************************************************************************************************************
  159.      * {@return the size} of the file.
  160.      * @throws  IOException if the file does not exist or cannot be accessed
  161.      **********************************************************************************************************************************************************/
  162.     @Nonnegative
  163.     public long getSize()
  164.             throws IOException
  165.       {
  166.         return Files.size(path);
  167.       }

  168.     /***********************************************************************************************************************************************************
  169.      * {@return the basic attributes} of the file.
  170.      * @throws  IOException if the file does not exist or cannot be accessed
  171.      **********************************************************************************************************************************************************/
  172.     @Nonnull
  173.     private BasicFileAttributes getBasicFileAttributes()
  174.             throws IOException
  175.       {
  176.         return Files.getFileAttributeView(path, BasicFileAttributeView.class).readAttributes();
  177.       }

  178.     /***********************************************************************************************************************************************************
  179.      *
  180.      **********************************************************************************************************************************************************/
  181.     @Nonnull
  182.     private static ZonedDateTime toZoneDateTime (@Nonnull final FileTime dateTime)
  183.       {
  184.         return ZonedDateTime.ofInstant(dateTime.toInstant(), ZoneId.systemDefault());
  185.       }
  186.   }