001package org.dllearner.confparser;
002
003import org.apache.commons.collections4.BidiMap;
004import org.dllearner.cli.ConfFileOption;
005import org.dllearner.configuration.IConfiguration;
006import org.dllearner.configuration.IConfigurationProperty;
007import org.dllearner.confparser.json.ConfParserJson;
008import org.dllearner.core.AnnComponentManager;
009import org.dllearner.core.Component;
010import org.dllearner.core.ComponentInitException;
011import org.dllearner.core.StringRenderer;
012import org.dllearner.core.StringRenderer.Rendering;
013import org.springframework.core.io.InputStreamResource;
014import org.springframework.core.io.Resource;
015
016import java.io.BufferedInputStream;
017import java.io.IOException;
018import java.util.*;
019import java.util.Map.Entry;
020
021/**
022 * Created by IntelliJ IDEA.
023 * User: Chris
024 * Date: 8/27/11
025 * Time: 7:21 AM
026 * <p/>
027 * Conf Parser Based implementation.
028 */
029public class ConfParserConfiguration implements IConfiguration {
030
031    private final ConfParser parser;
032    private final String baseDir;
033    private final String typeProperty = "type";
034
035    public ConfParserConfiguration(Resource source) {
036        try {
037//          baseDir = source.getFile().getAbsoluteFile().getParent();
038                if(!(source instanceof InputStreamResource)){
039                        baseDir = source.getFile().getAbsoluteFile().getParentFile().getAbsolutePath();
040                } else {
041                        baseDir = null;
042                }
043            BufferedInputStream bufferedInputStream = new BufferedInputStream(source.getInputStream());
044            bufferedInputStream.mark(1);
045            int peek = bufferedInputStream.read();
046            bufferedInputStream.reset();
047            if (peek == '{') {
048                parser = new ConfParserJson(bufferedInputStream);
049            } else {
050                parser = new ConfParserLegacy(bufferedInputStream);
051            }
052            parser.init();
053            
054            // setup rendering TODO put it into CLI
055            ConfFileOption renderingOption = parser.getConfOptionsByProperty("rendering");
056            if(renderingOption != null) {
057                StringRenderer.setRenderer((String) renderingOption.getValue());
058            } else {
059                StringRenderer.setRenderer(Rendering.MANCHESTER_SYNTAX);
060            }
061        } catch (IOException | ComponentInitException e) {
062            throw new RuntimeException(e);
063        }
064    }
065
066    @Override
067    public Collection<String> getBeanNames() {
068        Set<String> result = new HashSet<>();
069        Map<String,List<ConfFileOption>> beans = parser.getConfOptionsByBean();
070        result.addAll(beans.keySet());
071        return result;
072    }
073
074    @Override
075    public Class getClass(String beanName) {
076
077        List<ConfFileOption> confOptions = parser.getConfOptionsByBean(beanName);
078
079        ConfFileOption option = null;
080        for (ConfFileOption confOption : confOptions) {
081            if(typeProperty.equalsIgnoreCase(confOption.getPropertyName())){
082                option = confOption;
083            }
084        }
085
086        if(option == null){
087            throw new RuntimeException("No type property set for bean: " + beanName);
088        }
089
090        Class<?> result = null;
091
092        String value = (String) option.getValue();
093        // first option: use long name of @ComponentAnn annotation (case insensitive)
094        BidiMap<Class<? extends Component>, String> componentsNamed = AnnComponentManager.getInstance().getComponentsNamed();
095        for(Entry<Class<? extends Component>, String> entry : componentsNamed.entrySet()) {
096                if(entry.getValue().equalsIgnoreCase(value)) {
097                        return entry.getKey();
098                }
099        }
100        // second option: use short name of @ComponentAnn annotation
101        // by convention, short names should always be lower case, but we still do it case insensitive
102        BidiMap<Class<? extends Component>, String> componentsNamedShort = AnnComponentManager.getInstance().getComponentsNamedShort();
103        for(Entry<Class<? extends Component>, String> entry : componentsNamedShort.entrySet()) {
104                if(entry.getValue().equalsIgnoreCase(value)) {
105                        return entry.getKey();
106                }
107        }
108        // third option: use specified class name
109        try {
110            result = Class.forName(value);
111        } catch (ClassNotFoundException e) {
112                // if all methods fail, throw an exception
113            throw new RuntimeException("Problem getting class type for bean: " + beanName + " - trying to instantiate class: " + value,e);
114        }
115        return result;
116    }
117
118    @Override
119    public String getBaseDir() {
120        return baseDir;
121    }
122
123    @Override
124    public Collection<IConfigurationProperty> getConfigurationProperties(String beanName) {
125        List<ConfFileOption> confFileOptions = parser.getConfOptionsByBean(beanName);
126        Collection<IConfigurationProperty> result = new ArrayList<>();
127
128        for (ConfFileOption confFileOption : confFileOptions) {
129
130            if (!typeProperty.equalsIgnoreCase(confFileOption.getPropertyName())) {
131                result.add(confFileOption);
132            }
133        }
134        return result;
135    }
136}