001package org.biopax.paxtools.controller;
002
003import org.apache.commons.logging.Log;
004import org.apache.commons.logging.LogFactory;
005import org.biopax.paxtools.model.BioPAXElement;
006import org.biopax.paxtools.model.BioPAXLevel;
007import org.biopax.paxtools.util.IllegalBioPAXArgumentException;
008
009import java.io.BufferedReader;
010import java.io.IOException;
011import java.io.InputStream;
012import java.io.InputStreamReader;
013import java.util.*;
014
015/**
016 * Provides a simple editor map for a level with a given factory.
017 * 
018 * This class initializes 3 singletons( 1 for each level) from a tab delimited text resources that lists the
019 * properties and their domains. This is done to remove any dependencies to Jena.
020 * 
021 * The recommended usage is to use the {@link #get(org.biopax.paxtools.model.BioPAXLevel)} method.
022 * @author Emek Demir
023 */
024public enum SimpleEditorMap implements EditorMap
025{
026
027        L1(BioPAXLevel.L1),
028        L2(BioPAXLevel.L2),
029        L3(BioPAXLevel.L3);
030
031        private static final Log log = LogFactory.getLog(EditorMapImpl.class);
032
033        private final SimpleEditorMapImpl impl;
034
035
036        SimpleEditorMap(BioPAXLevel level)
037        {
038                this.impl = new SimpleEditorMapImpl(level);
039        }
040
041        /**
042         * To obtain a copy of the editor map for the corresponding level, use the
043         * @param level the BioPAX level
044         * @return SimpleEditorMap implementation for the BioPAX L1, L2, or L3
045         */
046        public static SimpleEditorMap get(BioPAXLevel level)
047        {
048                for (SimpleEditorMap value : values())
049                {
050                        if (value.getLevel().equals(level)) return value;
051                }
052                //should never reach here
053                throw new IllegalBioPAXArgumentException("Unknown level:" + level);
054        }
055
056        static class SimpleEditorMapImpl extends EditorMapImpl implements EditorMap
057        {
058                SimpleEditorMapImpl(BioPAXLevel level)
059                {
060                        super(level);
061                        InputStream stream = this.getClass().getResourceAsStream(level + "Editor.properties");
062                        readEditors(level, stream, this);
063                }
064        }
065
066
067        public <D extends BioPAXElement> PropertyEditor<? super D, ?> getEditorForProperty(String property,
068                        Class<D> javaClass)
069
070        {
071                return impl.getEditorForProperty(property, javaClass);
072        }
073
074        @Override public Set<PropertyEditor> getEditorsForProperty(String property)
075        {
076                return impl.getEditorsForProperty(property);
077        }
078
079        @Override
080        public <D extends BioPAXElement> Set<PropertyEditor<? extends D, ?>> getSubclassEditorsForProperty(String property,
081                        Class<D> domain)
082        {
083                return impl.getSubclassEditorsForProperty(property, domain);
084        }
085
086        @Override public Set<PropertyEditor> getEditorsOf(BioPAXElement bpe)
087        {
088                return impl.getEditorsOf(bpe);
089
090        }
091
092        @Override public Set<ObjectPropertyEditor> getInverseEditorsOf(BioPAXElement bpe)
093        {
094                return impl.getInverseEditorsOf(bpe);
095        }
096
097        @Override public <E extends BioPAXElement> Set<? extends Class<E>> getKnownSubClassesOf(Class<E> javaClass)
098        {
099                return impl.getKnownSubClassesOf(javaClass);
100        }
101
102
103        public BioPAXLevel getLevel()
104        {
105                return impl.getLevel();
106
107        }
108
109        @Override public Set<PropertyEditor> getEditorsOf(Class<? extends BioPAXElement> domain)
110        {
111                return impl.getEditorsOf(domain);
112        }
113
114        @Override public Set<ObjectPropertyEditor> getInverseEditorsOf(Class<? extends BioPAXElement> domain)
115        {
116                return impl.getInverseEditorsOf(domain);
117        }
118
119        @Override
120        public Iterator<PropertyEditor> iterator()
121        {
122                return impl.iterator();
123        }
124
125
126        static void readEditors(BioPAXLevel level, InputStream stream, EditorMapImpl map)
127        {
128                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
129                try
130                {
131                        String line = reader.readLine();
132                        StringTokenizer st = new StringTokenizer(line);
133                        while (st.hasMoreElements())
134                        {
135                                map.registerModelClass(st.nextToken());
136                        }
137
138                        while ((line = reader.readLine()) != null)
139                        {
140                                if (!line.startsWith("#"))
141                                {
142                                        st = new StringTokenizer(line);
143                                        String domain = st.nextToken();
144                                        Class<? extends BioPAXElement> domainInterface = map.getLevel().getInterfaceForName(domain);
145
146                                        String propertyName = st.nextToken();
147                                        Map<Class<? extends BioPAXElement>, Set<Class<? extends BioPAXElement>>> rangeRestrictions =
148                                                        new HashMap<Class<? extends BioPAXElement>, Set<Class<? extends BioPAXElement>>>();
149                                        while (st.hasMoreTokens())
150                                        {
151                                                String rToken = st.nextToken();
152                                                if (rToken.startsWith("R:"))
153                                                {
154                                                        StringTokenizer rt = new StringTokenizer(rToken.substring(2), "=");
155                                                        Class<? extends BioPAXElement> rDomain = level.getInterfaceForName(rt.nextToken());
156                                                        Set<Class<? extends BioPAXElement>> rRanges = new HashSet<Class<? extends
157                                                                        BioPAXElement>>();
158                                                        for (StringTokenizer dt = new StringTokenizer(rt.nextToken(), ","); dt.hasMoreTokens(); )
159                                                        {
160                                                                rRanges.add(level.getInterfaceForName(dt.nextToken()));
161                                                        }
162                                                        rangeRestrictions.put(rDomain, rRanges);
163                                                }
164
165                                        }
166                                        map.createAndRegisterBeanEditor(propertyName, domainInterface, rangeRestrictions);
167                                }
168                        }
169                }
170                catch (IOException e)
171                {
172                        log.error("Could not initialize " + "Editor Map", e);
173                }
174                finally
175                {
176                        try
177                        {
178                                stream.close();
179                        }
180                        catch (IOException ignore)
181                        {
182                                log.error("Could not close stream! Exiting");
183                                System.exit(1);
184                        }
185                }
186
187        }
188
189        public static EditorMap buildCustomEditorMap(BioPAXLevel level, InputStream stream)
190        {
191                EditorMapImpl editorMap = new EditorMapImpl(level);
192                readEditors(level,stream,editorMap);
193                return editorMap;
194
195        }
196
197}