Last modified 13 years ago Last modified on 11/13/09 20:23:24

Error: Macro BackLinksMenu(None) failed
compressed data is corrupt

Error: Macro TicketQuery(summary=NFR_LARGE_RESOURCES_R0, format=table, col=summary|owner|status|type|component|priority|effort|importance, rows=description|analysis_owners|analysis_reviewers|analysis_score|design_owners|design_reviewers|design_score|implementation_owners|implementation_reviewers|implementation_score|test_owners|test_reviewers|test_score|) failed
current transaction is aborted, commands ignored until end of transaction block


(Give as much as possible of the needed information for designing and implementing the task in the following sections.)


Sophie needs to work with large resources some of which bigger than 50MB. There is problems loading large video and audio file so we need to change the loading of resources with big data.

Task requirements

  • Created a special way for linking a file in Sophie. The file should be accessed in parts.
  • When the user opens big files for binary resource ask the user if he/she wants to link the file or automatically link the file if it is too large.
    • If the file is smaller than 4 MB automatically embed it.
    • If the file is between 4 MB and 16 MB ask the user if he/she wants to link or embed it.
    • If the file is bigger than 16 MB automatically link it.
  • Create special dialog for user interaction for large files or modify the file dialog if possible.
  • Create a way for linking every type of URL (optional, hard because there could be no API that can do that).
  • Ask the user if he/she wants to copy the file in special directory that can be transferred with the book. (optional, hard due to relative paths).
    • That will work only with files saved on the file system.
  • Think of working with large resources on the server (optional, that is different task, but if there is time there could be done something).

Task result

The result of this task will be source code.

Implementation idea

  • Make the current BinData abstract class that has two extenders:
    • EmbeddedBinData (working as the current one)
    • FileBinData (linking files).
  • Make the FileBinData#getSub method to read from it's file with random access.
    • First it will seek to the wanted position in the file.
    • Then it will return a new BinData containing only the bytes from the passed position with length, the passed one.


How to demo

  • Run Sophie.
    • In the insert menu click on "insert video..."
    • Insert big video file (40-50MB or bigger).
    • Try to play it. It should play if the format is supported.
  • Run Sophie.
    • In the insert menu click on "insert video..."
    • Insert average video (between 4 MB and 16 MB)
    • You should be asked if you want to link or embed the video.
    • Try to play the video. It should play if the format is supported.


  • BinData hierarchy:
    • Move all the BinData related classes to the package : org.sophie2.base.commons.util.bindata
    • BinData : Make BinData abstract class that will have a number of child classes. BinData has the following methods:
      • public abstract int getSize() -> Gets the size (in bytes) of this bin data.
      • public abstract byte[] getBytes() throws BinSourceNotFoundException -> Gets all the bytes of the BinData and if that is not possible throws the unchecked exception BinSourceNotFoundException.
      • public BinData getSub(int begin, int end) -> Gets BinData that holds access to a given range in the byte array source, of the BinData. By default it returns new SubBinData for the range.
      • public byte[] getBytes(int begin, int end) throws BinSourceNotFoundException -> Gets the bytes of the bin data from the 'begin' position to the 'end' position. The default implementation will allocate an array of bytes with the wanted size to be used by the implementations and will assert that the passed parameters are accurate. If the bytes can not by retrieved from the source the unchecked BinSourceNotFoundException is thrown.
      • public static void transport(InputStream from, OutputStream to) throws IOException -> A helper method for transporting bytes from one stream to another, its implementation is from the old BinData (now RawBinData).
      • Other helper methods should be put here if they are not used only by the old BinData (now RawBinData).
    • RawBinData : Represents embedded BinData, it's source byte array is in the memory. That is the old BinData.
      • It's immutable kind is changed to @Immutable(kind = "raw-bin-data")
      • The implementations of the BinData abstract methods are as they were before this task. The others use the default implementations to allocate byte array only, the unchecked BinSourceNotFoundException is not thrown anywhere, because the source is in the memory.
    • SubBinData : Used to work with parts of the byte array source of the BinData implementations.
      • It's constructor is private and factory methods are with package visibility, only BinData implementations can instantiate it.
      • It keeps as source the BinData that it subs...
      • Getting bytes from it just calls the public byte[] getBytes(int begin, int end) method of its source BinData with it's range.
      • Its public BinData getSub(int begin, int end) method calls the default implementation with given offset.
    • FileBinData : Used as linked to a local file (relative or absolute to a resource) BinData.
      • When bytes are demanded from it, it opens RandomFileAccess to its source file and seeks and reads from it.
      • The public abstract int getSize() method returns the size of the file in bytes.
      • When its source file is not found the unchecked exception BinSourceNotFoundException is thrown. The coders that use that BinData should handle the exception.
    • RemoteBinData (optional for that revision) : Communicates with a remote file source through the Facade.
      • It's methods use the Facade to retrieve their byte arrays and data.
      • On the server side there is RawBinData or FileBinData that provides the bytes or data demanded.
      • When the server is down, or the file on the server can not be retrieved the unchecked BinSourceNotFoundException is thrown.
    • BinSourceNotFoundException -> Thrown from the BinData implementations when their source could not be found. For example the FileBinData file source, or the RemoteBinData remote file source...
    • Some ideas for future revisions:
      • May be UploadBinData is needed for uploading big binary data.
      • May be StreamingBinData can be used as alternative to the RemoteBinData, it will not use the Facade but remote streaming service.
  • Media persistence:
    • Alter the current persist method of the MediaResourceR4#KEY_DATA key.
      • It should work with BinData, not only RawBinData
      • The logic if the BinData is RawBinData stays as it is.
      • With the src attribute, save and dataType to the storage.
        • BinDataPersistType is enumeration that defines what is the type of the BinData to be Types:
          • EMBEDDED -> used for RawBinData
          • LINKED_ABSOLUTE -> used for FileBinData with source file that has absolute path.
          • LINKED_RELATIVE -> used for FIleBinData with source, that has relative to the main resource file path.
          • REMOTE (optional) -> used for RemoteBinData.
        • The helper method public static BinDataPersistType getPersistType(BinData data) is used to get the dataType from a BinData instance.
        • The SubBinData should be used only for operating over parts of other BinDatas, so it should be not persistable.
        • An EnumPersister is registered for that enumeration.
    • When saving if type of the data is LINKED_ABSOLUTE, LINKED_RELATIVE or REMOTE as 'src' attribute just set the path to the file.
      • If the type is remote add child/attribute 'server account' and save the account to its server. (optional)
    • When loading:
      • if the type is null (for old books) or EMBEDDED work with the logic as it is now.
      • If the type is LINKED_ABSOLUTE create a FileBinData with File for the path in the 'src' attribute.
      • If the type is LINKED_RELATIVE, get the path to the resource file it is relative from the PersistenceOptions. It is store when loading in the constant PersistenceUtil.LOCATION. That make FileBinData with file the File for the path stored in the 'src'attribute and parent the path to the resource file.
      • If it's remote make RemoteBinData with the path to the file stored in the 'src' attribute (optional).
    • User inteface:
      • As in the analysis when importing media resources ask the user or link or embed the media.
        • The FileDialog's JFileChooser should be modified to have combo box with options how to import the binary data.
          • JFileChooser can have an accessory component used for additional information when choosing files.
          • Modify the FileDialogInput to have accessory logic.
            • Make two inner classes in the FileDialogInput:
              • FileAccessory, baseProObject, has two abstract methods:
                • A property with a JComponent.
                • getData method, returning AccessoryData.
                • It can have access to a jFileChooser to track the selected files, so it has property containing JFileChooser.
              • AccessoryData, holds data provided by a FileAccessory, immutable, has only one method getData
            • The two classes are generic for their data.
            • FileDialogInput can be constructed with an FileAccessory, it can be null if no accessory is needed.
            • FileDialog sets its JFileChooser accessory to the swing component of the one in the input if it is not null.
            • When constructing the FileContainer as a result of showing FileDialog, it can be constructed with AccessoryData, which can be null.
            • The FileContainer has method getAccessoryData with one parameter the generic type of the data.
            • Add new FileAccessory, BinDataChooser in the main.funk.resources module.
              • It has JLabels with information for the user.
              • It has combo bx with choices for embed and link (can be with radio buttons if dido wants :))
              • It has check box for copying to the '_files' directory.
            • Add new AccessoryData in the same module, its generic type is ImportBinDataType.
            • Add enumeration ImportBinDataType in the same module with three choices EMBED, LINK, COPY_AND_LINK. I don't think it is redundant, because the BinDataPersistType another purpose and contains types for remote datas.
            • When importing media resources between 4 and 16 MB pass the new accessory as accessory to the file dialog.
              • That is easy, modify the ImportManagers of the media resources to pass the accessory.
        • The choices are used this way:
          • Embed -> makes a RawBinData for the resource (as how it is now)
          • Link -> makes a FileBinData to a file with an absolute path on the file system.
          • Link and copy to _files (only for stored books) -> copies the file in a folder '_files' in the same folder as the stored book. Creates a FileBinData to a relative File in that folder, the File is relative to the book file (./_files/myMedia.dat for example).
        • For the server resources for now the bin data will be always RawBinData, saving a book on server will loose the big resources for now (BinSourceNotFoundException will be handled when these resources are used)... Uploading large data is not for this revision.
  • Other notes:
    • The media logics and resources work with BinData.
    • The Image resource and logics work with RawBinData (for now).
    • The new FileBinData works only for the media (for now).
  • Test
  • Branch in the track browser:


  • Additional stuff:
    • Added special content view for errors in media that can refresh the state of the media.
    • Added special ResourceFilesUtil for seving relative to a resource files in its own directory, many string related methods, pfff...
    • Added MediaPersistenceTest, the task is only for the media resources now, but in the future this kind of persistence will be available for all kinds of resources.
    • The import dialog from the resources palette at this point will not be able to link resources.
    • Insert audio and video can link resources.
    • The import managers are aware of the parent resource and an additional data when retrieving resource data, can be done for DND in the future...
    • The BinDataChooser can be buggy, but I'm too tired... I tested it one whole day...
  • Branch:


(Place the testing results here.)


(Write comments for this or later revisions here.)