001 /* 002 * mesopotamia @mesopotamia.version@ 003 * Multilingual parser and repository. 004 * Copyright (C) 2005 Hammurapi Group 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 019 * 020 * URL: http://http://www.hammurapi.biz 021 * e-Mail: support@hammurapi.biz 022 */ 023 package org.mesopotamia; 024 025 import java.awt.event.WindowEvent; 026 import java.lang.ref.Reference; 027 import java.lang.ref.SoftReference; 028 import java.sql.SQLException; 029 import java.util.ArrayList; 030 import java.util.Collection; 031 import java.util.Collections; 032 import java.util.HashMap; 033 import java.util.Iterator; 034 import java.util.List; 035 import java.util.Map; 036 037 import javax.swing.WindowConstants; 038 import javax.swing.tree.TreeNode; 039 040 import org.mesopotamia.sql.LoadError; 041 import org.mesopotamia.sql.MesopotamiaEngine; 042 import org.w3c.dom.Element; 043 044 import biz.hammurapi.config.Context; 045 import biz.hammurapi.convert.ConvertingService; 046 import biz.hammurapi.legacy.review.Signed; 047 import biz.hammurapi.render.HtmlRenderer; 048 import biz.hammurapi.swing.Browser; 049 import biz.hammurapi.swing.Visualizable; 050 import biz.hammurapi.util.Attributable; 051 import biz.hammurapi.util.VisitableBase; 052 import biz.hammurapi.xml.dom.DomSerializable; 053 054 055 /** 056 * Represents source unit, e.g. java source file 057 * @author Pavel Vlasov 058 * @revision $Revision: 1.1 $ 059 */ 060 public class SourceUnit extends VisitableBase implements DomSerializable, Signed, Attributable { 061 Scan scan; 062 RepositoryLanguage repoLanguage; 063 private org.mesopotamia.sql.SourceUnit dbData; 064 065 /** 066 * Map of level name -> Soft reference -> level data 067 */ 068 private Map<String, Reference> levelData = new HashMap<String, Reference>(); 069 070 /** 071 * Set of level at which this unit is loaded. 072 */ 073 private Collection<Number> loadLevels = new ArrayList<Number>(); 074 075 /** 076 * Instances of SourceUnit shall be created only by 077 * repository 078 * @throws SQLException 079 */ 080 protected SourceUnit(org.mesopotamia.sql.SourceUnit dbData, final Scan scan, RepositoryLanguage repoLanguage, Collection<Number> loadLevels) throws MesopotamiaException { 081 this.repoLanguage=repoLanguage; 082 this.scan=scan; 083 this.dbData=dbData; 084 085 Iterator<Number> it = loadLevels.iterator(); 086 while (it.hasNext()) { 087 this.loadLevels.add(it.next()); 088 089 } 090 MesopotamiaEngine engine = scan.getRepository().getFactory().getEngine(); 091 try { 092 errors=Collections.unmodifiableCollection(engine.getLoadError(dbData.getId(), scan.getId(), new ArrayList<LoadError>())); 093 } catch (SQLException e) { 094 throw new MesopotamiaException("Could not load errors: "+e, e); 095 } 096 } 097 098 static final List<Object> EMPTY_UNMODIFIABLE_LIST = Collections.unmodifiableList(new ArrayList()); 099 100 public int getId() { 101 return dbData.getId(); 102 } 103 104 public String getName() { 105 return dbData.getName(); 106 } 107 108 /** 109 * Namespace shall be retrieved from repository 110 * @return 111 */ 112 public Namespace getNamespace() { 113 return scan.getNamespace(dbData.getNamespaceId()); 114 } 115 116 public String getPath() { 117 return dbData.getPath(); 118 } 119 120 public String getDigest() { 121 return dbData.getUnitDigest(); 122 } 123 124 public Long getSize() { 125 return dbData.getUnitSize(); 126 } 127 128 public RepositoryLanguage getLanguage() { 129 return repoLanguage; 130 } 131 132 public Scan getScan() { 133 return scan; 134 } 135 136 public void toDom(Element holder) { 137 holder.setAttribute("digest-algorithm", dbData.getDigestAlgorithm()); 138 holder.setAttribute("id", String.valueOf(dbData.getId())); 139 holder.setAttribute("language", dbData.getLanguage()); 140 holder.setAttribute("language-version", dbData.getLanguageVersion()); 141 if (dbData.getLastModified()!=null) { 142 holder.setAttribute("last-modified", dbData.getLastModified().toString()); 143 } 144 holder.setAttribute("name", dbData.getName()); 145 holder.setAttribute("path", dbData.getPath()); 146 holder.setAttribute("repository", String.valueOf(dbData.getRepositoryId())); 147 if (dbData.getUnitSize()!=null) { 148 holder.setAttribute("size", dbData.getUnitSize().toString()); 149 } 150 if (dbData.getUnitDigest()!=null) { 151 holder.setAttribute("digest", dbData.getUnitDigest()); 152 } 153 } 154 155 /** 156 * Returns signature, which is path. 157 */ 158 public String getSignature() { 159 return getPath(); 160 } 161 162 /** 163 * @return load levels of this source unit. Elements are of type org.mesopotamia.sql.SourceUnitSuccessfulLoadLevels 164 */ 165 public Collection<Number> getLoadLevels() { 166 return loadLevels; 167 } 168 169 public String toString() { 170 return "["+getClass().getName()+"] "+getPath(); 171 } 172 173 private Collection<LoadError> errors; 174 175 public Collection<LoadError> getErrors() { 176 return errors; 177 } 178 179 /** 180 * @param levelName 181 * @return Load level data for given source unit. This method returns only 182 * scan-independent data. 183 * @throws MesopotamiaException 184 */ 185 public Object getLevelData(String levelName) { 186 synchronized (levelData) { 187 try { 188 Reference<Object> ref = levelData.get(levelName); 189 Object ret = ref==null ? null : ref.get(); 190 if (ret==null) { 191 ret = getLanguage().getLoader(levelName).getData(getId(), null); 192 ref = new SoftReference<Object>(ret); 193 levelData.put(levelName, ref); 194 } 195 return ret; 196 } catch (MesopotamiaException e) { 197 throw new MesopotamiaRuntimeException(e); 198 } 199 } 200 } 201 202 /** 203 * Shows source unit in browser. Use it for debugging. 204 */ 205 public void show() { 206 Visualizable vs = (Visualizable) ConvertingService.convert(this, Visualizable.class); 207 TreeNode root = vs.toTreeNode(null, "Source unit"); 208 209 final Object monitor = new Object(); 210 211 Browser browser = new Browser("Source unit "+getId(), root) { 212 213 protected void processWindowEvent(WindowEvent e) { 214 super.processWindowEvent(e); 215 if (e.getID()==WindowEvent.WINDOW_CLOSED) { 216 synchronized (monitor) { 217 monitor.notifyAll(); 218 } 219 } 220 } 221 }; 222 223 browser.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 224 browser.setVisible(true); 225 226 synchronized (monitor) { 227 try { 228 monitor.wait(); 229 } catch (InterruptedException ex) { 230 // Ignore 231 } 232 } 233 234 } 235 236 private Map<Object, Object> attributes = new HashMap<Object, Object>(); 237 238 public Object getAttribute(Object key) { 239 return attributes.get(key); 240 } 241 242 public Object removeAttribute(Object key) { 243 return attributes.remove(key); 244 } 245 246 public void setAttribute(Object key, Object value) { 247 attributes.put(key, value); 248 } 249 250 /** 251 * Returns renderer to render this source unit to HTML. 252 * @param context Renderer configuration parameters. 253 * @return renderer or null if source unit does not support 254 * rendering. 255 */ 256 public HtmlRenderer getRenderer(Context context) { 257 return null; 258 } 259 }