So I searched all over internet and in every single topic I found this solution for limitting JTextField input.
public class FixedDocument extends PlainDocument {
private int limit;
// optional uppercase conversion
private boolean toUppercase = false;
FixedDocument(int limit) {
super();
this.limit = limit;
}
FixedDocument(int limit, boolean upper) {
super();
this.limit = limit;
toUppercase = upper;
}
public void insertString (int offset, String str, AttributeSet attr) throws BadLocationException {
if (str == null){
return;
}
if ((getLength() + str.length()) <= limit) {
if (toUppercase) str = str.toUpperCase();
super.insertString(offset, str, attr);
}
}
}
but I have a problem with that code. This code line "super.insertString(offset, str, attr);" gives me error:
no suitable method found for insertString(int,java.lanf.String,javax.print.attribute.AttributeSet)
method javax.swing.text.PlainDocument.insertString(int,java.lang.String,javax.text.AttributeSet) is not applicable
(actual argument javax.printattribute.AttributeSet cannot be converted to javax.swing.text.AttributeSet by method invocation conversion)
anyone got any ideas what I am doing wrong here?
Your problem is that your importing the wrong AttributeSet class. You are importing javax.print.attribute.AttributeSet, when you should be importing javax.swing.text.AttributeSet, and the error message pretty much tells you this. Again, myself, I'd use a DocumentFilter for this as that is what it was built for.
Related
Hi I'm writing a test program to reverse a string. When I convert the character array to a string using the toString() method, I get the wrong output. When I try to print the array manually using a for loop without converting it to a string the answer is correct. The code I've written is shown below:
import java.util.*;
public class stringManip {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String str = "This is a string";
System.out.println("String=" +str);
//reverse(s);
char[] c = str.toCharArray();
int left = 0;
int right = str.length() - 1;
for (int i = 0; i < (str.length())/2; i++)
{
char temp = c[left];
c[left++] = c[right];
c[right--] = temp;
}
System.out.print("Reverse="+c.toString());
}
}
I should get the reverse of the string I entered, instead the output am getting is:
String=This is a string
Reverse=[C#45a1472d
Is there something am doing wrong when using the toString() method? Any help is appreciated. Thank you.
Arrays don't override the toString() method. What you're seeing is thus the output of the default Object.toString() implementation, which contains the type of the object ([C means array of chars) followed by its hashCode.
To construct a String from a char array, use
new String(c)
When ever i execute the program the output says not a palindrome when it is a palindrome(only does this when input has spaces or punctuation) can some one tell me where i went wrong in my code?
public class Palindromes
{
public static void main(String[]args)
{
ConsoleIO keyboard=new ConsoleIO();
String word, word2="",terminate;
int length;
do
{
System.out.print("Enter a string:");
word=keyboard.readLine();
word=word.toLowerCase();
word=word.trim();
word=word.replaceAll("\\W", "");
word=word.replaceAll(" ","");
length=word.length();
//finding the reverse of the string
for(int i=length-1;i>=0;i--)
{
word2+=word.charAt(i);
}
//checking to see if the string is a palindrome
if(word.length()==1)
{
System.out.println("The string you entered is not a palindrome");
}
else if(word.equals(word2))
{
System.out.println("The string you entered is a palindrome.");
}
else
{
System.out.println("The string you entered is not a palindrome.");
}
System.out.print("Do you want to continue (yes or no):");
terminate=keyboard.readLine();
System.out.println();
}
while(terminate.equalsIgnoreCase("yes"));
}
}
I think you'd need to account for the punctuation because that will affect the plaindrome test you have. ra.cecar is not otherwise a palindrome. Have you tried adding more lines like the following?
word=word.replaceAll(".", "");
word=word.replaceAll("?", "");
word=word.replaceAll("!", "");
word=word.replaceAll("-", "");
To end all problem to Palindrome, I've made this Java program that will end all suffering to it. It's in Java so you're in luck. It basically strip every non-word character, put it to lower case just with 13 lines. Hope this help haha! Let's hope other guys would get lucky to find this too.
import java.util.Scanner;
public class Palindrome {
public static void main(String[]args){
if(isReverse()){System.out.println("This is a palindrome.");}
else{System.out.print("This is not a palindrome");}
}
public static boolean isReverse(){
Scanner keyboard = new Scanner(System.in);
System.out.print("Please type something: ");
String line = ((keyboard.nextLine()).toLowerCase()).replaceAll("\\W","");
return (line.equals(new StringBuffer(line).reverse().toString()));
}
}
I need to create an Eclipse plugin that displays a tooltip when I hover the mouse over a String literal.
But only if that String literal is the first parameter of a special method.
Here is the Test.java file I use to test my plugin:
package test;
public class Test {
public static void main(String[] args) {
String hello = "Hello";
String world = Translator.get("Test.worldLabel");
System.out.println(hello + " " + world);
}
}
I created a class implementing IJavaEditorTextHover and I need to compile the currently edited Java file to compute if the cursor is hovering a String that needs to be translated or not.
Hovering "Hello" will do nothing.
Hovering "Test.worldLabel" will display my tooltip because that literal is included inside a Translator.get() method call.
At first I used this (170 is inside "Test.worldLabel"):
ITypeRoot typeRoot = (ITypeRoot)
JavaUI.getEditorInputJavaElement(editorPart.getEditorInput());
JavaElement foundElement = (JavaElement) typeRoot.getElementAt(170);
But the foundElement contains the whole main() method: it is not fine-grained enough.
Then, the correct way is, I think:
private static ASTNode parse(ICompilationUnit unit, int position) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(unit);
parser.setResolveBindings(true);
parser.setIgnoreMethodBodies(false);
// TODO Future optimisation: parser.setFocalPosition(position);
return parser.createAST((IProgressMonitor) null); // parse
}
And in my IJavaEditorTextHover.getHoverInfo(...) implementation:
ICompilationUnit compilationUnit = (ICompilationUnit)
JavaUI.getEditorInputJavaElement(editor.getEditorInput())
int position = 170/*hoverRegion.getOffset()*/;
ASTNode ast = parse(compilationUnit, position);
And now, here is my question:
How, from this ast node, do I get the ASTNode reprensenting the StringLiteral at position 170 in the source code (the "Test.worldLabel" String)?
Bonus question: did I choose the right solution? On a performance basis.
Edit:
Well, here is a solution I found:
private StringLiteral findStringLiteralAtPosition(final ASTNode parent, final int position) {
final List<StringLiteral> stringLiterals = new ArrayList<StringLiteral>();
parent.accept(new ASTVisitor() {
#Override
public boolean visit(StringLiteral stringLiteral) {
int start = stringLiteral.getStartPosition();
int end = start + stringLiteral.getLength();
if (start <= position && position <= end) {
stringLiterals.add(stringLiteral);
}
return super.visit(stringLiteral);
}
});
return (stringLiterals.size() > 0 ? stringLiterals.get(0) : null);
}
Does it seam OK?
Or is it an easier way or a more performant one?
One solution will be not using the offset logic at all.
You can generalise the solution by using a node parent check.
Here is a sample code:
public boolean visit(StringLiteral stringLiteral) {
// Check if parent is a method inovacation.
if (stringLiteral.getParent().getNodeType() == ASTNode.METHOD_INVOCATION) {
// get the parent method inovacation.
MethodInvocation miNode = (MethodInvocation) stringLiteral.getParent();
//To do: null and empty check on argument list.
// Check if is the special method and this is the 1st argument
if (miNode.getName().toString().equals("SpecialMethod")
&& miNode.arguments().get(0).toString().equals(stringLiteral.toString())) {
System.out.println("Found it : " + stringLiteral.toString());
}
}
return true;
}
Is there a simple way to make Hibernate Search to index all its values in lower case ? Instead of the default mixed-case.
I'm using the annotation #Field. But I can't seem to be able to configure some application-level set
Fool that I am ! The StandardAnalyzer class is already indexing in lowercase. It's just a matter of setting the search terms in lowercase too. I was assuming the query would do that.
However, if a different analyzer were to be used, application-wide, then it can be set using the property hibernate.search.analyzer.
Lowercasing, term splitting, removing common terms and many more advanced language processing functions are applied by the Analyzer.
Usually you should process user input meant to match indexed strings with the same Analyzer used at indexing; configuring hibernate.search.analyzer sets the default (global) Analyzer, but you can customize it per index, per entity type, per field and even on different entity instances.
It is for example useful to have language specific analysis, so to process Chinese descriptions with Chinese specific routines, Italian descriptions with Italian tokenizers.
The default analyzer is ok for most use cases, and does lowercasing and splits terms on whitespace.
Consider as well that when using the Lucene Queryparser the API requests you the appropriate Analyzer.
When using the Hibernate Search QueryBuilder it attempts to apply the correct Analyzer on each field; see also http://docs.jboss.org/hibernate/search/4.1/reference/en-US/html_single/#search-query-querydsl .
There are multiple way to make sort insensitive in string type field only.
1.First Way is add #Fields annotation in field/property on entity.
Like
#Fields({#Field(index=Index.YES,analyze=Analyze.YES,store=Store.YES),
#Field(index=Index.YES,name = "nameSort",analyzer = #Analyzer(impl=KeywordAnalyzer.class), store = Store.YES)})
private String name;
suppose you have name property with custom analyzer and sort on that. so it's not possible then you can add new Field in index with nameSort apply sort on that field.
you must apply Keyword Analyzer class because that is not tokeniz field and by default apply lowercase factory class in field.
2.Second way is that you can implement your comparison class on sorting like
#Override
public FieldComparator newComparator(String field, int numHits, int sortPos, boolean reversed) throws IOException {
return new StringValComparator(numHits, field);
}
Make one class with extend FieldComparatorSource class and implement above method.
Created new Class name with StringValComparator and implements FieldComparator
and implement following method
class StringValComparator extends FieldComparator {
private String[] values;
private String[] currentReaderValues;
private final String field;
private String bottom;
StringValComparator(int numHits, String field) {
values = new String[numHits];
this.field = field;
}
#Override
public int compare(int slot1, int slot2) {
final String val1 = values[slot1];
final String val2 = values[slot2];
if (val1 == null) {
if (val2 == null) {
return 0;
}
return -1;
} else if (val2 == null) {
return 1;
}
return val1.toLowerCase().compareTo(val2.toLowerCase());
}
#Override
public int compareBottom(int doc) {
final String val2 = currentReaderValues[doc];
if (bottom == null) {
if (val2 == null) {
return 0;
}
return -1;
} else if (val2 == null) {
return 1;
}
return bottom.toLowerCase().compareTo(val2.toLowerCase());
}
#Override
public void copy(int slot, int doc) {
values[slot] = currentReaderValues[doc];
}
#Override
public void setNextReader(IndexReader reader, int docBase) throws IOException {
currentReaderValues = FieldCache.DEFAULT.getStrings(reader, field);
}
#Override
public void setBottom(final int bottom) {
this.bottom = values[bottom];
}
#Override
public String value(int slot) {
return values[slot];
}
}
Apply sorting on Fields Like
new SortField("name",new StringCaseInsensitiveComparator(), true);
I'm trying to implement a caching scheme for my EF Repository similar to the one blogged here. As the author and commenters have reported the limitation is that the key generation method cannot produce cache keys that vary with a given query's parameters. Here is the cache key generation method:
private static string GetKey<T>(IQueryable<T> query)
{
string key = string.Concat(query.ToString(), "\n\r",
typeof(T).AssemblyQualifiedName);
return key;
}
So the following queries will yield the same cache key:
var isActive = true;
var query = context.Products
.OrderBy(one => one.ProductNumber)
.Where(one => one.IsActive == isActive).AsCacheable();
and
var isActive = false;
var query = context.Products
.OrderBy(one => one.ProductNumber)
.Where(one => one.IsActive == isActive).AsCacheable();
Notice that the only difference is that isActive = true in the first query and isActive = false in the second.
Any suggestions/insight to efficiently generating cache keys which vary by IQueryable parameters would be truly appreciated.
Kudos to Sergey Barskiy for sharing the EF CodeFirst caching scheme.
Update
I took the approach of traversing the IQueryable's expression tree myself with the goal of resolving the values of the parameters used in the query. With maxlego's suggestion, I extended the System.Linq.Expressions.ExpressionVisitor class to visit the expression nodes that we're interested in - in this case, the MemberExpression. The updated GetKey method looks something like this:
public static string GetKey<T>(IQueryable<T> query)
{
var keyBuilder = new StringBuilder(query.ToString());
var queryParamVisitor = new QueryParameterVisitor(keyBuilder);
queryParamVisitor.GetQueryParameters(query.Expression);
keyBuilder.Append("\n\r");
keyBuilder.Append(typeof (T).AssemblyQualifiedName);
return keyBuilder.ToString();
}
And the QueryParameterVisitor class, which was inspired by the answers of Bryan Watts and Marc Gravell to this question, looks like this:
/// <summary>
/// <see cref="ExpressionVisitor"/> subclass which encapsulates logic to
/// traverse an expression tree and resolve all the query parameter values
/// </summary>
internal class QueryParameterVisitor : ExpressionVisitor
{
public QueryParameterVisitor(StringBuilder sb)
{
QueryParamBuilder = sb;
Visited = new Dictionary<int, bool>();
}
protected StringBuilder QueryParamBuilder { get; set; }
protected Dictionary<int, bool> Visited { get; set; }
public StringBuilder GetQueryParameters(Expression expression)
{
Visit(expression);
return QueryParamBuilder;
}
private static object GetMemberValue(MemberExpression memberExpression, Dictionary<int, bool> visited)
{
object value;
if (!TryGetMemberValue(memberExpression, out value, visited))
{
UnaryExpression objectMember = Expression.Convert(memberExpression, typeof (object));
Expression<Func<object>> getterLambda = Expression.Lambda<Func<object>>(objectMember);
Func<object> getter = null;
try
{
getter = getterLambda.Compile();
}
catch (InvalidOperationException)
{
}
if (getter != null) value = getter();
}
return value;
}
private static bool TryGetMemberValue(Expression expression, out object value, Dictionary<int, bool> visited)
{
if (expression == null)
{
// used for static fields, etc
value = null;
return true;
}
// Mark this node as visited (processed)
int expressionHash = expression.GetHashCode();
if (!visited.ContainsKey(expressionHash))
{
visited.Add(expressionHash, true);
}
// Get Member Value, recurse if necessary
switch (expression.NodeType)
{
case ExpressionType.Constant:
value = ((ConstantExpression) expression).Value;
return true;
case ExpressionType.MemberAccess:
var me = (MemberExpression) expression;
object target;
if (TryGetMemberValue(me.Expression, out target, visited))
{
// instance target
switch (me.Member.MemberType)
{
case MemberTypes.Field:
value = ((FieldInfo) me.Member).GetValue(target);
return true;
case MemberTypes.Property:
value = ((PropertyInfo) me.Member).GetValue(target, null);
return true;
}
}
break;
}
// Could not retrieve value
value = null;
return false;
}
protected override Expression VisitMember(MemberExpression node)
{
// Only process nodes that haven't been processed before, this could happen because our traversal
// is depth-first and will "visit" the nodes in the subtree before this method (VisitMember) does
if (!Visited.ContainsKey(node.GetHashCode()))
{
object value = GetMemberValue(node, Visited);
if (value != null)
{
QueryParamBuilder.Append("\n\r");
QueryParamBuilder.Append(value.ToString());
}
}
return base.VisitMember(node);
}
}
I'm still doing some performance profiling on the cache key generation and hoping that it isn't too expensive (I'll update the question with the results once I have them). I'll leave the question open, in case anyone has suggestions on how to optimize this process or has a recommendation for a more efficient method for generating cache keys with vary with the query parameters. Although this method produces the desired output, it is by no means optimal.
i suggest to use ExpressionVisitor
http://msdn.microsoft.com/en-us/library/bb882521(v=vs.90).aspx
Just for the record, "Caching the results of LINQ queries" works well with the EF and it's able to work with parameters correctly, so it can be considered as a good second level cache implementation for EF.
While the solution of the OP works quite well, I found that the performance of the solution is a little bit poor.
The duration of the key generation varied between 300ms and 1200ms for my queries.
However, I've found another solution that has quite better performance (<10ms).
public static string ToTraceString<T>(DbQuery<T> query)
{
var internalQueryField = query.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(f => f.Name.Equals("_internalQuery")).FirstOrDefault();
var internalQuery = internalQueryField.GetValue(query);
var objectQueryField = internalQuery.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(f => f.Name.Equals("_objectQuery")).FirstOrDefault();
var objectQuery = objectQueryField.GetValue(internalQuery) as ObjectQuery<T>;
return ToTraceStringWithParameters(objectQuery);
}
private static string ToTraceStringWithParameters<T>(ObjectQuery<T> query)
{
string traceString = query.ToTraceString() + "\n";
foreach (var parameter in query.Parameters)
{
traceString += parameter.Name + " [" + parameter.ParameterType.FullName + "] = " + parameter.Value + "\n";
}
return traceString;
}