📄 variable.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Variable.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.database.variable;import com.sun.electric.database.IdMapper;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.id.ArcProtoId;import com.sun.electric.database.id.CellId;import com.sun.electric.database.id.ExportId;import com.sun.electric.database.id.IdReader;import com.sun.electric.database.id.IdWriter;import com.sun.electric.database.id.LibId;import com.sun.electric.database.id.PrimitiveNodeId;import com.sun.electric.database.id.TechId;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.technology.technologies.Generic;import com.sun.electric.tool.Tool;import com.sun.electric.tool.user.ActivityLogger;import java.io.IOException;import java.io.Serializable;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;/** * The Variable immutable class defines a single attribute-value pair that can be attached to any ElectricObject. * <P> * This immutable class is thread-safe. */public class Variable implements Serializable{ /** * The Key class caches Variable names. */ public static class Key implements Comparable<Key> { private final String name; /** * Method to create a new Key object with the specified name. * @param name the name of the Variable. * @throws NullPointerException if name is null. */ private Key(String name) { if (name == null) throw new NullPointerException(); this.name = name; } /** * Method to return the name of this Key object. * @return the name of this Key object. */ public String getName() { return name; } /** * Method to return if this Variable.Key is a User Attribute. * @return true if this Variable.Key is an attribute, false otherwise. */ public boolean isAttribute() { return false; } /** * Compares Variable Keys by their names. * @param that the other Variable Key. * @return a comparison between the Variable Keys. */ public int compareTo(Key that) { return TextUtils.STRING_NUMBER_ORDER.compare(name, that.name); } /** * Returns a printable version of this Key. * @return a printable version of this Key. */ @Override public String toString() { return name; } /** * Print statistics about Variable Keys. */ public static void printStatistics() { long keyLength = 0; for (Key key: varKeys.values()) keyLength += key.getName().length(); int canonicCount = 0; long canonicLength = 0; for (String canonic: varCanonicKeys.keySet()) { Key key = varCanonicKeys.get(canonic); if (key != null && key.getName() == canonic) continue; canonicCount++; canonicLength += canonic.length(); } System.out.println(varKeys.size() + " variable keys with " + keyLength + " chars." + " Canonic " + varCanonicKeys.size() + " entries " + canonicCount + " strings with " + canonicLength + " chars."); } } /** * The Key class caches attribute Variable names. */ public static class AttrKey extends Key { AttrKey(String name) { super(name); } /** * Method to return if this Variable.Key is a User Attribute. * @return true if this Variable.Key is an attribute, false otherwise. */ @Override public boolean isAttribute() { return true; } } /** a list of all variable keys */ private static final HashMap<String,Key> varKeys = new HashMap<String,Key>(); /** all variable keys addressed by lower case name */ private static final HashMap<String,Key> varCanonicKeys = new HashMap<String,Key>(); /** * Method to return the Key object for a given Variable name. * Variable Key objects are caches of the actual string name of the Variable. * @return the Key object for a given Variable name. */ public static synchronized Key findKey(String name) { Key key = varKeys.get(name); if (key != null) return key; if (varKeys.containsKey(name)) return null; name = name.intern(); varKeys.put(name, null); String canonicName = TextUtils.canonicString(name); key = varCanonicKeys.get(canonicName); if (key != null) { String msg = "WARNING: Variable \"" + name + "\" not found though variable \"" + key.getName() + "\" exists"; ActivityLogger.logMessage(msg); System.out.println(msg); } return null; } /** * Method to find or create the Key object for a given Variable name. * Variable Key objects are caches of the actual string name of the Variable. * @param name given Variable name. * @return the Key object for a given Variable name. */ public static synchronized Key newKey(String name) { Key key = varKeys.get(name); if (key != null) return key; return newKey(name, null); } /** * Method to find or create the Key object for a given Variable name. * Variable Key objects are caches of the actual string name of the Variable. * @param name given Variable name. * @param parent the object on which this Variable key will reside. * @return the Key object for a given Variable name. */ public static synchronized Key newKey(String name, ElectricObject parent) { Key key = varKeys.get(name); if (key != null) return key; name = name.intern(); key = name.startsWith("ATTR_") ? new AttrKey(name) : new Key(name); varKeys.put(name, key); String canonicName = TextUtils.canonicString(name); Key key2 = varCanonicKeys.get(canonicName); if (key2 != null) { // find examples of these two variables String ex = null; for(Library lib : Library.getVisibleLibraries()) { if (ex == null) ex = findVariable(lib, key2); for(Iterator<Cell> cIt = lib.getCells(); cIt.hasNext(); ) { Cell cell = cIt.next(); if (ex == null) ex = findVariable(cell, key2); for(Iterator<NodeInst> nIt = cell.getNodes(); nIt.hasNext(); ) { NodeInst ni = nIt.next(); if (ex == null) ex = findVariable(ni, key2); } for(Iterator<ArcInst> aIt = cell.getArcs(); aIt.hasNext(); ) { ArcInst ai = aIt.next(); if (ex == null) ex = findVariable(ai, key2); } for(Iterator<Export> eIt = cell.getExports(); eIt.hasNext(); ) { Export e = eIt.next(); if (ex == null) ex = findVariable(e, key2); } } } String msg = "WARNING: Variables with similar names are used: \"" + name + "\""; if (parent != null) msg += " (on " + getObjectName(parent) + ")"; msg += " and \"" + key2.getName() + "\""; if (ex != null) msg += " (on " + ex + ")"; ActivityLogger.logMessage(msg); System.out.println(msg); } else { varCanonicKeys.put(canonicName.intern(), key); } return key; } private static String findVariable(ElectricObject eObj, Key key) { for(Iterator<Variable> it = eObj.getParametersAndVariables(); it.hasNext(); ) { Variable var = it.next(); if (var.getKey() == key) return getObjectName(eObj); } return null; } private static String getObjectName(ElectricObject eObj) { if (eObj instanceof Library) return "Library " + ((Library)eObj).getName(); if (eObj instanceof Cell) return "Cell " + ((Cell)eObj).describe(false); if (eObj instanceof Export) return "Export " + ((Export)eObj).getName() + " in Cell " + ((Export)eObj).getParent().describe(false); if (eObj instanceof NodeInst) return "Node " + ((NodeInst)eObj).describe(false) + " in Cell " + ((NodeInst)eObj).getParent().describe(false); if (eObj instanceof ArcInst) return "Arc " + ((ArcInst)eObj).describe(false) + " in Cell " + ((ArcInst)eObj).getParent().describe(false); return eObj.toString(); } /** empty array of Variables. */ public static final Variable[] NULL_ARRAY = {}; /** type if value. */ private final static byte ARRAY = 1; private final static byte LIBRARY = 2; private final static byte CELL = 4; private final static byte EXPORT = 6; private final static byte STRING = 8; private final static byte CODE = 10; private final static byte DOUBLE = 12; private final static byte FLOAT = 14; private final static byte LONG = 16; private final static byte INTEGER = 18; private final static byte SHORT = 20; private final static byte BYTE = 22; private final static byte BOOLEAN = 24; private final static byte EPOINT = 26; private final static byte TOOL = 28; private final static byte TECHNOLOGY = 30; private final static byte PRIM_NODE = 32; private final static byte ARC_PROTO = 34; /** Valid type of value. */ private static final HashMap<Class,Byte> validClasses = new HashMap<Class,Byte>(); static { validClasses.put(LibId.class, Byte.valueOf(LIBRARY)); validClasses.put(CellId.class, Byte.valueOf(CELL)); validClasses.put(ExportId.class, Byte.valueOf(EXPORT)); validClasses.put(String.class, Byte.valueOf(STRING)); validClasses.put(CodeExpression.class, Byte.valueOf(CODE)); validClasses.put(Double.class, Byte.valueOf(DOUBLE)); validClasses.put(Float.class, Byte.valueOf(FLOAT)); validClasses.put(Long.class, Byte.valueOf(LONG)); validClasses.put(Integer.class, Byte.valueOf(INTEGER)); validClasses.put(Short.class, Byte.valueOf(SHORT)); validClasses.put(Byte.class, Byte.valueOf(BYTE)); validClasses.put(Boolean.class, Byte.valueOf(BOOLEAN)); validClasses.put(EPoint.class, Byte.valueOf(EPOINT)); validClasses.put(Tool.class, Byte.valueOf(TOOL)); validClasses.put(TechId.class, Byte.valueOf(TECHNOLOGY)); validClasses.put(PrimitiveNodeId.class, Byte.valueOf(PRIM_NODE)); validClasses.put(ArcProtoId.class, Byte.valueOf(ARC_PROTO)); } /** key of this Variable. */ private final Key key; /** Value of this Variable. */ private final Object value; /** Text descriptor of this Variable. */ private final TextDescriptor descriptor; private final byte type; /** * Constructor of Variable. * @param key key of this Variable. * @param descriptor text descriptor of this Variable. * @param value value of this Variable. * @param type type of the value */ private Variable(Key key, Object value, TextDescriptor descriptor, byte type) { this.key = key; this.value = value; this.descriptor = descriptor; this.type = type; check(true, true); } /** * Returns new Variable. * @param key key of this Variable. * @param value value of this Variable. * @param descriptor text descriptor of this Variable. * @return new Variable object. * @throws NullPointerException if key, descriptor or value is null. * @throws IllegalArgumentException if value has invalid type */ public static Variable newInstance(Variable.Key key, Object value, TextDescriptor descriptor) { if (key == null) throw new NullPointerException("key"); if (descriptor == null) throw new NullPointerException("descriptor"); if (!key.isAttribute()) descriptor = descriptor.withParam(false); byte type = getObjectType(value); if ((type & ARRAY) != 0) value = ((Object[])value).clone(); return new Variable(key, value, descriptor, type); } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -