/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2004-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.factory;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import java.util.Arrays;
import java.util.Locale;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Comparator;
import java.util.Collection;
import java.util.Collections;
import org.opengis.util.Factory;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Citation;
import org.opengis.referencing.AuthorityFactory;
import org.geotoolkit.lang.Debug;
import org.geotoolkit.io.TableWriter;
import org.apache.sis.util.Classes;
import org.geotoolkit.resources.Vocabulary;
/**
* Prints a list of factory.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.00
*
* @since 2.4
* @module
*/
@Debug
final class FactoryPrinter implements Comparator<Class<?>> {
/**
* The factory registries to format.
*/
private final Collection<FactoryRegistry> registries;
/**
* Constructs a default instance of this printer.
*
* @param registry Where the factories are registered.
*/
public FactoryPrinter(final FactoryRegistry registry) {
this.registries = Collections.singleton(registry);
}
/**
* Constructs a default instance of this printer.
*
* @param registries Where the factories are registered.
*/
public FactoryPrinter(final Collection<FactoryRegistry> registries) {
this.registries = registries;
}
/**
* Compares two categories for order. This is used for sorting out the services
* before to display them.
*/
@Override
public int compare(final Class<?> factory1, final Class<?> factory2) {
return Classes.getShortName(factory1).compareToIgnoreCase(
Classes.getShortName(factory2));
}
/**
* Lists all available factory implementations in a tabular format. For each factory interface,
* the first implementation listed is the default one. This method provides a way to check the
* state of a system, usually for debugging purpose.
*
* @param out The output stream where to format the list.
* @param locale The locale for the list, or {@code null}.
* @throws IOException if an error occurs while writing to {@code out}.
*/
public void list(final Writer out, final Locale locale) throws IOException {
/*
* Gets the categories in some sorted order.
*/
final Map<Class<?>,FactoryRegistry> categories = new HashMap<>();
for (final FactoryRegistry registry : registries) {
for (final Iterator<Class<?>> it=registry.getCategories(); it.hasNext();) {
categories.put(it.next(), registry);
}
}
final Class<?>[] sorted = categories.keySet().toArray(new Class<?>[categories.size()]);
Arrays.sort(sorted, this);
/*
* Prints the table header.
*/
final Vocabulary resources = Vocabulary.getResources(locale);
final TableWriter table = new TableWriter(out);
table.setMultiLinesCells(true);
table.nextLine(TableWriter.DOUBLE_HORIZONTAL_LINE);
table.write(resources.getString(Vocabulary.Keys.Service));
table.nextColumn();
table.write(resources.getString(Vocabulary.Keys.Implementations));
table.nextColumn();
table.write(resources.getString(Vocabulary.Keys.Vendor));
table.nextColumn();
table.write(resources.getString(Vocabulary.Keys.Authority));
table.nextLine();
table.nextLine(TableWriter.DOUBLE_HORIZONTAL_LINE);
final StringBuilder vendors = new StringBuilder();
final StringBuilder authorities = new StringBuilder();
int categoryCount = 0;
for (final Class<?> category : sorted) {
if (categoryCount++ != 0) {
table.writeHorizontalSeparator();
}
/*
* Writes the category name (CRSFactory, DatumFactory, etc.)
*/
table.write(Classes.getShortName(category));
table.nextColumn();
/*
* Writes the implementation in a single cell. We will do the same for vendors and
* authorities, but those ones need to be stored in a temporary buffer for now.
*/
final FactoryRegistry registry = categories.get(category);
final Iterator<?> providers = registry.getServiceProviders(category, null, null, null);
int implementationsCount = 0;
while (providers.hasNext()) {
if (implementationsCount++ != 0) {
table .write ('\n');
vendors .append('\n');
authorities.append('\n');
}
final Object provider = providers.next();
table.write(Classes.getShortClassName(provider));
if (provider instanceof Factory) {
final Citation vendor = ((Factory) provider).getVendor();
vendors.append(vendor.getTitle().toString(locale));
}
if (provider instanceof AuthorityFactory) {
final Citation authority = ((AuthorityFactory) provider).getAuthority();
final Iterator<? extends Identifier> identifiers =
authority.getIdentifiers().iterator();
final String identifier = identifiers.hasNext() ?
identifiers.next().getCode() : authority.getTitle().toString(locale);
authorities.append(identifier);
}
}
/*
* Writes all columns (vendors and authorities) that were buffered in the aboved loop.
*/
table.nextColumn();
table.write(vendors.toString());
vendors.setLength(0);
table.nextColumn();
table.write(authorities.toString());
authorities.setLength(0);
table.nextLine();
}
table.nextLine(TableWriter.DOUBLE_HORIZONTAL_LINE);
table.flush();
}
/**
* Returns the list of available factory implementations in a string.
*
* @param registry Where the factories are registered.
* @return A string representation of the factories table.
*/
@Override
public String toString() {
final StringWriter out = new StringWriter();
try {
list(out, null);
} catch (IOException e) {
// Should never happen since we are writing to a StringWriter,
throw new AssertionError(e);
}
return out.toString();
}
}