001/*
002 * (C) Copyright 2006-2014 Nuxeo SA <http://nuxeo.com> and others
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Jean-Marc Orliaguet, Chalmers
011 *
012 */
013
014package org.nuxeo.theme.vocabularies;
015
016import java.io.IOException;
017import java.io.InputStream;
018import java.io.InputStreamReader;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.commons.csv.CSVFormat;
025import org.apache.commons.csv.CSVParser;
026import org.apache.commons.csv.CSVRecord;
027import org.apache.commons.io.Charsets;
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030
031import org.nuxeo.theme.Manager;
032import org.nuxeo.theme.Registrable;
033import org.nuxeo.theme.types.TypeFamily;
034
035public final class VocabularyManager implements Registrable {
036
037    private static final Log log = LogFactory.getLog(VocabularyManager.class);
038
039    private final Map<String, Vocabulary> vocabularies = new HashMap<>();
040
041    public List<VocabularyItem> getItems(String name) {
042        VocabularyType vocabularyType = (VocabularyType) Manager.getTypeRegistry().lookup(TypeFamily.VOCABULARY, name);
043        if (vocabularyType == null) {
044            return null;
045        }
046        final String path = vocabularyType.getPath();
047        final String className = vocabularyType.getClassName();
048
049        if (path == null && className == null) {
050            log.error("Must specify a class name or a path for vocabulary: " + name);
051            return null;
052        }
053        if (path != null && className != null) {
054            log.error("Cannot specify both a class name and a path for vocabulary: " + name);
055            return null;
056        }
057
058        if (className != null) {
059            Vocabulary vocabulary = getInstance(className);
060            if (vocabulary == null) {
061                log.error("Vocabulary class not found: " + className);
062                return null;
063            }
064            return vocabulary.getItems();
065        }
066
067        if (path != null) {
068            if (!path.endsWith(".csv")) {
069                log.error("Only .csv vocabularies are supported: " + path);
070                return null;
071            }
072            final List<VocabularyItem> items = new ArrayList<>();
073            try (InputStream is = getClass().getClassLoader().getResourceAsStream(path)) {
074                if (is == null) {
075                    log.error("Vocabulary file not found: " + path);
076                    return null;
077                }
078                try (CSVParser reader = new CSVParser(new InputStreamReader(is, Charsets.UTF_8), CSVFormat.DEFAULT)) {
079                    for (CSVRecord record : reader) {
080                        final String value = record.get(0);
081                        String label = value;
082                        if (record.size() >= 2) {
083                            label = record.get(1);
084                        }
085                        items.add(new VocabularyItem(value, label));
086                    }
087                }
088            } catch (IOException e) {
089                log.error("Could not read vocabulary file: " + path, e);
090            }
091            return items;
092        }
093        return null;
094    }
095
096    private Vocabulary getInstance(String className) {
097        Vocabulary vocabulary = vocabularies.get(className);
098        if (vocabulary == null) {
099            try {
100                vocabulary = (Vocabulary) Class.forName(className).newInstance();
101            } catch (InstantiationException e) {
102                log.error("Could not instantiate vocabulary: " + className);
103            } catch (IllegalAccessException e) {
104                log.error("Could not instantiate vocabulary: " + className);
105            } catch (ClassNotFoundException e) {
106                log.error("Could not instantiate vocabulary: " + className);
107            }
108        }
109        if (vocabulary != null) {
110            vocabularies.put(className, vocabulary);
111        }
112        return vocabulary;
113    }
114
115    @Override
116    public void clear() {
117        // FIXME: should call vocabularies.clear() ?
118    }
119
120}