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