001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.controls.runtime.assembly;
020:
021: import java.io.File;
022: import java.lang.annotation.Annotation;
023: import java.lang.reflect.Method;
024: import java.util.Map;
025: import java.util.Set;
026: import java.util.LinkedList;
027: import java.util.Queue;
028:
029: import com.sun.mirror.apt.Messager;
030: import com.sun.mirror.util.SourcePosition;
031:
032: import org.apache.beehive.controls.api.bean.ControlInterface;
033: import org.apache.beehive.controls.api.assembly.ControlAssemblyContext;
034: import org.apache.beehive.controls.api.assembly.ControlAssemblyException;
035: import org.apache.beehive.controls.runtime.bean.ControlUtils;
036:
037: /**
038: * Abstract ControlAssemblyContext implementation. Provides a basic implementation of most non-module-specific
039: * APIs, meant to be extended by module-specific types.
040: */
041: public abstract class BaseAssemblyContext implements
042: ControlAssemblyContext {
043: protected BaseAssemblyContext(Class controlIntfOrExt,
044: Map<String, String> bindings, Set<String> clients,
045: File moduleRoot, String moduleName, File srcOutputRoot)
046: throws ControlAssemblyException {
047: _controlIntfOrExt = controlIntfOrExt;
048: _bindings = bindings;
049: _clients = clients;
050: _moduleRoot = moduleRoot;
051: _moduleName = moduleName;
052: _srcOutputRoot = srcOutputRoot;
053: _messager = new DefaultAssemblyMessager();
054:
055: // Compute and cache "most derived ControlInterface"
056: Queue<Class> q = new LinkedList<Class>();
057: Class ci = controlIntfOrExt;
058:
059: while (ci != null) {
060: if (ci.isAnnotationPresent(ControlInterface.class)) {
061: _controlMostDerivedIntf = ci;
062: break;
063: }
064:
065: Class[] super s = ci.getInterfaces();
066: for (Class s : super s)
067: q.offer(s);
068:
069: ci = q.poll();
070: }
071:
072: if (_controlMostDerivedIntf == null)
073: throw new ControlAssemblyException("Invalid control type: "
074: + controlIntfOrExt.getName());
075: }
076:
077: public Class getControlType() {
078: return _controlIntfOrExt;
079: }
080:
081: public Class getMostDerivedControlInterface() {
082: return _controlMostDerivedIntf;
083: }
084:
085: // TODO - if we want to override class annotations on instance then here is where we will do it
086: public <T extends Annotation> T getControlAnnotation(
087: Class<T> annotationClass) {
088: Class controlInterface = getControlType();
089: return (T) controlInterface.getAnnotation(annotationClass);
090: }
091:
092: public <T extends Annotation> T getControlMethodAnnotation(
093: Class<T> annotationClass, Method m)
094: throws NoSuchMethodException {
095: Class controlInterface = getControlType();
096: Method controlMethod = controlInterface.getMethod(m.getName(),
097: m.getParameterTypes());
098:
099: return (T) controlMethod.getAnnotation(annotationClass);
100: }
101:
102: public String getDefaultImplClassName() {
103: Class ci = getMostDerivedControlInterface();
104: ControlInterface a = (ControlInterface) ci
105: .getAnnotation(ControlInterface.class);
106:
107: return ControlUtils.resolveDefaultBinding(a.defaultBinding(),
108: ci.getName());
109: }
110:
111: public File getSrcOutputDir() {
112: return _srcOutputRoot;
113: }
114:
115: public File getModuleDir() {
116: return _moduleRoot;
117: }
118:
119: public String getModuleName() {
120: return _moduleName;
121: }
122:
123: public Set<String> getClients() {
124: return _clients;
125: }
126:
127: public Messager getMessager() {
128: return _messager;
129: }
130:
131: public boolean hasErrors() {
132: return _nErrors > 0;
133: }
134:
135: private class DefaultAssemblyMessager implements Messager {
136: public void printError(SourcePosition pos, String msg) {
137: printDiagnostic("Error", pos, msg);
138: _nErrors++;
139: }
140:
141: public void printError(String msg) {
142: printError(null, msg);
143: }
144:
145: public void printNotice(SourcePosition pos, String msg) {
146: printDiagnostic("Notice", pos, msg);
147: }
148:
149: public void printNotice(String msg) {
150: printNotice(null, msg);
151: }
152:
153: public void printWarning(SourcePosition pos, String msg) {
154: printDiagnostic("Warning", pos, msg);
155: }
156:
157: public void printWarning(String msg) {
158: printWarning(null, msg);
159: }
160:
161: protected void printDiagnostic(String type, SourcePosition pos,
162: String msg) {
163: String fn = "<not available>";
164: int line = 0;
165: int column = 0;
166:
167: if (pos != null) {
168: fn = pos.file().getName();
169: line = pos.line();
170: column = pos.column();
171: }
172:
173: System.out.println(type + ": (" + fn + ":" + line + ":"
174: + column + ") " + msg);
175: }
176: }
177:
178: private File _moduleRoot;
179: private String _moduleName;
180: private File _srcOutputRoot;
181: private Class _controlIntfOrExt;
182: private Map<String, String> _bindings;
183: private Set<String> _clients;
184: private Messager _messager;
185: private int _nErrors = 0;
186:
187: private Class _controlMostDerivedIntf;
188: }
|