View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.commons.geometry.examples.io.threed;
    18
    19  import java.io.File;
    20  import java.io.InputStream;
    21  import java.io.OutputStream;
    22  import java.util.ArrayList;
    23  import java.util.Collections;
    24  import java.util.List;
    25
    26  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
    27  import org.apache.commons.geometry.euclidean.threed.BoundarySource3D;
    28
    29  /** Object that holds an internal registry {@link ModelIOHandler} and delegates
    30   * read/write operations to them as determined by their supported model types.
    31   *
    32   * <p>Instances of this class are thread-safe as long as all registered handlers are
    33   * also thread-safe.</p>
    34   */
    35  public class ModelIOHandlerRegistry implements ModelIOHandler {
    36
    37      /** Handler list. */
    38      private final List<ModelIOHandler> handlers = new ArrayList<>();
    39
    40      /** Get the {@link ModelIOHandler} for the given type or null if no
    41       * handler is found.
    42       * @param type model type to retrieve the handler for
    43       * @return the handler for the given type or null if no handler is found
    44       */
    45      public ModelIOHandler getHandlerForType(final String type) {
    46          synchronized (handlers) {
    47              for (final ModelIOHandler handler : handlers) {
    48                  if (handler.handlesType(type)) {
    49                      return handler;
    50                  }
    51              }
    52
    53              return null;
    54          }
    55      }
    56
    57      /** Get the list of registered {@link ModelIOHandler}s.
    58       * @return the registered {@link ModelIOHandler}s
    59       */
    60      public List<ModelIOHandler> getHandlers() {
    61          synchronized (handlers) {
    62              return Collections.unmodifiableList(new ArrayList<>(handlers));
    63          }
    64      }
    65
    66      /** Set the list of registered {@link ModelIOHandler}s.
    67       * @param newHandlers the new list of {@link ModelIOHandler}s.
    68       */
    69      public void setHandlers(final List<ModelIOHandler> newHandlers) {
    70          synchronized (handlers) {
    71              handlers.clear();
    72
    73              if (newHandlers != null) {
    74                  handlers.addAll(newHandlers);
    75              }
    76          }
    77      }
    78
    79      /** {@inheritDoc} */
    80      @Override
    81      public boolean handlesType(final String type) {
    82          return getHandlerForType(type) != null;
    83      }
    84
    85      /** Read a 3D model from the given file, using the file extension as the model type.
    86       * @param in file to read from
    87       * @param precision precision context to use in model construction
    88       * @return a 3D model represented as a boundary source
    89       * @throws java.io.UncheckedIOException if an IO operation fails
    90       * @throws IllegalArgumentException if the file does not have a file extension or the
    91       *      file extension does not indicate a supported model type
    92       */
    93      public BoundarySource3D read(final File in, final DoublePrecisionContext precision) {
    94          return read(getFileExtension(in), in, precision);
    95      }
    96
    97      /** {@inheritDoc} */
    98      @Override
    99      public BoundarySource3D read(final String type, final File in, final DoublePrecisionContext precision) {
    100         return requireHandlerForType(type).read(type, in, precision);
    101     }
    102
    103     /** {@inheritDoc} */
    104     @Override
    105     public BoundarySource3D read(final String type, final InputStream in, final DoublePrecisionContext precision) {
    106         return requireHandlerForType(type).read(type, in, precision);
    107     }
    108
    109     /** Write the model to the file. The file type is determined by the file extension
    110      * of the target file.
    111      * @param model model to write
    112      * @param out output file
    113      * @throws java.io.UncheckedIOException if an IO operation fails
    114      * @throws IllegalArgumentException if the file does not have a file extension or the
    115      *      file extension does not indicate a supported model type
    116      */
    117     public void write(final BoundarySource3D model, final File out) {
    118         write(model, getFileExtension(out), out);
    119     }
    120
    121     /** {@inheritDoc} */
    122     @Override
    123     public void write(final BoundarySource3D model, final String type, final File out) {
    124         requireHandlerForType(type).write(model, type, out);
    125     }
    126
    127     /** {@inheritDoc} */
    128     @Override
    129     public void write(final BoundarySource3D model, final String type, final OutputStream out) {
    130         requireHandlerForType(type).write(model, type, out);
    131     }
    132
    133     /** Get the file extension of the given file, throwing an exception if one cannot be found.
    134      * @param file the file to get the extension for
    135      * @return the file extension
    136      * @throws IllegalArgumentException if the file does not have a file extension
    137      */
    138     private String getFileExtension(final File file) {
    139         final String name = file.getName();
    140         final int idx = name.lastIndexOf('.');
    141         if (idx > -1) {
    142             return name.substring(idx + 1).toLowerCase();
    143         }
    144
    145         throw new IllegalArgumentException("Cannot determine target file type: \"" + file +
    146                 "\" does not have a file extension");
    147     }
    148
    149     /** Get the handler for the given type, throwing an exception if not found.
    150      * @param type model type
    151      * @return the handler for the given type
    152      * @throws IllegalArgumentException if no handler for the type is found
    153      */
    154     private ModelIOHandler requireHandlerForType(final String type) {
    155         final ModelIOHandler handler = getHandlerForType(type);
    156         if (handler == null) {
    157             throw new IllegalArgumentException("No handler found for type \"" + type + "\"");
    158         }
    159
    160         return handler;
    161     }
    162 }