1 /***************************************************************************************
2 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.expression.regexp;
9
10 import org.codehaus.aspectwerkz.expression.ExpressionException;
11 import org.codehaus.aspectwerkz.expression.SubtypePatternType;
12 import org.codehaus.aspectwerkz.util.Strings;
13
14 import java.io.ObjectInputStream;
15
16 /***
17 * Implements the regular expression pattern matcher for types.
18 *
19 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
20 */
21 public class TypePattern extends Pattern {
22 /***
23 * The fully qualified type name.
24 */
25 protected transient com.karneim.util.collection.regex.Pattern m_typeNamePattern;
26
27 /***
28 * The pattern as a string.
29 */
30 protected String m_pattern;
31
32 /***
33 * The subtype pattern type.
34 */
35 private SubtypePatternType m_subtypePatternType;
36
37 /***
38 * Private constructor.
39 *
40 * @param pattern the pattern
41 * @param subtypePatternType the subtype pattern type
42 */
43 TypePattern(final String pattern, final SubtypePatternType subtypePatternType) {
44 m_pattern = pattern;
45 m_subtypePatternType = subtypePatternType;
46 escape(m_pattern);
47 }
48
49 /***
50 * Matches a type name.
51 *
52 * @param typeName the name of the type
53 * @return true if we have a matche
54 */
55 public boolean matches(final String typeName) {
56 if (typeName == null) {
57 throw new IllegalArgumentException("type name can not be null");
58 }
59 if (typeName.equals("")) {
60 return false;
61 }
62 return m_typeNamePattern.contains(typeName);
63 }
64
65 /***
66 * Returns the subtype pattern type
67 *
68 * @return boolean
69 */
70 public SubtypePatternType getSubtypePatternType() {
71 return m_subtypePatternType;
72 }
73
74 /***
75 * Checks if the pattern matches all types.
76 *
77 * @return boolean
78 */
79 public boolean isEagerWildCard() {
80 return m_pattern.equals(EAGER_WILDCARD);
81 }
82
83 /***
84 * Returns the pattern as a string.
85 *
86 * @return the pattern
87 */
88 public String getPattern() {
89 return m_pattern;
90 }
91
92 /***
93 * Escapes the type pattern.
94 *
95 * @param pattern the method pattern
96 */
97 protected void escape(final String pattern) {
98 String typeName = pattern;
99 if (ABBREVIATIONS.containsKey(pattern)) {
100 typeName = (String) ABBREVIATIONS.get(pattern);
101 }
102 try {
103 if (typeName.equals(REGULAR_WILDCARD) || typeName.equals(EAGER_WILDCARD)) {
104 typeName = "[a-zA-Z0-9_$.//[//]]+";
105 } else {
106
107 typeName = Strings.replaceSubString(typeName, "[", "//[");
108 typeName = Strings.replaceSubString(typeName, "]", "//]");
109 typeName = Strings.replaceSubString(typeName, "..", "[a-zA-Z0-9_$.]+");
110 typeName = Strings.replaceSubString(typeName, ".", "//.");
111 typeName = Strings.replaceSubString(typeName, "*", "[a-zA-Z0-9_$//[//]]*");
112 }
113 m_typeNamePattern = new com.karneim.util.collection.regex.Pattern(typeName);
114 } catch (Throwable e) {
115 throw new ExpressionException("type pattern is not well formed: " + pattern, e);
116 }
117 }
118
119 /***
120 * Provides custom deserialization.
121 *
122 * @param stream the object input stream containing the serialized object
123 * @throws Exception in case of failure
124 */
125 private void readObject(final ObjectInputStream stream) throws Exception {
126 ObjectInputStream.GetField fields = stream.readFields();
127 m_pattern = (String) fields.get("m_pattern", null);
128 escape(m_pattern);
129 }
130
131 public int hashCode() {
132 int result = 17;
133 result = (37 * result) + hashCodeOrZeroIfNull(m_pattern);
134 result = (37 * result) + hashCodeOrZeroIfNull(m_typeNamePattern);
135 return result;
136 }
137
138 protected static int hashCodeOrZeroIfNull(final Object o) {
139 if (null == o) {
140 return 19;
141 }
142 return o.hashCode();
143 }
144
145 public boolean equals(final Object o) {
146 if (this == o) {
147 return true;
148 }
149 if (!(o instanceof TypePattern)) {
150 return false;
151 }
152 final TypePattern obj = (TypePattern) o;
153 return areEqualsOrBothNull(obj.m_pattern, this.m_pattern)
154 && areEqualsOrBothNull(obj.m_typeNamePattern, this.m_typeNamePattern);
155 }
156
157 protected static boolean areEqualsOrBothNull(final Object o1, final Object o2) {
158 if (null == o1) {
159 return (null == o2);
160 }
161 return o1.equals(o2);
162 }
163 }