Author: desruisseaux
Date: Wed Dec  5 08:03:27 2012
New Revision: 1417302

URL: http://svn.apache.org/viewvc?rev=1417302&view=rev
Log:
Initial implementation of MarshalContext (internal API).

Added:
    
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
   (with props)
Modified:
    
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
    
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/xml/MarshalContext.java

Added: 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java?rev=1417302&view=auto
==============================================================================
--- 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
 (added)
+++ 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
 Wed Dec  5 08:03:27 2012
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sis.internal.jaxb;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Locale;
+import java.util.TimeZone;
+import org.opengis.metadata.Identifier;
+import org.apache.sis.util.Version;
+import org.apache.sis.xml.ValueConverter;
+import org.apache.sis.xml.ReferenceResolver;
+import org.apache.sis.util.collection.UnmodifiableArrayList;
+
+
+/**
+ * Thread-local status of a marshalling or unmarshalling process.
+ * Contains also static methods for managing the collections to be marshalled.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.07)
+ * @version 0.3
+ * @module
+ */
+public final class MarshalContext extends org.apache.sis.xml.MarshalContext {
+    /**
+     * The bit flag telling if a marshalling process is under progress.
+     * This flag is unset for unmarshalling processes.
+     */
+    public static final int MARSHALING = 1;
+
+    /**
+     * The bit flag for enabling substitution of language codes by character 
strings.
+     */
+    public static final int SUBSTITUTE_LANGUAGE = 2;
+
+    /**
+     * The bit flag for enabling substitution of country codes by character 
strings.
+     */
+    public static final int SUBSTITUTE_COUNTRY = 4;
+
+    /**
+     * The thread-local context.
+     */
+    private static final ThreadLocal<MarshalContext> CURRENT = new 
ThreadLocal<>();
+
+    /**
+     * The value converter currently in use, or {@code null} for {@link 
ValueConverter#DEFAULT}.
+     */
+    private ValueConverter converter;
+
+    /**
+     * The reference resolver currently in use, or {@code null} for {@link 
ReferenceResolver#DEFAULT}.
+     */
+    private ReferenceResolver resolver;
+
+    /**
+     * The GML version to be marshalled or unmarshalled, or {@code null} if 
unspecified.
+     * If null, than the latest version is assumed.
+     */
+    private Version versionGML;
+
+    /**
+     * The base URL of ISO 19139 (or other standards) schemas. The valid values
+     * are documented in the {@link org.apache.sis.xml.XML#SCHEMAS} property.
+     */
+    private Map<String,String> schemas;
+
+    /**
+     * The locale to use for marshalling, or {@code null} if no locale were 
explicitly specified.
+     */
+    private Locale locale;
+
+    /**
+     * The timezone, or {@code null} if unspecified.
+     * In the later case, an implementation-default (typically UTC) timezone 
is used.
+     */
+    private TimeZone timezone;
+
+    /**
+     * Various boolean attributes determines by the above static constants.
+     */
+    private int bitMasks;
+
+    /**
+     * The context which was previously used. This form a linked list allowing
+     * to push properties (e.g. {@link #pushLocale(Locale)}) and pull back the
+     * context to its previous state once finished.
+     */
+    private final MarshalContext previous;
+
+    /**
+     * Invoked when a marshalling or unmarshalling process is about to begin.
+     * Must be followed by a call to {@link #finish()} in a {@code finally} 
block.
+     *
+     * {@preformat java
+     *     MarshalContext context = new MarshalContext(…);
+     *     try {
+     *         ...
+     *     } finally {
+     *         context.finish();
+     *     }
+     * }
+     *
+     * @param  converter  The converter in use.
+     * @param  resolver   The resolver in use.
+     * @param  versionGML The GML version, or {@code null}.
+     * @param  schemas    The schemas root URL, or {@code null} if none.
+     * @param  locale     The locale, or {@code null} if unspecified.
+     * @param  timezone   The timezone, or {@code null} if unspecified.
+     * @param  bitMasks   A combination of {@link #MARSHALING}, {@link 
#SUBSTITUTE_LANGUAGE},
+     *                    {@link #SUBSTITUTE_COUNTRY} or other bit masks.
+     */
+    public MarshalContext(final ValueConverter converter, final 
ReferenceResolver resolver,
+            final Version versionGML, final Map<String,String> schemas,
+            final Locale locale, final TimeZone timezone, final int bitMasks)
+    {
+        this.converter  = converter;
+        this.resolver   = resolver;
+        this.versionGML = versionGML;
+        this.schemas    = schemas; // No clone, because this class is internal.
+        this.locale     = locale;
+        this.timezone   = timezone;
+        this.bitMasks   = bitMasks;
+        previous = current();
+        CURRENT.set(this);
+    }
+
+    /**
+     * Inherits all configuration from the previous context, if any.
+     *
+     * @param previous The context from which to inherit the configuration, or 
{@code null}.
+     *
+     * @see #push(Locale)
+     */
+    private MarshalContext(final MarshalContext previous) {
+        if (previous != null) {
+            converter  = previous.converter;
+            resolver   = previous.resolver;
+            versionGML = previous.versionGML;
+            schemas    = previous.schemas;
+            locale     = previous.locale;
+            timezone   = previous.timezone;
+            bitMasks   = previous.bitMasks;
+        }
+        this.previous = previous;
+        CURRENT.set(this);
+    }
+
+    /**
+     * Returns the context of the XML (un)marshalling currently progressing in 
the current thread,
+     * or {@code null} if none.
+     *
+     * @return The current (un)marshalling context, or {@code null} if none.
+     */
+    public static MarshalContext current() {
+        return CURRENT.get();
+    }
+
+    /**
+     * Returns {@code true} if the given flag is set.
+     *
+     * @param  flag One of {@link #MARSHALING}, {@link #SUBSTITUTE_LANGUAGE},
+     *         {@link #SUBSTITUTE_COUNTRY} or other bit masks.
+     * @return {@code true} if the given flag is set.
+     */
+    public static boolean isFlagSet(final int flag) {
+        final MarshalContext current = current();
+        return (current != null) && (current.bitMasks & flag) != 0;
+    }
+
+    /**
+     * Returns the value converter in use for the current marshalling or 
unmarshalling process.
+     * If no converter were explicitely set, then this method returns {@link 
ValueConverter#DEFAULT}.
+     *
+     * {@note This method is static for the convenience of performing the 
check for null context.}
+     *
+     * @param  current The current context, or {@code null} if none.
+     * @return The current value converter (never null).
+     */
+    public static ValueConverter converter(final MarshalContext current) {
+        if (current != null) {
+            final ValueConverter converter = current.converter;
+            if (converter != null) {
+                return converter;
+            }
+        }
+        return ValueConverter.DEFAULT;
+    }
+
+    /**
+     * Returns the reference resolver in use for the current marshalling or 
unmarshalling process.
+     * If no resolver were explicitely set, then this method returns {@link 
ReferenceResolver#DEFAULT}.
+     *
+     * {@note This method is static for the convenience of performing the 
check for null context.}
+     *
+     * @param  current The current context, or {@code null} if none.
+     * @return The current reference resolver (never null).
+     */
+    public static ReferenceResolver resolver(final MarshalContext current) {
+        if (current != null) {
+            final ReferenceResolver resolver = current.resolver;
+            if (resolver != null) {
+                return resolver;
+            }
+        }
+        return ReferenceResolver.DEFAULT;
+    }
+
+    /**
+     * Returns the base URL of ISO 19139 (or other standards) schemas.
+     * The valid values are documented in the {@link 
org.apache.sis.xml.XML#SCHEMAS} property.
+     *
+     * {@note This method is static for the convenience of performing the 
check for null context.}
+     *
+     * @param  current The current context, or {@code null} if none.
+     * @param  key One of the value documented in the "<cite>Map key</cite>" 
column of
+     *         {@link org.apache.sis.xml.XML#SCHEMAS}.
+     * @param  defaultSchema The value to return if no schema is found for the 
given key.
+     * @return The base URL of the schema, or {@code null} if none were 
specified.
+     */
+    public static String schema(final MarshalContext current, final String 
key, final String defaultSchema) {
+        if (current != null) {
+            final Map<String,String> schemas = current.schemas;
+            if (schemas != null) {
+                final String schema = schemas.get(key);
+                if (schema != null) {
+                    return schema;
+                }
+            }
+        }
+        return defaultSchema;
+    }
+
+    /**
+     * Returns {@code true} if the GML version is equals or newer than the 
specified version.
+     * If no GML version were specified, then this method returns {@code 
true}, i.e. newest
+     * version is assumed.
+     *
+     * {@note This method is static for the convenience of performing the 
check for null context.}
+     *
+     * @param  current The current context, or {@code null} if none.
+     * @param  version The version to compare to.
+     * @return {@code true} if the GML version is equals or newer than the 
specified version.
+     *
+     * @see #getVersion(String)
+     */
+    public static boolean isGMLVersion(final MarshalContext current, final 
Version version) {
+        if (current != null) {
+            final Version versionGML = current.versionGML;
+            if (versionGML != null) {
+                return versionGML.compareTo(version) >= 0;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the schema version of the XML document being (un)marshalled.
+     * See the super-class javadoc for the list of prefix that we shall 
support.
+     */
+    @Override
+    public final Version getVersion(final String prefix) {
+        if (prefix.equals("gml")) {
+            return versionGML;
+        }
+        // Future SIS versions may add more cases here.
+        return null;
+    }
+
+    /**
+     * Returns the timezone, or {@code null} if none were explicitely defined.
+     * In the later case, an implementation-default (typically UTC) timezone 
is used.
+     */
+    @Override
+    public final TimeZone getTimeZone() {
+        return timezone;
+    }
+
+    /**
+     * Returns the locale to use for marshalling, or {@code null} if no locale 
were explicitly
+     * specified. A {@code null} value means that some locale-neutral language 
should be used
+     * if available, or an implementation-default locale (typically English) 
otherwise.
+     */
+    @Override
+    public final Locale getLocale() {
+        return locale;
+    }
+
+    /**
+     * Sets the locale to the given value. The old locales are remembered and 
will
+     * be restored by the next call to {@link #pullLocale()}.
+     *
+     * @param locale The locale to set, or {@code null}.
+     */
+    public static void push(final Locale locale) {
+        final MarshalContext current = new MarshalContext(current());
+        if (locale != null) {
+            current.locale = locale;
+        }
+    }
+
+    /**
+     * Restores the locale (or any other setting) which was used prior the 
call to
+     * {@link #push(Locale)}.
+     */
+    public static void pull() {
+        final MarshalContext current = current();
+        if (current != null) {
+            current.finish();
+        }
+    }
+
+    /**
+     * If marshalling, filters the given collection of identifiers in order to 
omit any identifiers
+     * for which the authority is one of the {@link 
org.apache.sis.xml.IdentifierSpace} constants.
+     *
+     * @param  identifiers The identifiers to filter, or {@code null}.
+     * @return The identifiers to marshal, or {@code null} if none.
+     */
+    public static Collection<Identifier> 
filterIdentifiers(Collection<Identifier> identifiers) {
+        if (identifiers != null && isFlagSet(MARSHALING)) {
+            int count = identifiers.size();
+            if (count != 0) {
+                final Identifier[] copy = identifiers.toArray(new 
Identifier[count]);
+                for (int i=count; --i>=0;) {
+                    final Identifier id = copy[i];
+                    if (id == null || (id.getAuthority() instanceof 
NonMarshalledAuthority)) {
+                        System.arraycopy(copy, i+1, copy, i, --count - i);
+                    }
+                }
+                identifiers = (count != 0) ? UnmodifiableArrayList.wrap(copy, 
0, count) : null;
+            }
+        }
+        return identifiers;
+    }
+
+    /**
+     * Invoked in a {@code finally} block when a unmarshalling process is 
finished.
+     */
+    public final void finish() {
+        if (previous != null) {
+            CURRENT.set(previous);
+        } else {
+            CURRENT.remove();
+        }
+    }
+}

Propchange: 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java?rev=1417302&r1=1417301&r2=1417302&view=diff
==============================================================================
--- 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
 (original)
+++ 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
 Wed Dec  5 08:03:27 2012
@@ -256,10 +256,17 @@ public class DefaultInternationalString 
      * {@section Handling of <code>null</code> argument value}
      * A {@code null} argument value can be given to this method for
      * requesting a "unlocalized" string - typically some programmatic strings 
like
-     * {@linkplain org.opengis.annotation.UML#identifier() UML identifiers}. 
While such
-     * identifiers often look like English words, they are not considered as 
the
-     * {@linkplain Locale#ENGLISH English locale}. In order to produce a value 
close
-     * to the common practice, this method handles {@code null} argument value 
as below:
+     * {@linkplain org.opengis.annotation.UML#identifier() UML identifiers}.
+     * While such identifiers often look like English words, they are not 
considered
+     * as the {@linkplain Locale#ENGLISH English locale}. For example:
+     *
+     * <ul>
+     *   <li>Numbers are formatted using {@code Number.toString()} rather than 
{@link java.text.NumberFormat}.</li>
+     *   <li>Dates are formatted according the ISO standard rather than the 
English locale.</li>
+     * </ul>
+     *
+     * In order to produce a value close to the common practice,
+     * this method handles {@code null} argument value as below:
      *
      * <ul>
      *   <li>If a string has been explicitly {@linkplain #add(Locale, String) 
added} for the

Modified: 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/xml/MarshalContext.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/xml/MarshalContext.java?rev=1417302&r1=1417301&r2=1417302&view=diff
==============================================================================
--- 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/xml/MarshalContext.java
 (original)
+++ 
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/xml/MarshalContext.java
 Wed Dec  5 08:03:27 2012
@@ -79,6 +79,23 @@ public abstract class MarshalContext {
      * In particular children of {@link org.opengis.metadata.Metadata} inherit 
the locale
      * specified by the {@link org.opengis.metadata.Metadata#getLanguage()} 
attribute.
      *
+     * {@section Null locale}
+     * Null locales are typically interpreted as a request for 
locale-independent strings in SIS.
+     * The meaning of "locale-independent" is implementation specific -
+     * this is usually very close to the English locale, but not necessarily
+     * (e.g. dates formatted according ISO standard instead then English 
locale).
+     * If the locale is {@code null}, then callers shall select a default 
locale as documented
+     * in the {@link 
org.apache.sis.util.type.DefaultInternationalString#toString(Locale)} javadoc.
+     * As a matter of rule:
+     *
+     * <ul>
+     *   <li>If the locale is given to an {@code 
InternationalString.toString(Locale)} method,
+     *       keep the {@code null} value since the international string is 
already expected to
+     *       returns a "unlocalized" string in such case.</li>
+     *   <li>Otherwise, if a {@code Locale} instance is really needed, use 
{@link Locale#US}
+     *       as an approximation of "unlocalized" string.</li>
+     * </ul>
+     *
      * @return The locale for the XML fragment being (un)marshalled, or {@code 
null} is unspecified.
      */
     public abstract Locale getLocale();


Reply via email to