001 /**
002 * Copyright (C) 2009-2011 the original author or authors.
003 * See the notice.md file distributed with this work for additional
004 * information regarding copyright ownership.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.fusesource.restygwt.rebind;
020
021 import java.util.ArrayList;
022 import java.util.List;
023 import java.util.Map;
024
025 import org.fusesource.restygwt.client.Method;
026 import org.fusesource.restygwt.client.ModelChange;
027 import org.fusesource.restygwt.client.cache.Domain;
028
029 import com.google.gwt.core.ext.TreeLogger;
030 import com.google.gwt.core.ext.UnableToCompleteException;
031 import com.google.gwt.core.ext.typeinfo.JClassType;
032 import com.google.gwt.core.ext.typeinfo.JMethod;
033
034 /**
035 * Implementation for an annotationparser which is responsible to put
036 * annotation-data from ModelChange annotations to {@link Method} instances.
037 *
038 * This class transports information about ModelChangeEvents to be triggered,
039 * when some servicemethods have been called.
040 *
041 * @author <a href="mailto:andi.balke@gmail.com">andi</<a>
042 */
043 public class ModelChangeAnnotationResolver implements AnnotationResolver {
044
045 @Override
046 public Map<String, String[]> resolveAnnotation(TreeLogger logger, JClassType source, JMethod method,
047 final String restMethod) throws UnableToCompleteException {
048 ModelChange classAnnot = source.getAnnotation(ModelChange.class);
049 String[] serviceDomains = null;
050 ModelChange methodAnnot = method.getAnnotation(ModelChange.class);
051 final Map<String, String[]> ret = new java.util.HashMap<String, String[]>();
052
053 if(null != source.getAnnotation(Domain.class)) {
054 serviceDomains = getAnnotationsAsStringArray(
055 source.getAnnotation(Domain.class).value());
056
057 // cachedomain annotations are resolved in any case
058 logger.log(TreeLogger.TRACE, "found ``Domain`` annotation with " + serviceDomains.length
059 + " domains in " + source.getName());
060 ret.put(Domain.CACHE_DOMAIN_KEY, serviceDomains);
061 }
062
063 if (methodAnnot != null) {
064 String[] domains = null;
065
066 if (methodAnnot.domain() == null
067 || methodAnnot.domain().length == 0) {
068 if (serviceDomains == null) {
069 logger.log(TreeLogger.ERROR, "found method annotation with empty domain definition in " +
070 source.getName() + " on method " + method.getName());
071 throw new UnableToCompleteException();
072 }
073 logger.log(TreeLogger.TRACE, "found ``Domain`` annotation with " + serviceDomains.length
074 + " domains '" + serviceDomains + "' "
075 + source.getName() + " on method " + method.getName());
076 domains = serviceDomains;
077 } else {
078 domains = getAnnotationsAsStringArray(methodAnnot.domain());
079 logger.log(TreeLogger.TRACE, "use domain from ModelChange annotation at: "
080 + source.getName() + "#" + method.getName() + ": " + domains);
081 }
082
083 // method annotation match
084 ret.put(ModelChange.MODEL_CHANGED_DOMAIN_KEY, domains);
085 return ret;
086 }
087
088 if (classAnnot != null
089 && classAnnot.on() != null) {
090 for (String s : classAnnot.on()) {
091 if (s.toUpperCase().equals(restMethod.toUpperCase())) {
092 String[] domains = null;
093
094 if (classAnnot.domain() == null
095 || classAnnot.domain().equals("")) {
096 if (serviceDomains == null) {
097 logger.log(TreeLogger.ERROR, "found class annotation with empty domain definition in " +
098 source.getName());
099 throw new UnableToCompleteException();
100 }
101 domains = serviceDomains;
102 } else {
103 domains = getAnnotationsAsStringArray(classAnnot.domain());
104 }
105
106 // class annotation match for current method
107 ret.put(ModelChange.MODEL_CHANGED_DOMAIN_KEY, domains);
108 return ret;
109 }
110 }
111 }
112
113 return ret;
114 }
115
116 /**
117 * convert an array of classes to an array of strings to be usable in js context.
118 *
119 * @param classes
120 * @return
121 */
122 private String[] getAnnotationsAsStringArray(final Class[] classes) {
123 if (null == classes) return null;
124
125 List<String> ret = new ArrayList<String>();
126
127 for(Class c: classes) {
128 ret.add(c.getName());
129 }
130
131 return ret.toArray(new String[ret.size()]);
132 }
133 }