1 /*
2  * Packages.java
3  *
4  * Copyright (C) 2002-2007 Peter Graves <peter@armedbear.org>
5  * $Id$
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *
21  * As a special exception, the copyright holders of this library give you
22  * permission to link this library with independent modules to produce an
23  * executable, regardless of the license terms of these independent
24  * modules, and to copy and distribute the resulting executable under
25  * terms of your choice, provided that you also meet, for each linked
26  * independent module, the terms and conditions of the license of that
27  * module.  An independent module is a module which is not derived from
28  * or based on this library.  If you modify this library, you may extend
29  * this exception to your version of the library, but you are not
30  * obligated to do so.  If you do not wish to do so, delete this
31  * exception statement from your version.
32  */
33 
34 package org.armedbear.lisp;
35 
36 import static org.armedbear.lisp.Lisp.*;
37 
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.Iterator;
41 import java.util.List;
42 
43 public final class Packages
44 {
45   private static final ArrayList<Package> packages = new ArrayList<Package>();
46   private static final HashMap<String,Package> map = new HashMap<String,Package>();
47 
createPackage(String name)48   public static final synchronized Package createPackage(String name)
49   {
50     return createPackage(name, 0);
51   }
52 
createPackage(String name, int size)53   public static final synchronized Package createPackage(String name, int size)
54   {
55     Package pkg = (Package) map.get(name);
56     if (pkg == null)
57       {
58         pkg = size != 0 ? new Package(name, size) : new Package(name);
59         packages.add(pkg);
60         map.put(name, pkg);
61       }
62     else
63       Debug.trace("package " + name + " already exists");
64     return pkg;
65   }
66 
addPackage(Package pkg)67   public static final synchronized void addPackage(Package pkg)
68 
69   {
70     final String name = pkg.getName();
71     if (map.get(name) != null)
72       {
73         error(new LispError("A package named " + name + " already exists."));
74         return;
75       }
76     packages.add(pkg);
77     map.put(name, pkg);
78     List nicknames = pkg.getNicknames();
79     if (nicknames != null)
80       {
81         for (Iterator it = nicknames.iterator(); it.hasNext();)
82           {
83             String nickname = (String) it.next();
84             addNickname(pkg, nickname);
85           }
86       }
87   }
88 
89   /**
90       Returns the current package of the current LispThread.
91 
92       Intended to be used from Java code manipulating an Interpreter
93       instance.
94   */
findPackage(String name)95   public static final synchronized Package findPackage(String name) {
96     return getCurrentPackage().findPackage(name);
97   }
98 
99   // Finds package named `name'.  Returns null if package doesn't exist.
100   // Called by Package.findPackage after checking package-local package
101   // nicknames.
findPackageGlobally(String name)102   static final synchronized Package findPackageGlobally(String name)
103   {
104     return (Package) map.get(name);
105   }
106 
makePackage(String name)107   public static final synchronized Package makePackage(String name)
108 
109   {
110     if (map.get(name) != null)
111       {
112         error(new LispError("A package named " + name + " already exists."));
113         // Not reached.
114         return null;
115       }
116     Package pkg = new Package(name);
117     packages.add(pkg);
118     map.put(name, pkg);
119     return pkg;
120   }
121 
addNickname(Package pkg, String nickname)122   public static final synchronized void addNickname(Package pkg, String nickname)
123 
124   {
125     Object obj = map.get(nickname);
126     if (obj != null && obj != pkg)
127       {
128         error(new PackageError("A package named " + nickname + " already exists.", new SimpleString(nickname)));
129         return;
130       }
131     map.put(nickname, pkg);
132   }
133 
134   // Removes name and nicknames from map, removes pkg from packages.
deletePackage(Package pkg)135   public static final synchronized boolean deletePackage(Package pkg)
136   {
137     String name = pkg.getName();
138     if (name != null)
139       {
140         map.remove(name);
141         List nicknames = pkg.getNicknames();
142         if (nicknames != null)
143           {
144             for (Iterator it = nicknames.iterator(); it.hasNext();)
145               {
146                 String nickname = (String) it.next();
147                 map.remove(nickname);
148               }
149           }
150         packages.remove(pkg);
151         return true;
152       }
153     return false;
154   }
155 
listAllPackages()156   public static final synchronized LispObject listAllPackages()
157   {
158     LispObject result = NIL;
159     for (Package pkg : packages) {
160       result = new Cons(pkg, result);
161     }
162     return result;
163   }
164 
getAllPackages()165   public static final synchronized Package[] getAllPackages()
166   {
167     Package[] array = new Package[packages.size()];
168     packages.toArray(array);
169     return array;
170   }
171 
getPackagesNicknamingPackage(Package thePackage)172   public static final synchronized LispObject getPackagesNicknamingPackage(Package thePackage)
173   {
174     LispObject result = NIL;
175     for (Package pkg : packages) {
176       for (Package nicknamedPackage : pkg.getLocallyNicknamedPackages()) {
177         if (thePackage.equals(nicknamedPackage)) {
178           result = new Cons(pkg, result);
179         }
180       }
181     }
182     return result;
183   }
184 }
185