AbstractArtifactHandler.java
001 /*
002  * Copyright 2008-2015 the original author or authors.
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 package org.codehaus.griffon.runtime.core.artifact;
017 
018 import griffon.core.GriffonApplication;
019 import griffon.core.artifact.ArtifactHandler;
020 import griffon.core.artifact.GriffonArtifact;
021 import griffon.core.artifact.GriffonClass;
022 import griffon.core.injection.Binding;
023 import org.codehaus.griffon.runtime.core.injection.Bindings;
024 import org.codehaus.griffon.runtime.core.injection.LinkedBindingBuilder;
025 
026 import javax.annotation.Nonnull;
027 import javax.annotation.Nullable;
028 import javax.inject.Inject;
029 import java.util.ArrayList;
030 import java.util.Collection;
031 import java.util.Collections;
032 import java.util.List;
033 import java.util.Map;
034 import java.util.TreeMap;
035 
036 import static griffon.util.AnnotationUtils.typed;
037 import static griffon.util.GriffonNameUtils.requireNonBlank;
038 import static java.util.Objects.requireNonNull;
039 
040 /**
041  * Base implementation of the ArtifactHandler interface.
042  *
043  @author Andres Almiray
044  @since 2.0.0
045  */
046 public abstract class AbstractArtifactHandler<A extends GriffonArtifact> implements ArtifactHandler<A> {
047     protected static final String ERROR_CLASS_NULL = "Argument 'class' must not be null";
048     private final Class<A> artifactType;
049     private final String type;
050     private final String trailing;
051     private final GriffonApplication application;
052 
053     private GriffonClass[] griffonClasses = new GriffonClass[0];
054     private final Map<String, GriffonClass> classesByName = new TreeMap<>();
055 
056     @Inject
057     public AbstractArtifactHandler(@Nonnull GriffonApplication application, @Nonnull Class<A> artifactType, @Nonnull String type, @Nonnull String trailing) {
058         this.application = requireNonNull(application, "Argument 'application' must not be null");
059         this.artifactType = requireNonNull(artifactType, "Argument 'artifactType' must not be null");
060         this.type = requireNonBlank(type, "Argument 'type' must not be blank");
061         this.trailing = requireNonNull(trailing, "Argument 'trailing' must not be null");
062     }
063 
064     @Nonnull
065     public Class<A> getArtifactType() {
066         return artifactType;
067     }
068 
069     @Nonnull
070     public String getType() {
071         return type;
072     }
073 
074     @Nonnull
075     public String getTrailing() {
076         return trailing;
077     }
078 
079     @Nonnull
080     public Collection<Binding<?>> initialize(@Nonnull Class<A>[] classes) {
081         griffonClasses = new GriffonClass[classes.length];
082         List<Binding<?>> bindings = new ArrayList<>();
083         for (int i = 0; i < classes.length; i++) {
084             Class<A> klass = classes[i];
085             GriffonClass griffonClass = newGriffonClassInstance(klass);
086             griffonClasses[i= griffonClass;
087             classesByName.put(klass.getName(), griffonClass);
088             createBindings(bindings, klass, griffonClass);
089         }
090         return bindings;
091     }
092 
093     protected void createBindings(@Nonnull List<Binding<?>> bindings, @Nonnull Class<A> clazz, @Nonnull GriffonClass griffonClass) {
094         LinkedBindingBuilder<GriffonClass> builder = Bindings.bind(GriffonClass.class)
095             .withClassifier(typed(clazz));
096         builder.toInstance(griffonClass);
097         bindings.add(builder.getBinding());
098         bindings.add(Bindings.bind(clazz).getBinding());
099     }
100 
101     @Nonnull
102     public Map<String, GriffonClass> getClassesByName() {
103         return Collections.unmodifiableMap(classesByName);
104     }
105 
106     /**
107      * Returns true if the target Class is a class artifact
108      * handled by this object.<p>
109      * This implementation performs an equality check on class.name
110      */
111     public boolean isArtifact(@Nonnull Class<A> clazz) {
112         requireNonNull(clazz, ERROR_CLASS_NULL);
113         return classesByName.get(clazz.getName()) != null;
114     }
115 
116     public boolean isArtifact(@Nonnull GriffonClass clazz) {
117         requireNonNull(clazz, ERROR_CLASS_NULL);
118         for (GriffonClass griffonClass : griffonClasses) {
119             if (griffonClass.equals(clazz)) return true;
120         }
121         return false;
122     }
123 
124     @Nonnull
125     public GriffonClass[] getClasses() {
126         return griffonClasses;
127     }
128 
129     @Nullable
130     public GriffonClass getClassFor(@Nonnull Class<A> clazz) {
131         requireNonNull(clazz, ERROR_CLASS_NULL);
132         return getClassFor(clazz.getName());
133     }
134 
135     @Nullable
136     public GriffonClass getClassFor(@Nonnull String fqnClassName) {
137         requireNonBlank(fqnClassName, "Argument 'fqnClassName' must not be blank");
138         return classesByName.get(fqnClassName);
139     }
140 
141     @Nullable
142     public GriffonClass findClassFor(@Nonnull String propertyName) {
143         requireNonBlank(propertyName, "Argument 'propertyName' must not be blank");
144 
145         String simpleName = propertyName;
146 
147         int lastDot = propertyName.lastIndexOf(".");
148         if (lastDot > -1) {
149             simpleName = simpleName.substring(lastDot + 1);
150         }
151 
152         if (simpleName.length() == 1) {
153             simpleName = simpleName.toUpperCase();
154         else {
155             simpleName = simpleName.substring(01).toUpperCase() + simpleName.substring(1);
156         }
157 
158         if (!simpleName.endsWith(trailing)) {
159             simpleName += trailing;
160         }
161 
162         for (GriffonClass griffonClass : griffonClasses) {
163             if (griffonClass.getClazz().getSimpleName().equals(simpleName)) {
164                 return griffonClass;
165             }
166         }
167 
168         return null;
169     }
170 
171     @Nonnull
172     protected GriffonApplication getApplication() {
173         return application;
174     }
175 }