Search in sources :

Example 1 with UnconvertibleObjectException

use of org.apache.sis.util.UnconvertibleObjectException in project sis by apache.

the class RangeFormat method parse.

/**
 * Parses text from the given string to produce a range. This method use the full string.
 * If there is some unparsed characters after the parsed range, then this method thrown an
 * exception.
 *
 * @param  source  the text to parse.
 * @return the parsed range (never {@code null}).
 * @throws ParseException if the given string can not be fully parsed.
 */
public Range<?> parse(final String source) throws ParseException {
    final ParsePosition pos = new ParsePosition(0);
    UnconvertibleObjectException failure = null;
    try {
        final Range<?> range = tryParse(source, pos);
        if (range != null) {
            return range;
        }
    } catch (UnconvertibleObjectException e) {
        failure = e;
    }
    throw new LocalizedParseException(locale, elementType, source, pos).initCause(failure);
}
Also used : UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) LocalizedParseException(org.apache.sis.internal.util.LocalizedParseException) ParsePosition(java.text.ParsePosition)

Example 2 with UnconvertibleObjectException

use of org.apache.sis.util.UnconvertibleObjectException in project sis by apache.

the class PropertyAccessor method convert.

/**
 * Converts values in the specified array to the given type.
 * The array content is modified in-place. This method accepts an array instead than
 * a single value because the values to convert may be the content of a collection.
 *
 * @param  elements    the array which contains element to convert.
 * @param  targetType  the base type of target elements.
 * @throws ClassCastException if an element can't be converted.
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
private void convert(final Object[] elements, final Class<?> targetType) throws ClassCastException {
    boolean hasNewConverter = false;
    ObjectConverter<?, ?> converter = null;
    for (int i = 0; i < elements.length; i++) {
        final Object value = elements[i];
        if (value != null) {
            final Class<?> sourceType = value.getClass();
            if (!targetType.isAssignableFrom(sourceType))
                try {
                    if (converter == null) {
                        // Volatile field - read only if needed.
                        converter = lastConverter;
                    }
                    /*
                     * Require the exact same classes, not parent or subclass,
                     * otherwise the converter could be stricter than necessary.
                     */
                    if (converter == null || converter.getSourceClass() != sourceType || converter.getTargetClass() != targetType) {
                        converter = ObjectConverters.find(sourceType, targetType);
                        hasNewConverter = true;
                    }
                    elements[i] = ((ObjectConverter) converter).apply(value);
                } catch (UnconvertibleObjectException cause) {
                    throw (ClassCastException) new ClassCastException(Errors.format(Errors.Keys.IllegalClass_2, targetType, sourceType)).initCause(cause);
                }
        }
    }
    if (hasNewConverter) {
        // Volatile field - store only if needed.
        lastConverter = converter;
    }
}
Also used : UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) ObjectConverter(org.apache.sis.util.ObjectConverter) IdentifiedObject(org.apache.sis.xml.IdentifiedObject)

Example 3 with UnconvertibleObjectException

use of org.apache.sis.util.UnconvertibleObjectException in project sis by apache.

the class UnitDimensionTest method testRationalPower.

/**
 * Tests a dimension with rational power. This tests use the specific detectivity, which dimension is T^2.5 / (M⋅L).
 */
@Test
@DependsOnMethod({ "testMultiply", "testDivide", "testPow", "testRoot" })
public void testRationalPower() {
    final Dimension dim = specificDetectivity();
    final Map<Dimension, Fraction> expected = new HashMap<>(4);
    assertNull(expected.put(TIME, new Fraction(5, 2)));
    assertNull(expected.put(MASS, new Fraction(-1, 1)));
    assertNull(expected.put(LENGTH, new Fraction(-1, 1)));
    assertMapEquals(expected, ((UnitDimension) dim).components);
    try {
        dim.getBaseDimensions().toString();
        fail("Mapping from Fraction to Integer should not be allowed.");
    } catch (UnconvertibleObjectException e) {
        final String message = e.getMessage();
        assertTrue(message, message.contains("Integer"));
    }
// 'toString()' formatting tested in UnitFormatTest.testRationalPower().
}
Also used : UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) HashMap(java.util.HashMap) Fraction(org.apache.sis.math.Fraction) Dimension(javax.measure.Dimension) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 4 with UnconvertibleObjectException

use of org.apache.sis.util.UnconvertibleObjectException in project sis by apache.

the class StorageConnector method getStorageAs.

/**
 * Returns the storage as a view of the given type if possible, or {@code null} otherwise.
 * The default implementation accepts the following types:
 *
 * <ul>
 *   <li>{@link String}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object is an instance of the {@link java.nio.file.Path},
 *           {@link java.io.File}, {@link java.net.URL}, {@link java.net.URI} or {@link CharSequence} types,
 *           returns the string representation of their path.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link java.nio.file.Path}, {@link java.net.URI}, {@link java.net.URL}, {@link java.io.File}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object is an instance of the {@link java.nio.file.Path},
 *           {@link java.io.File}, {@link java.net.URL}, {@link java.net.URI} or {@link CharSequence} types and
 *           that type can be converted to the requested type, returned the conversion result.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link ByteBuffer}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object can be obtained as described in bullet 2 of the
 *           {@code DataInput} section below, then this method returns the associated byte buffer.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link DataInput}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object is already an instance of {@code DataInput}
 *           (including the {@link ImageInputStream} and {@link javax.imageio.stream.ImageOutputStream} types),
 *           then it is returned unchanged.</li>
 *
 *       <li>Otherwise if the input is an instance of {@link java.nio.file.Path}, {@link java.io.File},
 *           {@link java.net.URI}, {@link java.net.URL}, {@link CharSequence}, {@link InputStream} or
 *           {@link java.nio.channels.ReadableByteChannel}, then an {@link ImageInputStream} backed by a
 *           {@link ByteBuffer} is created when first needed and returned.</li>
 *
 *       <li>Otherwise if {@link ImageIO#createImageInputStream(Object)} returns a non-null value,
 *           then this value is cached and returned.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link ImageInputStream}:
 *     <ul>
 *       <li>If the above {@code DataInput} can be created and casted to {@code ImageInputStream}, returns it.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link InputStream}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object is already an instance of {@link InputStream},
 *           then it is returned unchanged.</li>
 *
 *       <li>Otherwise if the above {@code ImageInputStream} can be created,
 *           returns a wrapper around that stream.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link Reader}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object is already an instance of {@link Reader},
 *           then it is returned unchanged.</li>
 *
 *       <li>Otherwise if the above {@code InputStream} can be created, returns an {@link InputStreamReader}
 *           using the encoding specified by {@link OptionKey#ENCODING} if any, or using the system default
 *           encoding otherwise.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>{@link Connection}:
 *     <ul>
 *       <li>If the {@linkplain #getStorage() storage} object is already an instance of {@link Connection},
 *           then it is returned unchanged.</li>
 *
 *       <li>Otherwise if the storage is an instance of {@link DataSource}, then a connection is obtained
 *           when first needed and returned.</li>
 *
 *       <li>Otherwise this method returns {@code null}.</li>
 *     </ul>
 *   </li>
 *   <li>Any other types:
 *     <ul>
 *       <li>If the storage given at construction time is already an instance of the requested type,
 *           returns it <i>as-is</i>.</li>
 *
 *       <li>Otherwise this method throws {@link IllegalArgumentException}.</li>
 *     </ul>
 *   </li>
 * </ul>
 *
 * Multiple invocations of this method on the same {@code StorageConnector} instance will try
 * to return the same instance on a <cite>best effort</cite> basis. Consequently, implementations of
 * {@link DataStoreProvider#probeContent(StorageConnector)} methods shall not close the stream or
 * database connection returned by this method. In addition, those {@code probeContent(StorageConnector)}
 * methods are responsible for restoring the stream or byte buffer to its original position on return.
 *
 * @param  <T>   the compile-time type of the {@code type} argument.
 * @param  type  the desired type as one of {@code ByteBuffer}, {@code DataInput}, {@code Connection}
 *               class or other type supported by {@code StorageConnector} subclasses.
 * @return the storage as a view of the given type, or {@code null} if no view can be created for the given type.
 * @throws IllegalArgumentException if the given {@code type} argument is not a supported type.
 * @throws DataStoreException if an error occurred while opening a stream or database connection.
 *
 * @see #getStorage()
 * @see #closeAllExcept(Object)
 */
public <T> T getStorageAs(final Class<T> type) throws IllegalArgumentException, DataStoreException {
    ArgumentChecks.ensureNonNull("type", type);
    /*
         * Verify if the cache contains an instance created by a previous invocation of this method.
         * Note that InputStream may need to be reseted if it has been used indirectly by other kind
         * of stream (for example a java.io.Reader). Example:
         *
         *    1) The storage specified at construction time is a java.nio.file.Path.
         *    2) getStorageAs(InputStream.class) opens an InputStream. Caller rewinds it after use.
         *    3) getStorageAs(Reader.class) wraps the InputStream. Caller rewinds the Reader after use,
         *       but invoking BufferedReader.reset() has no effect on the underlying InputStream.
         *    4) getStorageAs(InputStream.class) needs to rewind the InputStream itself since it was
         *       not done at step 3. However doing so invalidate the Reader, so we need to discard it.
         */
    Coupled value = getView(type);
    if (reset(value)) {
        // null is a valid result.
        return type.cast(value.view);
    }
    /*
         * If the storage is already an instance of the requested type, returns the storage as-is.
         * We check if the storage needs to be reseted in the same way than in getStorage() method.
         * As a special case, we ensure that InputStream and Reader can be marked.
         */
    if (type.isInstance(storage)) {
        @SuppressWarnings("unchecked") T view = (T) storage;
        reset();
        byte cascade = 0;
        if (type == InputStream.class) {
            final InputStream in = (InputStream) view;
            if (!in.markSupported()) {
                view = type.cast(new BufferedInputStream(in));
                cascade = (byte) (CLEAR_ON_RESET | CASCADE_ON_RESET);
            }
        } else if (type == Reader.class) {
            final Reader in = (Reader) view;
            if (!in.markSupported()) {
                view = type.cast(new LineNumberReader(in));
                cascade = (byte) (CLEAR_ON_RESET | CASCADE_ON_RESET);
            }
        }
        addView(type, view, null, cascade);
        return view;
    }
    /*
         * If the type is not one of the types listed in OPENERS, we delegate to ObjectConverter.
         * It may throw UnconvertibleObjectException (an IllegalArgumentException subtype) if the
         * given type is unrecognized. So the IllegalArgumentException documented in method javadoc
         * happen (indirectly) here.
         */
    final Opener<?> method = OPENERS.get(type);
    if (method == null) {
        T view;
        try {
            view = ObjectConverters.convert(storage, type);
        } catch (UnconvertibleObjectException e) {
            if (!OPENERS.containsKey(type))
                throw e;
            Logging.recoverableException(Logging.getLogger(Modules.STORAGE), StorageConnector.class, "getStorageAs", e);
            view = null;
        }
        addView(type, view);
        return view;
    }
    /*
         * No instance has been created previously for the requested type. Open the stream now.
         * Some types will need to reset the InputStream or Channel, but the decision of doing
         * so or not is left to openers. Result will be cached by the 'createFoo()' method.
         * Note that it may cache 'null' value if no stream of the given type can be created.
         */
    final Object view;
    try {
        view = method.open(this);
    } catch (DataStoreException e) {
        throw e;
    } catch (Exception e) {
        throw new DataStoreException(Errors.format(Errors.Keys.CanNotOpen_1, getStorageName()), e);
    }
    return type.cast(view);
}
Also used : BufferedInputStream(java.io.BufferedInputStream) ChannelImageInputStream(org.apache.sis.internal.storage.io.ChannelImageInputStream) ImageInputStream(javax.imageio.stream.ImageInputStream) InputStream(java.io.InputStream) RewindableLineReader(org.apache.sis.internal.storage.io.RewindableLineReader) LineNumberReader(java.io.LineNumberReader) Reader(java.io.Reader) InputStreamReader(java.io.InputStreamReader) SQLException(java.sql.SQLException) InvalidSeekException(org.apache.sis.io.InvalidSeekException) IOException(java.io.IOException) UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) LineNumberReader(java.io.LineNumberReader) UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) BufferedInputStream(java.io.BufferedInputStream)

Example 5 with UnconvertibleObjectException

use of org.apache.sis.util.UnconvertibleObjectException in project sis by apache.

the class MetadataSource method readColumn.

/**
 * Invoked by {@link MetadataProxy} for fetching an attribute value from a table.
 *
 * @param  info      the interface type (together with cached information).
 *                   This is mapped to the table name in the database.
 * @param  method    the method invoked. This is mapped to the column name in the database.
 * @param  toSearch  contains the identifier and preferred index of the record to search.
 * @return the value of the requested attribute.
 * @throws SQLException if the SQL query failed.
 * @throws MetadataStoreException if a value was not found or can not be converted to the expected type.
 */
final Object readColumn(final LookupInfo info, final Method method, final Dispatcher toSearch) throws SQLException, MetadataStoreException {
    /*
         * If the identifier is prefixed with a table name as in "{CI_Organisation}identifier",
         * the name between bracket is a subtype of the given 'type' argument.
         */
    final Class<?> type = subType(info.getMetadataType(), toSearch.identifier);
    final Class<?> returnType = Interim.getReturnType(method);
    final boolean wantCollection = Collection.class.isAssignableFrom(returnType);
    final Class<?> elementType = wantCollection ? Classes.boundOfParameterizedProperty(method) : returnType;
    final boolean isMetadata = standard.isMetadata(elementType);
    final String tableName = getTableName(type);
    final String columnName = info.asNameMap(standard).get(method.getName());
    final boolean isArray;
    Object value;
    synchronized (this) {
        if (!getExistingColumns(tableName).contains(columnName)) {
            value = null;
            isArray = false;
        } else {
            /*
                 * Prepares the statement and executes the SQL query in this synchronized block.
                 * Note that the usage of 'result' must stay inside this synchronized block
                 * because we can not assume that JDBC connections are thread-safe.
                 */
            CachedStatement result = take(type, Byte.toUnsignedInt(toSearch.preferredIndex));
            if (result == null) {
                final SQLBuilder helper = helper();
                final String query = helper.clear().append("SELECT * FROM ").appendIdentifier(schema, tableName).append(" WHERE ").append(ID_COLUMN).append("=?").toString();
                result = new CachedStatement(type, connection().prepareStatement(query), listeners);
            }
            value = result.getValue(toSearch.identifier, columnName);
            isArray = (value instanceof java.sql.Array);
            if (isArray) {
                final java.sql.Array array = (java.sql.Array) value;
                value = array.getArray();
                array.free();
            }
            toSearch.preferredIndex = (byte) recycle(result, Byte.toUnsignedInt(toSearch.preferredIndex));
        }
    }
    /*
         * If the value is an array and the return type is anything except an array of primitive type, ensure
         * that the value is converted in an array of type Object[]. In this process, resolve foreigner keys.
         */
    if (isArray && (wantCollection || !elementType.isPrimitive())) {
        final Object[] values = new Object[Array.getLength(value)];
        for (int i = 0; i < values.length; i++) {
            Object element = Array.get(value, i);
            if (element != null) {
                if (isMetadata) {
                    element = lookup(elementType, element.toString());
                } else
                    try {
                        element = info.convert(elementType, element);
                    } catch (UnconvertibleObjectException e) {
                        throw new MetadataStoreException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3, columnName + '[' + i + ']', elementType, element.getClass()), e);
                    }
            }
            values[i] = element;
        }
        // Now a Java array.
        value = values;
        if (wantCollection) {
            value = specialize(UnmodifiableArrayList.wrap(values), returnType, elementType);
        }
    }
    /*
         * Now converts the value to its final type. To be strict, we should convert null values into empty collections
         * if the return type is a collection type. But we leave this task to the caller (which is the Dispatcher class)
         * for making easier to detect when a value is absent, for allowing Dispatcher to manage its cache.
         */
    if (value != null) {
        if (isMetadata) {
            value = lookup(elementType, value.toString());
        } else
            try {
                value = info.convert(elementType, value);
            } catch (UnconvertibleObjectException e) {
                throw new MetadataStoreException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3, columnName, elementType, value.getClass()), e);
            }
        if (wantCollection) {
            if (Set.class.isAssignableFrom(returnType)) {
                return Collections.singleton(value);
            } else {
                return Collections.singletonList(value);
            }
        }
    }
    return value;
}
Also used : SQLBuilder(org.apache.sis.internal.metadata.sql.SQLBuilder) Array(java.lang.reflect.Array) UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException)

Aggregations

UnconvertibleObjectException (org.apache.sis.util.UnconvertibleObjectException)5 BufferedInputStream (java.io.BufferedInputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 LineNumberReader (java.io.LineNumberReader)1 Reader (java.io.Reader)1 Array (java.lang.reflect.Array)1 SQLException (java.sql.SQLException)1 ParsePosition (java.text.ParsePosition)1 HashMap (java.util.HashMap)1 ImageInputStream (javax.imageio.stream.ImageInputStream)1 Dimension (javax.measure.Dimension)1 SQLBuilder (org.apache.sis.internal.metadata.sql.SQLBuilder)1 ChannelImageInputStream (org.apache.sis.internal.storage.io.ChannelImageInputStream)1 RewindableLineReader (org.apache.sis.internal.storage.io.RewindableLineReader)1 LocalizedParseException (org.apache.sis.internal.util.LocalizedParseException)1 InvalidSeekException (org.apache.sis.io.InvalidSeekException)1 Fraction (org.apache.sis.math.Fraction)1 DependsOnMethod (org.apache.sis.test.DependsOnMethod)1