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