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(0, 1).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 }
|