001/*
002 * (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Jean-Marc Orliaguet, Chalmers
018 *
019 */
020
021package org.nuxeo.theme.vocabularies;
022
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.InputStreamReader;
026import java.util.ArrayList;
027import java.util.HashMap;
028import java.util.List;
029import java.util.Map;
030
031import org.apache.commons.csv.CSVFormat;
032import org.apache.commons.csv.CSVParser;
033import org.apache.commons.csv.CSVRecord;
034import org.apache.commons.io.Charsets;
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037
038import org.nuxeo.theme.Manager;
039import org.nuxeo.theme.Registrable;
040import org.nuxeo.theme.types.TypeFamily;
041
042public final class VocabularyManager implements Registrable {
043
044    private static final Log log = LogFactory.getLog(VocabularyManager.class);
045
046    private final Map<String, Vocabulary> vocabularies = new HashMap<>();
047
048    public List<VocabularyItem> getItems(String name) {
049        VocabularyType vocabularyType = (VocabularyType) Manager.getTypeRegistry().lookup(TypeFamily.VOCABULARY, name);
050        if (vocabularyType == null) {
051            return null;
052        }
053        final String path = vocabularyType.getPath();
054        final String className = vocabularyType.getClassName();
055
056        if (path == null && className == null) {
057            log.error("Must specify a class name or a path for vocabulary: " + name);
058            return null;
059        }
060        if (path != null && className != null) {
061            log.error("Cannot specify both a class name and a path for vocabulary: " + name);
062            return null;
063        }
064
065        if (className != null) {
066            Vocabulary vocabulary = getInstance(className);
067            if (vocabulary == null) {
068                log.error("Vocabulary class not found: " + className);
069                return null;
070            }
071            return vocabulary.getItems();
072        }
073
074        if (path != null) {
075            if (!path.endsWith(".csv")) {
076                log.error("Only .csv vocabularies are supported: " + path);
077                return null;
078            }
079            final List<VocabularyItem> items = new ArrayList<>();
080            try (InputStream is = getClass().getClassLoader().getResourceAsStream(path)) {
081                if (is == null) {
082                    log.error("Vocabulary file not found: " + path);
083                    return null;
084                }
085                try (CSVParser reader = new CSVParser(new InputStreamReader(is, Charsets.UTF_8), CSVFormat.DEFAULT)) {
086                    for (CSVRecord record : reader) {
087                        final String value = record.get(0);
088                        String label = value;
089                        if (record.size() >= 2) {
090                            label = record.get(1);
091                        }
092                        items.add(new VocabularyItem(value, label));
093                    }
094                }
095            } catch (IOException e) {
096                log.error("Could not read vocabulary file: " + path, e);
097            }
098            return items;
099        }
100        return null;
101    }
102
103    private Vocabulary getInstance(String className) {
104        Vocabulary vocabulary = vocabularies.get(className);
105        if (vocabulary == null) {
106            try {
107                vocabulary = (Vocabulary) Class.forName(className).newInstance();
108            } catch (InstantiationException e) {
109                log.error("Could not instantiate vocabulary: " + className);
110            } catch (IllegalAccessException e) {
111                log.error("Could not instantiate vocabulary: " + className);
112            } catch (ClassNotFoundException e) {
113                log.error("Could not instantiate vocabulary: " + className);
114            }
115        }
116        if (vocabulary != null) {
117            vocabularies.put(className, vocabulary);
118        }
119        return vocabulary;
120    }
121
122    @Override
123    public void clear() {
124        // FIXME: should call vocabularies.clear() ?
125    }
126
127}